Ninja
|
00001 // Copyright 2011 Google Inc. All Rights Reserved. 00002 // 00003 // Licensed under the Apache License, Version 2.0 (the "License"); 00004 // you may not use this file except in compliance with the License. 00005 // You may obtain a copy of the License at 00006 // 00007 // http://www.apache.org/licenses/LICENSE-2.0 00008 // 00009 // Unless required by applicable law or agreed to in writing, software 00010 // distributed under the License is distributed on an "AS IS" BASIS, 00011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 // See the License for the specific language governing permissions and 00013 // limitations under the License. 00014 00015 #include "test.h" 00016 00017 #include <algorithm> 00018 00019 #include <errno.h> 00020 00021 #include "build_log.h" 00022 #include "manifest_parser.h" 00023 #include "util.h" 00024 00025 #ifdef _WIN32 00026 #include <windows.h> 00027 #endif 00028 00029 namespace { 00030 00031 #ifdef _WIN32 00032 #ifndef _mktemp_s 00033 /// mingw has no mktemp. Implement one with the same type as the one 00034 /// found in the Windows API. 00035 int _mktemp_s(char* templ) { 00036 char* ofs = strchr(templ, 'X'); 00037 sprintf(ofs, "%d", rand() % 1000000); 00038 return 0; 00039 } 00040 #endif 00041 00042 /// Windows has no mkdtemp. Implement it in terms of _mktemp_s. 00043 char* mkdtemp(char* name_template) { 00044 int err = _mktemp_s(name_template); 00045 if (err < 0) { 00046 perror("_mktemp_s"); 00047 return NULL; 00048 } 00049 00050 err = _mkdir(name_template); 00051 if (err < 0) { 00052 perror("mkdir"); 00053 return NULL; 00054 } 00055 00056 return name_template; 00057 } 00058 #endif // _WIN32 00059 00060 string GetSystemTempDir() { 00061 #ifdef _WIN32 00062 char buf[1024]; 00063 if (!GetTempPath(sizeof(buf), buf)) 00064 return ""; 00065 return buf; 00066 #else 00067 const char* tempdir = getenv("TMPDIR"); 00068 if (tempdir) 00069 return tempdir; 00070 return "/tmp"; 00071 #endif 00072 } 00073 00074 } // anonymous namespace 00075 00076 StateTestWithBuiltinRules::StateTestWithBuiltinRules() { 00077 AddCatRule(&state_); 00078 } 00079 00080 void StateTestWithBuiltinRules::AddCatRule(State* state) { 00081 AssertParse(state, 00082 "rule cat\n" 00083 " command = cat $in > $out\n"); 00084 } 00085 00086 Node* StateTestWithBuiltinRules::GetNode(const string& path) { 00087 return state_.GetNode(path); 00088 } 00089 00090 void AssertParse(State* state, const char* input) { 00091 ManifestParser parser(state, NULL); 00092 string err; 00093 ASSERT_TRUE(parser.ParseTest(input, &err)) << err; 00094 ASSERT_EQ("", err); 00095 } 00096 00097 void AssertHash(const char* expected, uint64_t actual) { 00098 ASSERT_EQ(BuildLog::LogEntry::HashCommand(expected), actual); 00099 } 00100 00101 void VirtualFileSystem::Create(const string& path, 00102 const string& contents) { 00103 files_[path].mtime = now_; 00104 files_[path].contents = contents; 00105 files_created_.insert(path); 00106 } 00107 00108 TimeStamp VirtualFileSystem::Stat(const string& path) { 00109 FileMap::iterator i = files_.find(path); 00110 if (i != files_.end()) 00111 return i->second.mtime; 00112 return 0; 00113 } 00114 00115 bool VirtualFileSystem::WriteFile(const string& path, const string& contents) { 00116 Create(path, contents); 00117 return true; 00118 } 00119 00120 bool VirtualFileSystem::MakeDir(const string& path) { 00121 directories_made_.push_back(path); 00122 return true; // success 00123 } 00124 00125 string VirtualFileSystem::ReadFile(const string& path, string* err) { 00126 files_read_.push_back(path); 00127 FileMap::iterator i = files_.find(path); 00128 if (i != files_.end()) 00129 return i->second.contents; 00130 return ""; 00131 } 00132 00133 int VirtualFileSystem::RemoveFile(const string& path) { 00134 if (find(directories_made_.begin(), directories_made_.end(), path) 00135 != directories_made_.end()) 00136 return -1; 00137 FileMap::iterator i = files_.find(path); 00138 if (i != files_.end()) { 00139 files_.erase(i); 00140 files_removed_.insert(path); 00141 return 0; 00142 } else { 00143 return 1; 00144 } 00145 } 00146 00147 void ScopedTempDir::CreateAndEnter(const string& name) { 00148 // First change into the system temp dir and save it for cleanup. 00149 start_dir_ = GetSystemTempDir(); 00150 if (start_dir_.empty()) 00151 Fatal("couldn't get system temp dir"); 00152 if (chdir(start_dir_.c_str()) < 0) 00153 Fatal("chdir: %s", strerror(errno)); 00154 00155 // Create a temporary subdirectory of that. 00156 char name_template[1024]; 00157 strcpy(name_template, name.c_str()); 00158 strcat(name_template, "-XXXXXX"); 00159 char* tempname = mkdtemp(name_template); 00160 if (!tempname) 00161 Fatal("mkdtemp: %s", strerror(errno)); 00162 temp_dir_name_ = tempname; 00163 00164 // chdir into the new temporary directory. 00165 if (chdir(temp_dir_name_.c_str()) < 0) 00166 Fatal("chdir: %s", strerror(errno)); 00167 } 00168 00169 void ScopedTempDir::Cleanup() { 00170 if (temp_dir_name_.empty()) 00171 return; // Something went wrong earlier. 00172 00173 // Move out of the directory we're about to clobber. 00174 if (chdir(start_dir_.c_str()) < 0) 00175 Fatal("chdir: %s", strerror(errno)); 00176 00177 #ifdef _WIN32 00178 string command = "rmdir /s /q " + temp_dir_name_; 00179 #else 00180 string command = "rm -rf " + temp_dir_name_; 00181 #endif 00182 if (system(command.c_str()) < 0) 00183 Fatal("system: %s", strerror(errno)); 00184 00185 temp_dir_name_.clear(); 00186 }