move test virtual time "now_" into VirtualFileSystem
authorEvan Martin <martine@danga.com>
Mon, 8 Apr 2013 21:05:27 +0000 (14:05 -0700)
committerEvan Martin <martine@danga.com>
Mon, 8 Apr 2013 21:18:50 +0000 (14:18 -0700)
It's the only piece that cares about the current time.

src/build_test.cc
src/clean_test.cc
src/graph_test.cc
src/test.cc
src/test.h

index 40a82ed..7eecddf 100644 (file)
@@ -380,15 +380,15 @@ struct BuildTest : public StateTestWithBuiltinRules,
                    public CommandRunner {
   BuildTest() : config_(MakeConfig()),
                 builder_(&state_, config_, NULL, &fs_),
-                now_(1), last_command_(NULL), status_(config_) {
+                last_command_(NULL), status_(config_) {
     builder_.command_runner_.reset(this);
     AssertParse(&state_,
 "build cat1: cat in1\n"
 "build cat2: cat in1 in2\n"
 "build cat12: cat cat1 cat2\n");
 
-    fs_.Create("in1", now_, "");
-    fs_.Create("in2", now_, "");
+    fs_.Create("in1", "");
+    fs_.Create("in2", "");
   }
 
   ~BuildTest() {
@@ -414,7 +414,6 @@ struct BuildTest : public StateTestWithBuiltinRules,
   BuildConfig config_;
   VirtualFileSystem fs_;
   Builder builder_;
-  int now_;
 
   vector<string> commands_ran_;
   Edge* last_command_;
@@ -446,7 +445,7 @@ bool BuildTest::StartCommand(Edge* edge) {
       edge->rule().name() == "touch-interrupt") {
     for (vector<Node*>::iterator out = edge->outputs_.begin();
          out != edge->outputs_.end(); ++out) {
-      fs_.Create((*out)->path(), now_, "");
+      fs_.Create((*out)->path(), "");
     }
   } else if (edge->rule().name() == "true" ||
              edge->rule().name() == "fail" ||
@@ -540,11 +539,11 @@ TEST_F(BuildTest, TwoStep) {
 
   EXPECT_EQ("cat cat1 cat2 > cat12", commands_ran_[2]);
 
-  now_++;
+  fs_.Tick();
 
   // Modifying in2 requires rebuilding one intermediate file
   // and the final file.
-  fs_.Create("in2", now_, "");
+  fs_.Create("in2", "");
   state_.Reset();
   EXPECT_TRUE(builder_.AddTarget("cat12", &err));
   ASSERT_EQ("", err);
@@ -561,7 +560,7 @@ TEST_F(BuildTest, TwoOutputs) {
 "  command = touch $out\n"
 "build out1 out2: touch in.txt\n"));
 
-  fs_.Create("in.txt", now_, "");
+  fs_.Create("in.txt", "");
 
   string err;
   EXPECT_TRUE(builder_.AddTarget("out1", &err));
@@ -581,8 +580,9 @@ TEST_F(BuildTest, MultiOutIn) {
 "build in1 otherfile: touch in\n"
 "build out: touch in | in1\n"));
 
-  fs_.Create("in", now_, "");
-  fs_.Create("in1", ++now_, "");
+  fs_.Create("in", "");
+  fs_.Tick();
+  fs_.Create("in1", "");
 
   string err;
   EXPECT_TRUE(builder_.AddTarget("out", &err));
@@ -598,7 +598,7 @@ TEST_F(BuildTest, Chain) {
 "build c4: cat c3\n"
 "build c5: cat c4\n"));
 
-  fs_.Create("c1", now_, "");
+  fs_.Create("c1", "");
 
   string err;
   EXPECT_TRUE(builder_.AddTarget("c5", &err));
@@ -614,9 +614,9 @@ TEST_F(BuildTest, Chain) {
   ASSERT_EQ("", err);
   EXPECT_TRUE(builder_.AlreadyUpToDate());
 
-  now_++;
+  fs_.Tick();
 
-  fs_.Create("c3", now_, "");
+  fs_.Create("c3", "");
   err.clear();
   commands_ran_.clear();
   state_.Reset();
@@ -657,7 +657,6 @@ TEST_F(BuildTest, MakeDirs) {
 #endif
 
   EXPECT_EQ("", err);
-  now_ = 0;  // Make all stat()s return file not found.
   EXPECT_TRUE(builder_.Build(&err));
   ASSERT_EQ("", err);
   ASSERT_EQ(2u, fs_.directories_made_.size());
@@ -674,7 +673,7 @@ TEST_F(BuildTest, DepFileMissing) {
   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
 "rule cc\n  command = cc $in\n  depfile = $out.d\n"
 "build foo.o: cc foo.c\n"));
-  fs_.Create("foo.c", now_, "");
+  fs_.Create("foo.c", "");
 
   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
   ASSERT_EQ("", err);
@@ -690,9 +689,9 @@ TEST_F(BuildTest, DepFileOK) {
 "build foo.o: cc foo.c\n"));
   Edge* edge = state_.edges_.back();
 
-  fs_.Create("foo.c", now_, "");
+  fs_.Create("foo.c", "");
   GetNode("bar.h")->MarkDirty();  // Mark bar.h as missing.
-  fs_.Create("foo.o.d", now_, "foo.o: blah.h bar.h\n");
+  fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
   ASSERT_EQ("", err);
   ASSERT_EQ(1u, fs_.files_read_.size());
@@ -713,8 +712,8 @@ TEST_F(BuildTest, DepFileParseError) {
   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
 "rule cc\n  command = cc $in\n  depfile = $out.d\n"
 "build foo.o: cc foo.c\n"));
-  fs_.Create("foo.c", now_, "");
-  fs_.Create("foo.o.d", now_, "randomtext\n");
+  fs_.Create("foo.c", "");
+  fs_.Create("foo.o.d", "randomtext\n");
   EXPECT_FALSE(builder_.AddTarget("foo.o", &err));
   EXPECT_EQ("expected depfile 'foo.o.d' to mention 'foo.o', got 'randomtext'",
             err);
@@ -727,9 +726,9 @@ TEST_F(BuildTest, OrderOnlyDeps) {
 "build foo.o: cc foo.c || otherfile\n"));
   Edge* edge = state_.edges_.back();
 
