34 virtual void SetUp() {
39 TEST_F(CleanTest, CleanAll) {
41 "build in1: cat src1\n"
42 "build out1: cat in1\n"
43 "build in2: cat src2\n"
44 "build out2: cat in2\n"));
45 fs_.Create(
"in1",
"");
46 fs_.Create(
"out1",
"");
47 fs_.Create(
"in2",
"");
48 fs_.Create(
"out2",
"");
50 Cleaner cleaner(&state_, config_, &fs_);
52 ASSERT_EQ(0, cleaner.cleaned_files_count());
53 EXPECT_EQ(0, cleaner.CleanAll());
54 EXPECT_EQ(4, cleaner.cleaned_files_count());
55 EXPECT_EQ(4u, fs_.files_removed_.size());
59 EXPECT_EQ(0, fs_.Stat(
"in1", &err));
60 EXPECT_EQ(0, fs_.Stat(
"out1", &err));
61 EXPECT_EQ(0, fs_.Stat(
"in2", &err));
62 EXPECT_EQ(0, fs_.Stat(
"out2", &err));
63 fs_.files_removed_.clear();
65 EXPECT_EQ(0, cleaner.CleanAll());
66 EXPECT_EQ(0, cleaner.cleaned_files_count());
67 EXPECT_EQ(0u, fs_.files_removed_.size());
70 TEST_F(CleanTest, CleanAllDryRun) {
72 "build in1: cat src1\n"
73 "build out1: cat in1\n"
74 "build in2: cat src2\n"
75 "build out2: cat in2\n"));
76 fs_.Create(
"in1",
"");
77 fs_.Create(
"out1",
"");
78 fs_.Create(
"in2",
"");
79 fs_.Create(
"out2",
"");
81 config_.dry_run =
true;
82 Cleaner cleaner(&state_, config_, &fs_);
84 ASSERT_EQ(0, cleaner.cleaned_files_count());
85 EXPECT_EQ(0, cleaner.CleanAll());
86 EXPECT_EQ(4, cleaner.cleaned_files_count());
87 EXPECT_EQ(0u, fs_.files_removed_.size());
91 EXPECT_LT(0, fs_.Stat(
"in1", &err));
92 EXPECT_LT(0, fs_.Stat(
"out1", &err));
93 EXPECT_LT(0, fs_.Stat(
"in2", &err));
94 EXPECT_LT(0, fs_.Stat(
"out2", &err));
95 fs_.files_removed_.clear();
97 EXPECT_EQ(0, cleaner.CleanAll());
98 EXPECT_EQ(4, cleaner.cleaned_files_count());
99 EXPECT_EQ(0u, fs_.files_removed_.size());
102 TEST_F(CleanTest, CleanTarget) {
104 "build in1: cat src1\n"
105 "build out1: cat in1\n"
106 "build in2: cat src2\n"
107 "build out2: cat in2\n"));
108 fs_.Create(
"in1",
"");
109 fs_.Create(
"out1",
"");
110 fs_.Create(
"in2",
"");
111 fs_.Create(
"out2",
"");
113 Cleaner cleaner(&state_, config_, &fs_);
115 ASSERT_EQ(0, cleaner.cleaned_files_count());
116 ASSERT_EQ(0, cleaner.CleanTarget(
"out1"));
117 EXPECT_EQ(2, cleaner.cleaned_files_count());
118 EXPECT_EQ(2u, fs_.files_removed_.size());
122 EXPECT_EQ(0, fs_.Stat(
"in1", &err));
123 EXPECT_EQ(0, fs_.Stat(
"out1", &err));
124 EXPECT_LT(0, fs_.Stat(
"in2", &err));
125 EXPECT_LT(0, fs_.Stat(
"out2", &err));
126 fs_.files_removed_.clear();
128 ASSERT_EQ(0, cleaner.CleanTarget(
"out1"));
129 EXPECT_EQ(0, cleaner.cleaned_files_count());
130 EXPECT_EQ(0u, fs_.files_removed_.size());
133 TEST_F(CleanTest, CleanTargetDryRun) {
135 "build in1: cat src1\n"
136 "build out1: cat in1\n"
137 "build in2: cat src2\n"
138 "build out2: cat in2\n"));
139 fs_.Create(
"in1",
"");
140 fs_.Create(
"out1",
"");
141 fs_.Create(
"in2",
"");
142 fs_.Create(
"out2",
"");
144 config_.dry_run =
true;
145 Cleaner cleaner(&state_, config_, &fs_);
147 ASSERT_EQ(0, cleaner.cleaned_files_count());
148 ASSERT_EQ(0, cleaner.CleanTarget(
"out1"));
149 EXPECT_EQ(2, cleaner.cleaned_files_count());
150 EXPECT_EQ(0u, fs_.files_removed_.size());
154 EXPECT_LT(0, fs_.Stat(
"in1", &err));
155 EXPECT_LT(0, fs_.Stat(
"out1", &err));
156 EXPECT_LT(0, fs_.Stat(
"in2", &err));
157 EXPECT_LT(0, fs_.Stat(
"out2", &err));
158 fs_.files_removed_.clear();
160 ASSERT_EQ(0, cleaner.CleanTarget(
"out1"));
161 EXPECT_EQ(2, cleaner.cleaned_files_count());
162 EXPECT_EQ(0u, fs_.files_removed_.size());
165 TEST_F(CleanTest, CleanRule) {
168 " command = cat -e $in > $out\n"
169 "build in1: cat_e src1\n"
170 "build out1: cat in1\n"
171 "build in2: cat_e src2\n"
172 "build out2: cat in2\n"));
173 fs_.Create(
"in1",
"");
174 fs_.Create(
"out1",
"");
175 fs_.Create(
"in2",
"");
176 fs_.Create(
"out2",
"");
178 Cleaner cleaner(&state_, config_, &fs_);
180 ASSERT_EQ(0, cleaner.cleaned_files_count());
181 ASSERT_EQ(0, cleaner.CleanRule(
"cat_e"));
182 EXPECT_EQ(2, cleaner.cleaned_files_count());
183 EXPECT_EQ(2u, fs_.files_removed_.size());
187 EXPECT_EQ(0, fs_.Stat(
"in1", &err));
188 EXPECT_LT(0, fs_.Stat(
"out1", &err));
189 EXPECT_EQ(0, fs_.Stat(
"in2", &err));
190 EXPECT_LT(0, fs_.Stat(
"out2", &err));
191 fs_.files_removed_.clear();
193 ASSERT_EQ(0, cleaner.CleanRule(
"cat_e"));
194 EXPECT_EQ(0, cleaner.cleaned_files_count());
195 EXPECT_EQ(0u, fs_.files_removed_.size());
198 TEST_F(CleanTest, CleanRuleDryRun) {
201 " command = cat -e $in > $out\n"
202 "build in1: cat_e src1\n"
203 "build out1: cat in1\n"
204 "build in2: cat_e src2\n"
205 "build out2: cat in2\n"));
206 fs_.Create(
"in1",
"");
207 fs_.Create(
"out1",
"");
208 fs_.Create(
"in2",
"");
209 fs_.Create(
"out2",
"");
211 config_.dry_run =
true;
212 Cleaner cleaner(&state_, config_, &fs_);
214 ASSERT_EQ(0, cleaner.cleaned_files_count());
215 ASSERT_EQ(0, cleaner.CleanRule(
"cat_e"));
216 EXPECT_EQ(2, cleaner.cleaned_files_count());
217 EXPECT_EQ(0u, fs_.files_removed_.size());
221 EXPECT_LT(0, fs_.Stat(
"in1", &err));
222 EXPECT_LT(0, fs_.Stat(
"out1", &err));
223 EXPECT_LT(0, fs_.Stat(
"in2", &err));
224 EXPECT_LT(0, fs_.Stat(
"out2", &err));
225 fs_.files_removed_.clear();
227 ASSERT_EQ(0, cleaner.CleanRule(
"cat_e"));
228 EXPECT_EQ(2, cleaner.cleaned_files_count());
229 EXPECT_EQ(0u, fs_.files_removed_.size());
232 TEST_F(CleanTest, CleanRuleGenerator) {
235 " command = cat $in > $out\n"
237 "build out1: cat in1\n"
238 "build out2: regen in2\n"));
239 fs_.Create(
"out1",
"");
240 fs_.Create(
"out2",
"");
242 Cleaner cleaner(&state_, config_, &fs_);
243 EXPECT_EQ(0, cleaner.CleanAll());
244 EXPECT_EQ(1, cleaner.cleaned_files_count());
245 EXPECT_EQ(1u, fs_.files_removed_.size());
247 fs_.Create(
"out1",
"");
249 EXPECT_EQ(0, cleaner.CleanAll(
true));
250 EXPECT_EQ(2, cleaner.cleaned_files_count());
251 EXPECT_EQ(2u, fs_.files_removed_.size());
254 TEST_F(CleanTest, CleanDepFile) {
257 " command = cc $in > $out\n"
258 " depfile = $out.d\n"
259 "build out1: cc in1\n"));
260 fs_.Create(
"out1",
"");
261 fs_.Create(
"out1.d",
"");
263 Cleaner cleaner(&state_, config_, &fs_);
264 EXPECT_EQ(0, cleaner.CleanAll());
265 EXPECT_EQ(2, cleaner.cleaned_files_count());
266 EXPECT_EQ(2u, fs_.files_removed_.size());
269 TEST_F(CleanTest, CleanDepFileOnCleanTarget) {
272 " command = cc $in > $out\n"
273 " depfile = $out.d\n"
274 "build out1: cc in1\n"));
275 fs_.Create(
"out1",
"");
276 fs_.Create(
"out1.d",
"");
278 Cleaner cleaner(&state_, config_, &fs_);
279 EXPECT_EQ(0, cleaner.CleanTarget(
"out1"));
280 EXPECT_EQ(2, cleaner.cleaned_files_count());
281 EXPECT_EQ(2u, fs_.files_removed_.size());
284 TEST_F(CleanTest, CleanDepFileOnCleanRule) {
287 " command = cc $in > $out\n"
288 " depfile = $out.d\n"
289 "build out1: cc in1\n"));
290 fs_.Create(
"out1",
"");
291 fs_.Create(
"out1.d",
"");
293 Cleaner cleaner(&state_, config_, &fs_);
294 EXPECT_EQ(0, cleaner.CleanRule(
"cc"));
295 EXPECT_EQ(2, cleaner.cleaned_files_count());
296 EXPECT_EQ(2u, fs_.files_removed_.size());
299 TEST_F(CleanTest, CleanDyndep) {
303 "build out: cat in || dd\n"
306 fs_.Create(
"in",
"");
308 "ninja_dyndep_version = 1\n"
309 "build out | out.imp: dyndep\n"
311 fs_.Create(
"out",
"");
312 fs_.Create(
"out.imp",
"");
314 Cleaner cleaner(&state_, config_, &fs_);
316 ASSERT_EQ(0, cleaner.cleaned_files_count());
317 EXPECT_EQ(0, cleaner.CleanAll());
318 EXPECT_EQ(2, cleaner.cleaned_files_count());
319 EXPECT_EQ(2u, fs_.files_removed_.size());
322 EXPECT_EQ(0, fs_.Stat(
"out", &err));
323 EXPECT_EQ(0, fs_.Stat(
"out.imp", &err));
326 TEST_F(CleanTest, CleanDyndepMissing) {
329 "build out: cat in || dd\n"
332 fs_.Create(
"in",
"");
333 fs_.Create(
"out",
"");
334 fs_.Create(
"out.imp",
"");
336 Cleaner cleaner(&state_, config_, &fs_);
338 ASSERT_EQ(0, cleaner.cleaned_files_count());
339 EXPECT_EQ(0, cleaner.CleanAll());
340 EXPECT_EQ(1, cleaner.cleaned_files_count());
341 EXPECT_EQ(1u, fs_.files_removed_.size());
344 EXPECT_EQ(0, fs_.Stat(
"out", &err));
345 EXPECT_EQ(1, fs_.Stat(
"out.imp", &err));
348 TEST_F(CleanTest, CleanRspFile) {
351 " command = cc $in > $out\n"
352 " rspfile = $rspfile\n"
353 " rspfile_content=$in\n"
354 "build out1: cc in1\n"
355 " rspfile = cc1.rsp\n"));
356 fs_.Create(
"out1",
"");
357 fs_.Create(
"cc1.rsp",
"");
359 Cleaner cleaner(&state_, config_, &fs_);
360 EXPECT_EQ(0, cleaner.CleanAll());
361 EXPECT_EQ(2, cleaner.cleaned_files_count());
362 EXPECT_EQ(2u, fs_.files_removed_.size());
365 TEST_F(CleanTest, CleanRsp) {
368 " command = cat $rspfile > $out\n"
369 " rspfile = $rspfile\n"
370 " rspfile_content = $in\n"
371 "build in1: cat src1\n"
372 "build out1: cat in1\n"
373 "build in2: cat_rsp src2\n"
375 "build out2: cat_rsp in2\n"
376 " rspfile=out2.rsp\n"
378 fs_.Create(
"in1",
"");
379 fs_.Create(
"out1",
"");
380 fs_.Create(
"in2.rsp",
"");
381 fs_.Create(
"out2.rsp",
"");
382 fs_.Create(
"in2",
"");
383 fs_.Create(
"out2",
"");
385 Cleaner cleaner(&state_, config_, &fs_);
386 ASSERT_EQ(0, cleaner.cleaned_files_count());
387 ASSERT_EQ(0, cleaner.CleanTarget(
"out1"));
388 EXPECT_EQ(2, cleaner.cleaned_files_count());
389 ASSERT_EQ(0, cleaner.CleanTarget(
"in2"));
390 EXPECT_EQ(2, cleaner.cleaned_files_count());
391 ASSERT_EQ(0, cleaner.CleanRule(
"cat_rsp"));
392 EXPECT_EQ(2, cleaner.cleaned_files_count());
394 EXPECT_EQ(6u, fs_.files_removed_.size());
398 EXPECT_EQ(0, fs_.Stat(
"in1", &err));
399 EXPECT_EQ(0, fs_.Stat(
"out1", &err));
400 EXPECT_EQ(0, fs_.Stat(
"in2", &err));
401 EXPECT_EQ(0, fs_.Stat(
"out2", &err));
402 EXPECT_EQ(0, fs_.Stat(
"in2.rsp", &err));
403 EXPECT_EQ(0, fs_.Stat(
"out2.rsp", &err));
406 TEST_F(CleanTest, CleanFailure) {
408 "build dir: cat src1\n"));
410 Cleaner cleaner(&state_, config_, &fs_);
411 EXPECT_NE(0, cleaner.CleanAll());
414 TEST_F(CleanTest, CleanPhony) {
417 "build phony: phony t1 t2\n"
421 fs_.Create(
"phony",
"");
422 fs_.Create(
"t1",
"");
423 fs_.Create(
"t2",
"");
426 Cleaner cleaner(&state_, config_, &fs_);
427 EXPECT_EQ(0, cleaner.CleanAll());
428 EXPECT_EQ(2, cleaner.cleaned_files_count());
429 EXPECT_LT(0, fs_.Stat(
"phony", &err));
431 fs_.Create(
"t1",
"");
432 fs_.Create(
"t2",
"");
435 EXPECT_EQ(0, cleaner.CleanTarget(
"phony"));
436 EXPECT_EQ(2, cleaner.cleaned_files_count());
437 EXPECT_LT(0, fs_.Stat(
"phony", &err));
440 TEST_F(CleanTest, CleanDepFileAndRspFileWithSpaces) {
443 " command = cc $in > $out\n"
444 " depfile = $out.d\n"
446 " command = cc $in > $out\n"
447 " rspfile = $out.rsp\n"
448 " rspfile_content = $in\n"
449 "build out$ 1: cc_dep in$ 1\n"
450 "build out$ 2: cc_rsp in$ 1\n"
452 fs_.Create(
"out 1",
"");
453 fs_.Create(
"out 2",
"");
454 fs_.Create(
"out 1.d",
"");
455 fs_.Create(
"out 2.rsp",
"");
457 Cleaner cleaner(&state_, config_, &fs_);
458 EXPECT_EQ(0, cleaner.CleanAll());
459 EXPECT_EQ(4, cleaner.cleaned_files_count());
460 EXPECT_EQ(4u, fs_.files_removed_.size());
463 EXPECT_EQ(0, fs_.Stat(
"out 1", &err));
464 EXPECT_EQ(0, fs_.Stat(
"out 2", &err));
465 EXPECT_EQ(0, fs_.Stat(
"out 1.d", &err));
466 EXPECT_EQ(0, fs_.Stat(
"out 2.rsp", &err));
469 struct CleanDeadTest :
public CleanTest,
public BuildLogUser{
470 virtual void SetUp() {
475 virtual void TearDown() {
478 virtual bool IsPathDead(
StringPiece)
const {
return false; }
481 TEST_F(CleanDeadTest, CleanDead) {
485 " command = cat $in > $out\n"
486 "build out1: cat in\n"
487 "build out2: cat in\n"
490 "build out2: cat in\n"
492 fs_.Create(
"in",
"");
493 fs_.Create(
"out1",
"");
494 fs_.Create(
"out2",
"");
507 ASSERT_EQ(2u, log2.
entries().size());
512 Cleaner cleaner1(&state, config_, &fs_);
513 EXPECT_EQ(0, cleaner1.CleanDead(log2.
entries()));
514 EXPECT_EQ(0, cleaner1.cleaned_files_count());
515 EXPECT_EQ(0u, fs_.files_removed_.size());
516 EXPECT_NE(0, fs_.Stat(
"in", &err));
517 EXPECT_NE(0, fs_.Stat(
"out1", &err));
518 EXPECT_NE(0, fs_.Stat(
"out2", &err));
521 Cleaner cleaner2(&state_, config_, &fs_);
522 EXPECT_EQ(0, cleaner2.CleanDead(log2.
entries()));
523 EXPECT_EQ(1, cleaner2.cleaned_files_count());
524 EXPECT_EQ(1u, fs_.files_removed_.size());
525 EXPECT_EQ(
"out1", *(fs_.files_removed_.begin()));
526 EXPECT_NE(0, fs_.Stat(
"in", &err));
527 EXPECT_EQ(0, fs_.Stat(
"out1", &err));
528 EXPECT_NE(0, fs_.Stat(
"out2", &err));
531 EXPECT_EQ(0, cleaner2.CleanDead(log2.
entries()));
532 EXPECT_EQ(0, cleaner2.cleaned_files_count());
533 EXPECT_EQ(1u, fs_.files_removed_.size());
534 EXPECT_EQ(
"out1", *(fs_.files_removed_.begin()));
535 EXPECT_NE(0, fs_.Stat(
"in", &err));
536 EXPECT_EQ(0, fs_.Stat(
"out1", &err));
537 EXPECT_NE(0, fs_.Stat(
"out2", &err));
541 TEST_F(CleanDeadTest, CleanDeadPreservesInputs) {
545 " command = cat $in > $out\n"
546 "build out1: cat in\n"
547 "build out2: cat in\n"
553 "build out2: cat in | out1\n"
555 fs_.Create(
"in",
"");
556 fs_.Create(
"out1",
"");
557 fs_.Create(
"out2",
"");
570 ASSERT_EQ(2u, log2.
entries().size());
575 Cleaner cleaner1(&state, config_, &fs_);
576 EXPECT_EQ(0, cleaner1.CleanDead(log2.
entries()));
577 EXPECT_EQ(0, cleaner1.cleaned_files_count());
578 EXPECT_EQ(0u, fs_.files_removed_.size());
579 EXPECT_NE(0, fs_.Stat(
"in", &err));
580 EXPECT_NE(0, fs_.Stat(
"out1", &err));
581 EXPECT_NE(0, fs_.Stat(
"out2", &err));
584 Cleaner cleaner2(&state_, config_, &fs_);
585 EXPECT_EQ(0, cleaner2.CleanDead(log2.
entries()));
586 EXPECT_EQ(0, cleaner2.cleaned_files_count());
587 EXPECT_EQ(0u, fs_.files_removed_.size());
588 EXPECT_NE(0, fs_.Stat(
"in", &err));
589 EXPECT_NE(0, fs_.Stat(
"out1", &err));
590 EXPECT_NE(0, fs_.Stat(
"out2", &err));
593 EXPECT_EQ(0, cleaner2.CleanDead(log2.
entries()));
594 EXPECT_EQ(0, cleaner2.cleaned_files_count());
595 EXPECT_EQ(0u, fs_.files_removed_.size());
596 EXPECT_NE(0, fs_.Stat(
"in", &err));
597 EXPECT_NE(0, fs_.Stat(
"out1", &err));
598 EXPECT_NE(0, fs_.Stat(
"out2", &err));
const char kTestFilename[]
Options (e.g. verbosity, parallelism) passed to a build.
Can answer questions about the manifest for the BuildLog.
Store a log of every command ran for every build.
LogEntry * LookupByOutput(const std::string &path)
Lookup a previously-run command by its output path.
LoadStatus Load(const std::string &path, std::string *err)
Load the on-disk log.
const Entries & entries() const
bool OpenForWrite(const std::string &path, const BuildLogUser &user, std::string *err)
Prepares writing to the log file without actually opening it - that will happen when/if it's needed.
bool RecordCommand(Edge *edge, int start_time, int end_time, TimeStamp mtime=0)
A base test fixture that includes a State object with a builtin "cat" rule.
Global state (file status) for a single run.
std::vector< Edge * > edges_
All the edges of the graph.
StringPiece represents a slice of a string whose memory is managed externally.
An implementation of DiskInterface that uses an in-memory representation of disk state.
void AssertParse(State *state, const char *input, ManifestParserOptions opts)
int platformAwareUnlink(const char *filename)