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
15#include "clean.h"
16#include "build.h"
17
18#include "util.h"
19#include "test.h"
20
21#ifndef _WIN32
22#include <unistd.h>
23#endif
24
25using namespace std;
26
27namespace {
28
29const char kTestFilename[] = "CleanTest-tempfile";
30
31struct CleanTest : public StateTestWithBuiltinRules {
32 VirtualFileSystem fs_;
33 BuildConfig config_;
34 virtual void SetUp() {
35 config_.verbosity = BuildConfig::QUIET;
36 }
37};
38
39TEST_F(CleanTest, CleanAll) {
40 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
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", "");
49
50 Cleaner cleaner(&state_, config_, &fs_);
51
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());
56
57 // Check they are removed.
58 string err;
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();
64
65 EXPECT_EQ(0, cleaner.CleanAll());
66 EXPECT_EQ(0, cleaner.cleaned_files_count());
67 EXPECT_EQ(0u, fs_.files_removed_.size());
68}
69
70TEST_F(CleanTest, CleanAllDryRun) {
71 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
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", "");
80
81 config_.dry_run = true;
82 Cleaner cleaner(&state_, config_, &fs_);
83
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());
88
89 // Check they are not removed.
90 string err;
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();
96
97 EXPECT_EQ(0, cleaner.CleanAll());
98 EXPECT_EQ(4, cleaner.cleaned_files_count());
99 EXPECT_EQ(0u, fs_.files_removed_.size());
100}
101
102TEST_F(CleanTest, CleanTarget) {
103 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
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", "");
112
113 Cleaner cleaner(&state_, config_, &fs_);
114
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());
119
120 // Check they are removed.
121 string err;
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();
127
128 ASSERT_EQ(0, cleaner.CleanTarget("out1"));
129 EXPECT_EQ(0, cleaner.cleaned_files_count());
130 EXPECT_EQ(0u, fs_.files_removed_.size());
131}
132
133TEST_F(CleanTest, CleanTargetDryRun) {
134 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
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", "");
143
144 config_.dry_run = true;
145 Cleaner cleaner(&state_, config_, &fs_);
146
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());
151
152 // Check they are not removed.
153 string err;
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();
159
160 ASSERT_EQ(0, cleaner.CleanTarget("out1"));
161 EXPECT_EQ(2, cleaner.cleaned_files_count());
162 EXPECT_EQ(0u, fs_.files_removed_.size());
163}
164
165TEST_F(CleanTest, CleanRule) {
166 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
167"rule cat_e\n"
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", "");
177
178 Cleaner cleaner(&state_, config_, &fs_);
179
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());
184
185 // Check they are removed.
186 string err;
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();
192
193 ASSERT_EQ(0, cleaner.CleanRule("cat_e"));
194 EXPECT_EQ(0, cleaner.cleaned_files_count());
195 EXPECT_EQ(0u, fs_.files_removed_.size());
196}
197
198TEST_F(CleanTest, CleanRuleDryRun) {
199 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
200"rule cat_e\n"
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", "");
210
211 config_.dry_run = true;
212 Cleaner cleaner(&state_, config_, &fs_);
213
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());
218
219 // Check they are not removed.
220 string err;
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();
226
227 ASSERT_EQ(0, cleaner.CleanRule("cat_e"));
228 EXPECT_EQ(2, cleaner.cleaned_files_count());
229 EXPECT_EQ(0u, fs_.files_removed_.size());
230}
231
232TEST_F(CleanTest, CleanRuleGenerator) {
233 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
234"rule regen\n"
235" command = cat $in > $out\n"
236" generator = 1\n"
237"build out1: cat in1\n"
238"build out2: regen in2\n"));
239 fs_.Create("out1", "");
240 fs_.Create("out2", "");
241
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());
246
247 fs_.Create("out1", "");
248
249 EXPECT_EQ(0, cleaner.CleanAll(/*generator=*/true));
250 EXPECT_EQ(2, cleaner.cleaned_files_count());
251 EXPECT_EQ(2u, fs_.files_removed_.size());
252}
253
254TEST_F(CleanTest, CleanDepFile) {
255 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
256"rule cc\n"
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", "");
262
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());
267}
268
269TEST_F(CleanTest, CleanDepFileOnCleanTarget) {
270 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
271"rule cc\n"
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", "");
277
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());
282}
283
284TEST_F(CleanTest, CleanDepFileOnCleanRule) {
285 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
286"rule cc\n"
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", "");
292
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());
297}
298
299TEST_F(CleanTest, CleanDyndep) {
300 // Verify that a dyndep file can be loaded to discover a new output
301 // to be cleaned.
302 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
303"build out: cat in || dd\n"
304" dyndep = dd\n"
305 ));
306 fs_.Create("in", "");
307 fs_.Create("dd",
308"ninja_dyndep_version = 1\n"
309"build out | out.imp: dyndep\n"
310);
311 fs_.Create("out", "");
312 fs_.Create("out.imp", "");
313
314 Cleaner cleaner(&state_, config_, &fs_);
315
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());
320
321 string err;
322 EXPECT_EQ(0, fs_.Stat("out", &err));
323 EXPECT_EQ(0, fs_.Stat("out.imp", &err));
324}
325
326TEST_F(CleanTest, CleanDyndepMissing) {
327 // Verify that a missing dyndep file is tolerated.
328 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
329"build out: cat in || dd\n"
330" dyndep = dd\n"
331 ));
332 fs_.Create("in", "");
333 fs_.Create("out", "");
334 fs_.Create("out.imp", "");
335
336 Cleaner cleaner(&state_, config_, &fs_);
337
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());
342
343 string err;
344 EXPECT_EQ(0, fs_.Stat("out", &err));
345 EXPECT_EQ(1, fs_.Stat("out.imp", &err));
346}
347
348TEST_F(CleanTest, CleanRspFile) {
349 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
350"rule cc\n"
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", "");
358
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());
363}
364
365TEST_F(CleanTest, CleanRsp) {
366 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
367"rule cat_rsp \n"
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"
374" rspfile=in2.rsp\n"
375"build out2: cat_rsp in2\n"
376" rspfile=out2.rsp\n"
377));
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", "");
384
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());
393
394 EXPECT_EQ(6u, fs_.files_removed_.size());
395
396 // Check they are removed.
397 string err;
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));
404}
405
406TEST_F(CleanTest, CleanFailure) {
407 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
408 "build dir: cat src1\n"));
409 fs_.MakeDir("dir");
410 Cleaner cleaner(&state_, config_, &fs_);
411 EXPECT_NE(0, cleaner.CleanAll());
412}
413
414TEST_F(CleanTest, CleanPhony) {
415 string err;
416 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
417"build phony: phony t1 t2\n"
418"build t1: cat\n"
419"build t2: cat\n"));
420
421 fs_.Create("phony", "");
422 fs_.Create("t1", "");
423 fs_.Create("t2", "");
424
425 // Check that CleanAll does not remove "phony".
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));
430
431 fs_.Create("t1", "");
432 fs_.Create("t2", "");
433
434 // Check that CleanTarget does not remove "phony".
435 EXPECT_EQ(0, cleaner.CleanTarget("phony"));
436 EXPECT_EQ(2, cleaner.cleaned_files_count());
437 EXPECT_LT(0, fs_.Stat("phony", &err));
438}
439
440TEST_F(CleanTest, CleanDepFileAndRspFileWithSpaces) {
441 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
442"rule cc_dep\n"
443" command = cc $in > $out\n"
444" depfile = $out.d\n"
445"rule cc_rsp\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"
451));
452 fs_.Create("out 1", "");
453 fs_.Create("out 2", "");
454 fs_.Create("out 1.d", "");
455 fs_.Create("out 2.rsp", "");
456
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());
461
462 string err;
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));
467}
468
469struct CleanDeadTest : public CleanTest, public BuildLogUser{
470 virtual void SetUp() {
471 // In case a crashing test left a stale file behind.
472 unlink(kTestFilename);
473 CleanTest::SetUp();
474 }
475 virtual void TearDown() {
476 unlink(kTestFilename);
477 }
478 virtual bool IsPathDead(StringPiece) const { return false; }
479};
480
481TEST_F(CleanDeadTest, CleanDead) {
482 State state;
483 ASSERT_NO_FATAL_FAILURE(AssertParse(&state,
484"rule cat\n"
485" command = cat $in > $out\n"
486"build out1: cat in\n"
487"build out2: cat in\n"
488));
489 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
490"build out2: cat in\n"
491));
492 fs_.Create("in", "");
493 fs_.Create("out1", "");
494 fs_.Create("out2", "");
495
496 BuildLog log1;
497 string err;
498 EXPECT_TRUE(log1.OpenForWrite(kTestFilename, *this, &err));
499 ASSERT_EQ("", err);
500 log1.RecordCommand(state.edges_[0], 15, 18);
501 log1.RecordCommand(state.edges_[1], 20, 25);
502 log1.Close();
503
504 BuildLog log2;
505 EXPECT_TRUE(log2.Load(kTestFilename, &err));
506 ASSERT_EQ("", err);
507 ASSERT_EQ(2u, log2.entries().size());
508 ASSERT_TRUE(log2.LookupByOutput("out1"));
509 ASSERT_TRUE(log2.LookupByOutput("out2"));
510
511 // First use the manifest that describe how to build out1.
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));
519
520 // Then use the manifest that does not build out1 anymore.
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));
529
530 // Nothing to do now.
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));
538 log2.Close();
539}
540
541TEST_F(CleanDeadTest, CleanDeadPreservesInputs) {
542 State state;
543 ASSERT_NO_FATAL_FAILURE(AssertParse(&state,
544"rule cat\n"
545" command = cat $in > $out\n"
546"build out1: cat in\n"
547"build out2: cat in\n"
548));
549 // This manifest does not build out1 anymore, but makes
550 // it an implicit input. CleanDead should detect this
551 // and preserve it.
552 ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
553"build out2: cat in | out1\n"
554));
555 fs_.Create("in", "");
556 fs_.Create("out1", "");
557 fs_.Create("out2", "");
558
559 BuildLog log1;
560 string err;
561 EXPECT_TRUE(log1.OpenForWrite(kTestFilename, *this, &err));
562 ASSERT_EQ("", err);
563 log1.RecordCommand(state.edges_[0], 15, 18);
564 log1.RecordCommand(state.edges_[1], 20, 25);
565 log1.Close();
566
567 BuildLog log2;
568 EXPECT_TRUE(log2.Load(kTestFilename, &err));
569 ASSERT_EQ("", err);
570 ASSERT_EQ(2u, log2.entries().size());
571 ASSERT_TRUE(log2.LookupByOutput("out1"));
572 ASSERT_TRUE(log2.LookupByOutput("out2"));
573
574 // First use the manifest that describe how to build out1.
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));
582
583 // Then use the manifest that does not build out1 anymore.
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));
591
592 // Nothing to do now.
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));
599 log2.Close();
600}
601} // anonymous namespace
602