-  fs_.Create("foo.c", now_, "");
-  fs_.Create("otherfile", now_, "");
-  fs_.Create("foo.o.d", now_, "foo.o: blah.h bar.h\n");
+  fs_.Create("foo.c", "");
+  fs_.Create("otherfile", "");
+  fs_.Create("foo.o.d", "foo.o: blah.h bar.h\n");
   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
   ASSERT_EQ("", err);
 
@@ -752,11 +751,11 @@ TEST_F(BuildTest, OrderOnlyDeps) {
   ASSERT_EQ("", err);
   ASSERT_EQ(1u, commands_ran_.size());
 
-  now_++;
+  fs_.Tick();
 
   // implicit dep dirty, expect a rebuild.
-  fs_.Create("blah.h", now_, "");
-  fs_.Create("bar.h", now_, "");
+  fs_.Create("blah.h", "");
+  fs_.Create("bar.h", "");
   commands_ran_.clear();
   state_.Reset();
   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
@@ -764,10 +763,10 @@ TEST_F(BuildTest, OrderOnlyDeps) {
   ASSERT_EQ("", err);
   ASSERT_EQ(1u, commands_ran_.size());
 
-  now_++;
+  fs_.Tick();
 
   // order only dep dirty, no rebuild.
-  fs_.Create("otherfile", now_, "");
+  fs_.Create("otherfile", "");
   commands_ran_.clear();
   state_.Reset();
   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
@@ -792,8 +791,8 @@ TEST_F(BuildTest, RebuildOrderOnlyDeps) {
 "build oo.h: cc oo.h.in\n"
 "build foo.o: cc foo.c || oo.h\n"));
 
-  fs_.Create("foo.c", now_, "");
-  fs_.Create("oo.h.in", now_, "");
+  fs_.Create("foo.c", "");
+  fs_.Create("oo.h.in", "");
 
   // foo.o and order-only dep dirty, build both.
   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
@@ -818,10 +817,10 @@ TEST_F(BuildTest, RebuildOrderOnlyDeps) {
   ASSERT_EQ(1u, commands_ran_.size());
   ASSERT_EQ("cc oo.h.in", commands_ran_[0]);
 
-  now_++;
+  fs_.Tick();
 
   // order-only dep dirty, build it only.
-  fs_.Create("oo.h.in", now_, "");
+  fs_.Create("oo.h.in", "");
   commands_ran_.clear();
   state_.Reset();
   EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
@@ -836,7 +835,7 @@ TEST_F(BuildTest, Phony) {
   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
 "build out: cat bar.cc\n"
 "build all: phony out\n"));
-  fs_.Create("bar.cc", now_, "");
+  fs_.Create("bar.cc", "");
 
   EXPECT_TRUE(builder_.AddTarget("all", &err));
   ASSERT_EQ("", err);
@@ -853,8 +852,8 @@ TEST_F(BuildTest, PhonyNoWork) {
   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
 "build out: cat bar.cc\n"
 "build all: phony out\n"));
