xref: /third_party/ninja/src/clean_test.cc (revision 695b41ee)
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