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