-  fs_.Create("bar.cc", now_, "");
-  fs_.Create("out", now_, "");
+  fs_.Create("bar.cc", "");
+  fs_.Create("out", "");
 
   EXPECT_TRUE(builder_.AddTarget("all", &err));
   ASSERT_EQ("", err);
@@ -934,8 +933,8 @@ TEST_F(BuildWithLogTest, NotInLogButOnDisk) {
 
   // Create input/output that would be considered up to date when
   // not considering the command line hash.
-  fs_.Create("in", now_, "");
-  fs_.Create("out1", now_, "");
+  fs_.Create("in", "");
+  fs_.Create("out1", "");
   string err;
 
   // Because it's not in the log, it should not be up-to-date until
@@ -963,13 +962,13 @@ TEST_F(BuildWithLogTest, RestatTest) {
 "build out2: true out1\n"
 "build out3: cat out2\n"));
 
-  fs_.Create("out1", now_, "");
-  fs_.Create("out2", now_, "");
-  fs_.Create("out3", now_, "");
+  fs_.Create("out1", "");
+  fs_.Create("out2", "");
+  fs_.Create("out3", "");
 
-  now_++;
+  fs_.Tick();
 
-  fs_.Create("in", now_, "");
+  fs_.Create("in", "");
 
   // Do a pre-build so that there's commands in the log for the outputs,
   // otherwise, the lack of an entry in the build log will cause out3 to rebuild
@@ -982,9 +981,9 @@ TEST_F(BuildWithLogTest, RestatTest) {
   commands_ran_.clear();
   state_.Reset();
 
-  now_++;
+  fs_.Tick();
 
-  fs_.Create("in", now_, "");
+  fs_.Create("in", "");
   // "cc" touches out1, so we should build out2.  But because "true" does not
   // touch out2, we should cancel the build of out3.
   EXPECT_TRUE(builder_.AddTarget("out3", &err));
@@ -1000,9 +999,9 @@ TEST_F(BuildWithLogTest, RestatTest) {
   ASSERT_EQ("", err);
   EXPECT_TRUE(builder_.AlreadyUpToDate());
 
-  now_++;
+  fs_.Tick();
 
-  fs_.Create("in", now_, "");
+  fs_.Create("in", "");
 
   // The build log entry should not, however, prevent us from rebuilding out2
   // if out1 changes.
@@ -1028,8 +1027,8 @@ TEST_F(BuildWithLogTest, RestatMissingFile) {
 "build out1: true in\n"
 "build out2: cc out1\n"));
 
-  fs_.Create("in", now_, "");
-  fs_.Create("out2", now_, "");
+  fs_.Create("in", "");
+  fs_.Create("out2", "");
 
   // Do a pre-build so that there's commands in the log for the outputs,
   // otherwise, the lack of an entry in the build log will cause out2 to rebuild
@@ -1042,9 +1041,9 @@ TEST_F(BuildWithLogTest, RestatMissingFile) {
   commands_ran_.clear();
   state_.Reset();
 
-  now_++;
-  fs_.Create("in", now_, "");
-  fs_.Create("out2", now_, "");
+  fs_.Tick();
+  fs_.Create("in", "");
+  fs_.Create("out2", "");
 
   // Run a build, expect only the first command to run.
   // It doesn't touch its output (due to being the "true" command), so
@@ -1069,14 +1068,14 @@ TEST_F(BuildWithLogTest, RestatMissingInput) {
     "build out2: cc out1\n"));
 
   // Create all necessary files
-  fs_.Create("in", now_, "");
+  fs_.Create("in", "");
 
   // The implicit dependencies and the depfile itself
   // are newer than the output
-  TimeStamp restat_mtime = ++now_;
-  fs_.Create("out1.d", now_, "out1: will.be.deleted restat.file\n");
-  fs_.Create("will.be.deleted", now_, "");
-  fs_.Create("restat.file", now_, "");
+  TimeStamp restat_mtime = fs_.Tick();
+  fs_.Create("out1.d", "out1: will.be.deleted restat.file\n");
+  fs_.Create("will.be.deleted", "");
+  fs_.Create("restat.file", "");
 
   // Run the build, out1 and out2 get built
   string err;
@@ -1127,13 +1126,13 @@ TEST_F(BuildDryRun, AllCommandsShown) {
 "build out2: true out1\n"
 "build out3: cat out2\n"));
 
