Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 229 lines (196 sloc) 6.238 kb
2f3e566 @martine move test support into test.*
authored
1 // Copyright 2011 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
ac047b1 @nico Fix building tests on Windows again.
nico authored
15 #ifdef _WIN32
16 #include <direct.h> // Has to be before util.h is included.
17 #endif
18
2f3e566 @martine move test support into test.*
authored
19 #include "test.h"
20
8476164 @doctorlove Include <algorithm> for std::find in test.cc
doctorlove authored
21 #include <algorithm>
22
36660e4 @martine migrate tempdir code to test.cc
authored
23 #include <errno.h>
d634414 @doctorlove GetTempPath() needs windows.h
doctorlove authored
24 #ifdef _WIN32
25 #include <windows.h>
b2fe56c @nico Use a small, standalone testing framework instead of googletest.
nico authored
26 #else
27 #include <unistd.h>
d634414 @doctorlove GetTempPath() needs windows.h
doctorlove authored
28 #endif
29
ac047b1 @nico Fix building tests on Windows again.
nico authored
30 #include "build_log.h"
56e9d08 @nico Build self-consistent graphs for dupe edges with multiple outputs.
nico authored
31 #include "graph.h"
ac047b1 @nico Fix building tests on Windows again.
nico authored
32 #include "manifest_parser.h"
33 #include "util.h"
34
36660e4 @martine migrate tempdir code to test.cc
authored
35 namespace {
36
37 #ifdef _WIN32
38 #ifndef _mktemp_s
39 /// mingw has no mktemp. Implement one with the same type as the one
40 /// found in the Windows API.
41 int _mktemp_s(char* templ) {
42 char* ofs = strchr(templ, 'X');
43 sprintf(ofs, "%d", rand() % 1000000);
44 return 0;
45 }
46 #endif
47
48 /// Windows has no mkdtemp. Implement it in terms of _mktemp_s.
49 char* mkdtemp(char* name_template) {
50 int err = _mktemp_s(name_template);
51 if (err < 0) {
52 perror("_mktemp_s");
53 return NULL;
54 }
55
56 err = _mkdir(name_template);
57 if (err < 0) {
58 perror("mkdir");
59 return NULL;
60 }
61
62 return name_template;
63 }
faac236 @martine windows: use _WIN32 define everywhere
authored
64 #endif // _WIN32
36660e4 @martine migrate tempdir code to test.cc
authored
65
66 string GetSystemTempDir() {
67 #ifdef _WIN32
68 char buf[1024];
69 if (!GetTempPath(sizeof(buf), buf))
70 return "";
71 return buf;
72 #else
73 const char* tempdir = getenv("TMPDIR");
74 if (tempdir)
75 return tempdir;
76 return "/tmp";
77 #endif
78 }
79
80 } // anonymous namespace
2f3e566 @martine move test support into test.*
authored
81
82 StateTestWithBuiltinRules::StateTestWithBuiltinRules() {
0397155 @martine add a test for the "deps out of date" case
authored
83 AddCatRule(&state_);
84 }
85
86 void StateTestWithBuiltinRules::AddCatRule(State* state) {
87 AssertParse(state,
2f3e566 @martine move test support into test.*
authored
88 "rule cat\n"
89 " command = cat $in > $out\n");
90 }
91
92 Node* StateTestWithBuiltinRules::GetNode(const string& path) {
c475064 @sgraham make all GetNode explicit, add DepsLog canonicalize test
sgraham authored
93 EXPECT_FALSE(strpbrk(path.c_str(), "/\\"));
94 return state_.GetNode(path, 0);
2f3e566 @martine move test support into test.*
authored
95 }
96
97 void AssertParse(State* state, const char* input) {
98 ManifestParser parser(state, NULL);
99 string err;
b2fe56c @nico Use a small, standalone testing framework instead of googletest.
nico authored
100 EXPECT_TRUE(parser.ParseTest(input, &err));
2f3e566 @martine move test support into test.*
authored
101 ASSERT_EQ("", err);
56e9d08 @nico Build self-consistent graphs for dupe edges with multiple outputs.
nico authored
102 VerifyGraph(*state);
2f3e566 @martine move test support into test.*
authored
103 }
37a9390 @martine move VirtualFileSystem into test.*
authored
104
5be83d0 @nico Only store command hashes in the build log.
nico authored
105 void AssertHash(const char* expected, uint64_t actual) {
106 ASSERT_EQ(BuildLog::LogEntry::HashCommand(expected), actual);
107 }
108
56e9d08 @nico Build self-consistent graphs for dupe edges with multiple outputs.
nico authored
109 void VerifyGraph(const State& state) {
110 for (vector<Edge*>::const_iterator e = state.edges_.begin();
111 e != state.edges_.end(); ++e) {
112 // All edges need at least one output.
113 EXPECT_FALSE((*e)->outputs_.empty());
f5c5789 @nico Another crash fix for duplicate edges. Fixes #939.
nico authored
114 // Check that the edge's inputs have the edge as out-edge.
56e9d08 @nico Build self-consistent graphs for dupe edges with multiple outputs.
nico authored
115 for (vector<Node*>::const_iterator in_node = (*e)->inputs_.begin();
116 in_node != (*e)->inputs_.end(); ++in_node) {
117 const vector<Edge*>& out_edges = (*in_node)->out_edges();
118 EXPECT_NE(std::find(out_edges.begin(), out_edges.end(), *e),
119 out_edges.end());
120 }
f5c5789 @nico Another crash fix for duplicate edges. Fixes #939.
nico authored
121 // Check that the edge's outputs have the edge as in-edge.
56e9d08 @nico Build self-consistent graphs for dupe edges with multiple outputs.
nico authored
122 for (vector<Node*>::const_iterator out_node = (*e)->outputs_.begin();
123 out_node != (*e)->outputs_.end(); ++out_node) {
124 EXPECT_EQ((*out_node)->in_edge(), *e);
125 }
126 }
f5c5789 @nico Another crash fix for duplicate edges. Fixes #939.
nico authored
127
128 // The union of all in- and out-edges of each nodes should be exactly edges_.
129 set<const Edge*> node_edge_set;
130 for (State::Paths::const_iterator p = state.paths_.begin();
131 p != state.paths_.end(); ++p) {
132 const Node* n = p->second;
133 if (n->in_edge())
134 node_edge_set.insert(n->in_edge());
135 node_edge_set.insert(n->out_edges().begin(), n->out_edges().end());
136 }
137 set<const Edge*> edge_set(state.edges_.begin(), state.edges_.end());
138 EXPECT_EQ(node_edge_set, edge_set);
56e9d08 @nico Build self-consistent graphs for dupe edges with multiple outputs.
nico authored
139 }
140
29e76bc @martine move test virtual time "now_" into VirtualFileSystem
authored
141 void VirtualFileSystem::Create(const string& path,
37a9390 @martine move VirtualFileSystem into test.*
authored
142 const string& contents) {
29e76bc @martine move test virtual time "now_" into VirtualFileSystem
authored
143 files_[path].mtime = now_;
37a9390 @martine move VirtualFileSystem into test.*
authored
144 files_[path].contents = contents;
af070e5 Response files
unknown authored
145 files_created_.insert(path);
37a9390 @martine move VirtualFileSystem into test.*
authored
146 }
147
3beebde @nico Let Stat() have an err outparam instead of writing to stderr.
nico authored
148 TimeStamp VirtualFileSystem::Stat(const string& path, string* err) const {
e88a8da @nico make Stat() a const method
nico authored
149 FileMap::const_iterator i = files_.find(path);
3beebde @nico Let Stat() have an err outparam instead of writing to stderr.
nico authored
150 if (i != files_.end()) {
151 *err = i->second.stat_error;
37a9390 @martine move VirtualFileSystem into test.*
authored
152 return i->second.mtime;
3beebde @nico Let Stat() have an err outparam instead of writing to stderr.
nico authored
153 }
37a9390 @martine move VirtualFileSystem into test.*
authored
154 return 0;
155 }
156
af070e5 Response files
unknown authored
157 bool VirtualFileSystem::WriteFile(const string& path, const string& contents) {
29e76bc @martine move test virtual time "now_" into VirtualFileSystem
authored
158 Create(path, contents);
af070e5 Response files
unknown authored
159 return true;
160 }
161
37a9390 @martine move VirtualFileSystem into test.*
authored
162 bool VirtualFileSystem::MakeDir(const string& path) {
163 directories_made_.push_back(path);
164 return true; // success
165 }
166
3d17415 @martine disable the 'unused parameter' warning
authored
167 string VirtualFileSystem::ReadFile(const string& path, string* err) {
37a9390 @martine move VirtualFileSystem into test.*
authored
168 files_read_.push_back(path);
169 FileMap::iterator i = files_.find(path);
170 if (i != files_.end())
171 return i->second.contents;
172 return "";
173 }
5113d8c @nicolasdespres Add a test for the clean tool.
nicolasdespres authored
174
9412cb0 @nicolasdespres Return non-zero status when errors occur.
nicolasdespres authored
175 int VirtualFileSystem::RemoveFile(const string& path) {
176 if (find(directories_made_.begin(), directories_made_.end(), path)
177 != directories_made_.end())
178 return -1;
5113d8c @nicolasdespres Add a test for the clean tool.
nicolasdespres authored
179 FileMap::iterator i = files_.find(path);
180 if (i != files_.end()) {
181 files_.erase(i);
182 files_removed_.insert(path);
9412cb0 @nicolasdespres Return non-zero status when errors occur.
nicolasdespres authored
183 return 0;
5113d8c @nicolasdespres Add a test for the clean tool.
nicolasdespres authored
184 } else {
9412cb0 @nicolasdespres Return non-zero status when errors occur.
nicolasdespres authored
185 return 1;
5113d8c @nicolasdespres Add a test for the clean tool.
nicolasdespres authored
186 }
187 }
36660e4 @martine migrate tempdir code to test.cc
authored
188
189 void ScopedTempDir::CreateAndEnter(const string& name) {
190 // First change into the system temp dir and save it for cleanup.
191 start_dir_ = GetSystemTempDir();
192 if (start_dir_.empty())
193 Fatal("couldn't get system temp dir");
194 if (chdir(start_dir_.c_str()) < 0)
195 Fatal("chdir: %s", strerror(errno));
196
197 // Create a temporary subdirectory of that.
198 char name_template[1024];
199 strcpy(name_template, name.c_str());
200 strcat(name_template, "-XXXXXX");
201 char* tempname = mkdtemp(name_template);
202 if (!tempname)
203 Fatal("mkdtemp: %s", strerror(errno));
204 temp_dir_name_ = tempname;
205
206 // chdir into the new temporary directory.
207 if (chdir(temp_dir_name_.c_str()) < 0)
208 Fatal("chdir: %s", strerror(errno));
209 }
210
211 void ScopedTempDir::Cleanup() {
212 if (temp_dir_name_.empty())
213 return; // Something went wrong earlier.
214
215 // Move out of the directory we're about to clobber.
216 if (chdir(start_dir_.c_str()) < 0)
217 Fatal("chdir: %s", strerror(errno));
218
219 #ifdef _WIN32
220 string command = "rmdir /s /q " + temp_dir_name_;
221 #else
222 string command = "rm -rf " + temp_dir_name_;
223 #endif
224 if (system(command.c_str()) < 0)
225 Fatal("system: %s", strerror(errno));
226
227 temp_dir_name_.clear();
228 }
Something went wrong with that request. Please try again.