-  fs_.Create("out1", now_, "");
-  fs_.Create("out2", now_, "");
-  fs_.Create("out3", now_, "");
+  fs_.Create("out1", "");
+  fs_.Create("out2", "");
+  fs_.Create("out3", "");
 
-  now_++;
+  fs_.Tick();
 
-  fs_.Create("in", now_, "");
+  fs_.Create("in", "");
 
   // "cc" touches out1, so we should build out2.  But because "true" does not
   // touch out2, we should cancel the build of out3.
@@ -1158,13 +1157,13 @@ TEST_F(BuildTest, RspFileSuccess)
     "  rspfile = out2.rsp\n"
     "  long_command = Some very long command\n"));
 
-  fs_.Create("out1", now_, "");
-  fs_.Create("out2", now_, "");
-  fs_.Create("out3", now_, "");
+  fs_.Create("out1", "");
+  fs_.Create("out2", "");
+  fs_.Create("out3", "");
 
-  now_++;
+  fs_.Tick();
 
-  fs_.Create("in", now_, "");
+  fs_.Create("in", "");
 
   string err;
   EXPECT_TRUE(builder_.AddTarget("out1", &err));
@@ -1198,9 +1197,9 @@ TEST_F(BuildTest, RspFileFailure) {
     "  rspfile = out.rsp\n"
     "  long_command = Another very long command\n"));
 
-  fs_.Create("out", now_, "");
-  now_++;
-  fs_.Create("in", now_, "");
+  fs_.Create("out", "");
+  fs_.Tick();
+  fs_.Create("in", "");
 
   string err;
   EXPECT_TRUE(builder_.AddTarget("out", &err));
@@ -1237,9 +1236,9 @@ TEST_F(BuildWithLogTest, RspFileCmdLineChange) {
     "  rspfile = out.rsp\n"
     "  long_command = Original very long command\n"));
 
-  fs_.Create("out", now_, "");
-  now_++;
-  fs_.Create("in", now_, "");
+  fs_.Create("out", "");
+  fs_.Tick();
+  fs_.Create("in", "");
 
   string err;
   EXPECT_TRUE(builder_.AddTarget("out", &err));
@@ -1282,11 +1281,11 @@ TEST_F(BuildTest, InterruptCleanup) {
 "build out1: interrupt in1\n"
 "build out2: touch-interrupt in2\n"));
 
-  fs_.Create("out1", now_, "");
-  fs_.Create("out2", now_, "");
-  now_++;
-  fs_.Create("in1", now_, "");
-  fs_.Create("in2", now_, "");
+  fs_.Create("out1", "");
+  fs_.Create("out2", "");
+  fs_.Tick();
+  fs_.Create("in1", "");
+  fs_.Create("in2", "");
 
   // An untouched output of an interrupted command should be retained.
   string err;
@@ -1295,7 +1294,7 @@ TEST_F(BuildTest, InterruptCleanup) {
   EXPECT_FALSE(builder_.Build(&err));
   EXPECT_EQ("interrupted by user", err);
   builder_.Cleanup();
-  EXPECT_EQ(now_-1, fs_.Stat("out1"));
+  EXPECT_GT(fs_.Stat("out1"), 0);
   err = "";
 
   // A touched output of an interrupted command should be deleted.
@@ -1312,8 +1311,8 @@ TEST_F(BuildTest, PhonyWithNoInputs) {
 "build nonexistent: phony\n"
 "build out1: cat || nonexistent\n"
 "build out2: cat nonexistent\n"));
-  fs_.Create("out1", now_, "");
-  fs_.Create("out2", now_, "");
+  fs_.Create("out1", "");
+  fs_.Create("out2", "");
 
   // out1 should be up to date even though its input is dirty, because its
   // order-only dependency has nothing to do.
index 5ed48da..04cff73 100644 (file)
@@ -31,10 +31,10 @@ TEST_F(CleanTest, CleanAll) {
 "build out1: cat in1\n"
 "build in2: cat src2\n"
 "build out2: cat in2\n"));
-  fs_.Create("in1", 1, "");
-  fs_.Create("out1", 1, "");
-  fs_.Create("in2", 1, "");
-  fs_.Create("out2", 1, "");
+  fs_.Create("in1", "");
+  fs_.Create("out1", "");
+  fs_.Create("in2", "");
+  fs_.Create("out2", "");
 
   Cleaner cleaner(&state_, config_, &fs_);
 
@@ -61,10 +61,10 @@ TEST_F(CleanTest, CleanAllDryRun) {
 "build out1: cat in1\n"
 "build in2: cat src2\n"
 "build out2: cat in2\n"));
-  fs_.Create("in1", 1, "");
-  fs_.Create("out1", 1, "");
-  fs_.Create("in2", 1, "");
-  fs_.Create("out2", 1, "");
+  fs_.Create("in1", "");
+  fs_.Create("out1", "");
+  fs_.Create("in2", "");
+  fs_.Create("out2", "");
 
   config_.dry_run = true;
   Cleaner cleaner(&state_, config_, &fs_);
@@ -92,10 +92,10 @@ TEST_F(CleanTest, CleanTarget) {
 "build out1: cat in1\n"
 "build in2: cat src2\n"
 "build out2: cat in2\n"));
-  fs_.Create("in1", 1, "");
-  fs_.Create("out1", 1, "");
-  fs_.Create("in2", 1, "");
-  fs_.Create("out2", 1, "");
+  fs_.Create("in1", "");
+  fs_.Create("out1", "");
+  fs_.Create("in2", "");
+  fs_.Create("out2", "");
 
   Cleaner cleaner(&state_, config_, &fs_);
 
@@ -122,10 +122,10 @@ TEST_F(CleanTest, CleanTargetDryRun) {
 "build out1: cat in1\n"
 "build in2: cat src2\n"
 "build out2: cat in2\n"));
-  fs_.Create("in1", 1, "");
-  fs_.Create("out1", 1, "");
-  fs_.Create("in2", 1, "");
-  fs_.Create("out2", 1, "");
+  fs_.Create("in1", "");
+  fs_.Create("out1", "");
+  fs_.Create("in2", "");
+  fs_.Create("out2", "");
 
   config_.dry_run = true;
   Cleaner cleaner(&state_, config_, &fs_);
@@ -155,10 +155,10 @@ TEST_F(CleanTest, CleanRule) {
 "build out1: cat in1\n"
 "build in2: cat_e src2\n"
 "build out2: cat in2\n"));
-  fs_.Create("in1", 1, "");
-  fs_.Create("out1", 1, "");
-  fs_.Create("in2", 1, "");
-  fs_.Create("out2", 1, "");
+  fs_.Create("in1", "");
+  fs_.Create("out1", "");
+  fs_.Create("in2", "");
+  fs_.Create("out2", "");
 
   Cleaner cleaner(&state_, config_, &fs_);
 
@@ -187,10 +187,10 @@ TEST_F(CleanTest, CleanRuleDryRun) {
 "build out1: cat in1\n"
 "build in2: cat_e src2\n"
 "build out2: cat in2\n"));
-  fs_.Create("in1", 1, "");
-  fs_.Create("out1", 1, "");
-  fs_.Create("in2", 1, "");
-  fs_.Create("out2", 1, "");
+  fs_.Create("in1", "");
+  fs_.Create("out1", "");
+  fs_.Create("in2", "");
+  fs_.Create("out2", "");
 
   config_.dry_run = true;
   Cleaner cleaner(&state_, config_, &fs_);
@@ -219,15 +219,15 @@ TEST_F(CleanTest, CleanRuleGenerator) {
 "  generator = 1\n"
 "build out1: cat in1\n"
 "build out2: regen in2\n"));
-  fs_.Create("out1", 1, "");
-  fs_.Create("out2", 1, "");
+  fs_.Create("out1", "");
+  fs_.Create("out2", "");
 
   Cleaner cleaner(&state_, config_, &fs_);
   EXPECT_EQ(0, cleaner.CleanAll());
   EXPECT_EQ(1, cleaner.cleaned_files_count());
   EXPECT_EQ(1u, fs_.files_removed_.size());
 
-  fs_.Create("out1", 1, "");
+  fs_.Create("out1", "");
 
   EXPECT_EQ(0, cleaner.CleanAll(/*generator=*/true));
   EXPECT_EQ(2, cleaner.cleaned_files_count());
@@ -240,8 +240,8 @@ TEST_F(CleanTest, CleanDepFile) {
 "  command = cc $in > $out\n"
 "  depfile = $out.d\n"
 "build out1: cc in1\n"));
-  fs_.Create("out1", 1, "");
-  fs_.Create("out1.d", 1, "");
+  fs_.Create("out1", "");
+  fs_.Create("out1.d", "");
 
   Cleaner cleaner(&state_, config_, &fs_);
   EXPECT_EQ(0, cleaner.CleanAll());
@@ -255,8 +255,8 @@ TEST_F(CleanTest, CleanDepFileOnCleanTarget) {
 "  command = cc $in > $out\n"
 "  depfile = $out.d\n"
 "build out1: cc in1\n"));
-  fs_.Create("out1", 1, "");
-  fs_.Create("out1.d", 1, "");
+  fs_.Create("out1", "");
+  fs_.Create("out1.d", "");
 
   Cleaner cleaner(&state_, config_, &fs_);
   EXPECT_EQ(0, cleaner.CleanTarget("out1"));
@@ -270,8 +270,8 @@ TEST_F(CleanTest, CleanDepFileOnCleanRule) {
 "  command = cc $in > $out\n"
 "  depfile = $out.d\n"
 "build out1: cc in1\n"));
-  fs_.Create("out1", 1, "");
-  fs_.Create("out1.d", 1, "");
+  fs_.Create("out1", "");
+  fs_.Create("out1.d", "");
 
   Cleaner cleaner(&state_, config_, &fs_);
   EXPECT_EQ(0, cleaner.CleanRule("cc"));
@@ -288,8 +288,8 @@ TEST_F(CleanTest, CleanRspFile) {
 "build out1: cc in1\n"
 "  rspfile = cc1.rsp\n"
 "  rspfile_content=$in\n"));
-  fs_.Create("out1", 1, "");
-  fs_.Create("cc1.rsp", 1, "");
+  fs_.Create("out1", "");
+  fs_.Create("cc1.rsp", "");
 
   Cleaner cleaner(&state_, config_, &fs_);
   EXPECT_EQ(0, cleaner.CleanAll());
@@ -311,12 +311,12 @@ TEST_F(CleanTest, CleanRsp) {
 "build out2: cat_rsp in2\n"
 "  rspfile=out2.rsp\n"
 "  rspfile_content=$in\n"));
-  fs_.Create("in1", 1, "");
-  fs_.Create("out1", 1, "");
-  fs_.Create("in2.rsp", 1, "");
-  fs_.Create("out2.rsp", 1, "");
-  fs_.Create("in2", 1, "");
-  fs_.Create("out2", 1, "");
+  fs_.Create("in1", "");
+  fs_.Create("out1", "");
+  fs_.Create("in2.rsp", "");
+  fs_.Create("out2.rsp", "");
+  fs_.Create("in2", "");
+  fs_.Create("out2", "");
 
   Cleaner cleaner(&state_, config_, &fs_);
   ASSERT_EQ(0, cleaner.cleaned_files_count());
@@ -354,9 +354,9 @@ TEST_F(CleanTest, CleanPhony) {
 "build t1: cat\n"
 "build t2: cat\n"));
 
-  fs_.Create("phony", 1, "");
-  fs_.Create("t1", 1, "");
-  fs_.Create("t2", 1, "");
+  fs_.Create("phony", "");
+  fs_.Create("t1", "");
+  fs_.Create("t2", "");
 
   // Check that CleanAll does not remove "phony".
   Cleaner cleaner(&state_, config_, &fs_);
@@ -364,8 +364,8 @@ TEST_F(CleanTest, CleanPhony) {
   EXPECT_EQ(2, cleaner.cleaned_files_count());
   EXPECT_NE(0, fs_.Stat("phony"));
 
-  fs_.Create("t1", 1, "");
-  fs_.Create("t2", 1, "");
+  fs_.Create("t1", "");
+  fs_.Create("t2", "");
 
   // Check that CleanTarget does not remove "phony".
   EXPECT_EQ(0, cleaner.CleanTarget("phony"));
index 396def4..c105684 100644 (file)
@@ -26,8 +26,8 @@ struct GraphTest : public StateTestWithBuiltinRules {
 TEST_F(GraphTest, MissingImplicit) {
   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
 "build out: cat in | implicit\n"));
-  fs_.Create("in", 1, "");
-  fs_.Create("out", 1, "");
+  fs_.Create("in", "");
+  fs_.Create("out", "");
 
   Edge* edge = GetNode("out")->in_edge();
   string err;
@@ -43,9 +43,10 @@ TEST_F(GraphTest, MissingImplicit) {
 TEST_F(GraphTest, ModifiedImplicit) {
   ASSERT_NO_FATAL_FAILURE(AssertParse(&state_,
 "build out: cat in | implicit\n"));
-  fs_.Create("in", 1, "");
-  fs_.Create("out", 1, "");
-  fs_.Create("implicit", 2, "");
+  fs_.Create("in", "");
+  fs_.Create("out", "");
+  fs_.Tick();
+  fs_.Create("implicit", "");
 
   Edge* edge = GetNode("out")->in_edge();
   string err;
@@ -62,10 +63,11 @@ TEST_F(GraphTest, FunkyMakefilePath) {
 "  depfile = $out.d\n"
 "  command = cat $in > $out\n"
 "build out.o: catdep foo.cc\n"));
-  fs_.Create("implicit.h", 2, "");
-  fs_.Create("foo.cc", 1, "");
-  fs_.Create("out.o.d", 1, "out.o: ./foo/../implicit.h\n");
-  fs_.Create("out.o", 1, "");
+  fs_.Create("foo.cc",  "");
+  fs_.Create("out.o.d", "out.o: ./foo/../implicit.h\n");
+  fs_.Create("out.o", "");
+  fs_.Tick();
+  fs_.Create("implicit.h", "");
 
   Edge* edge = GetNode("out.o")->in_edge();
   string err;
@@ -84,11 +86,12 @@ TEST_F(GraphTest, ExplicitImplicit) {
 "  command = cat $in > $out\n"
 "build implicit.h: cat data\n"
 "build out.o: catdep foo.cc || implicit.h\n"));
-  fs_.Create("data", 2, "");
-  fs_.Create("implicit.h", 1, "");
-  fs_.Create("foo.cc", 1, "");
-  fs_.Create("out.o.d", 1, "out.o: implicit.h\n");
-  fs_.Create("out.o", 1, "");
+  fs_.Create("implicit.h", "");
+  fs_.Create("foo.cc", "");
+  fs_.Create("out.o.d", "out.o: implicit.h\n");
+  fs_.Create("out.o", "");
+  fs_.Tick();
+  fs_.Create("data", "");
 
   Edge* edge = GetNode("out.o")->in_edge();
   string err;
@@ -107,9 +110,9 @@ TEST_F(GraphTest, PathWithCurrentDirectory) {
 "  depfile = $out.d\n"
 "  command = cat $in > $out\n"
 "build ./out.o: catdep ./foo.cc\n"));
-  fs_.Create("foo.cc", 1, "");
-  fs_.Create("out.o.d", 1, "out.o: foo.cc\n");
-  fs_.Create("out.o", 1, "");
+  fs_.Create("foo.cc", "");
+  fs_.Create("out.o.d", "out.o: foo.cc\n");
+  fs_.Create("out.o", "");
 
   Edge* edge = GetNode("out.o")->in_edge();
   string err;
@@ -151,9 +154,9 @@ TEST_F(GraphTest, DepfileWithCanonicalizablePath) {
 "  depfile = $out.d\n"
 "  command = cat $in > $out\n"
 "build ./out.o: catdep ./foo.cc\n"));
-  fs_.Create("foo.cc", 1, "");
-  fs_.Create("out.o.d", 1, "out.o: bar/../foo.cc\n");
-  fs_.Create("out.o", 1, "");
+  fs_.Create("foo.cc", "");
+  fs_.Create("out.o.d", "out.o: bar/../foo.cc\n");
+  fs_.Create("out.o", "");
 
   Edge* edge = GetNode("out.o")->in_edge();
   string err;
@@ -170,10 +173,11 @@ TEST_F(GraphTest, DepfileRemoved) {
 "  depfile = $out.d\n"
 "  command = cat $in > $out\n"
 "build ./out.o: catdep ./foo.cc\n"));
-  fs_.Create("foo.h", 1, "");
-  fs_.Create("foo.cc", 1, "");
-  fs_.Create("out.o.d", 2, "out.o: foo.h\n");
-  fs_.Create("out.o", 2, "");
+  fs_.Create("foo.h", "");
+  fs_.Create("foo.cc", "");
+  fs_.Tick();
+  fs_.Create("out.o.d", "out.o: foo.h\n");
+  fs_.Create("out.o", "");
 
   Edge* edge = GetNode("out.o")->in_edge();
   string err;
index 0138b3a..c48ca82 100644 (file)
@@ -94,9 +94,9 @@ void AssertHash(const char* expected, uint64_t actual) {
   ASSERT_EQ(BuildLog::LogEntry::HashCommand(expected), actual);
 }
 
-void VirtualFileSystem::Create(const string& path, int time,
+void VirtualFileSystem::Create(const string& path,
                                const string& contents) {
-  files_[path].mtime = time;
+  files_[path].mtime = now_;
   files_[path].contents = contents;
   files_created_.insert(path);
 }
@@ -109,7 +109,7 @@ TimeStamp VirtualFileSystem::Stat(const string& path) {
 }
 
 bool VirtualFileSystem::WriteFile(const string& path, const string& contents) {
-  Create(path, 0, contents);
+  Create(path, contents);
   return true;
 }
 
index 37ca1f9..bff0e5a 100644 (file)
@@ -41,8 +41,16 @@ void AssertHash(const char* expected, uint64_t actual);
 /// of disk state.  It also logs file accesses and directory creations
 /// so it can be used by tests to verify disk access patterns.
 struct VirtualFileSystem : public DiskInterface {
-  /// "Create" a file with a given mtime and contents.
-  void Create(const string& path, int time, const string& contents);
+  VirtualFileSystem() : now_(1) {}
+
+  /// "Create" a file with contents.
+  void Create(const string& path, const string& contents);
+
+  /// Tick "time" forwards; subsequent file operations will be newer than
+  /// previous ones.
+  int Tick() {
+    return ++now_;
+  }
 
   // DiskInterface
   virtual TimeStamp Stat(const string& path);
@@ -63,6 +71,9 @@ struct VirtualFileSystem : public DiskInterface {
   FileMap files_;
   set<string> files_removed_;
   set<string> files_created_;
+
+  /// A simple fake timestamp for file operations.
+  int now_;
 };
 
 struct ScopedTempDir {