ASSERT_EQ("dependency cycle: out -> mid -> in -> pre -> out", err);
}
+struct VirtualFileSystem : public DiskInterface {
+ struct Entry {
+ int mtime;
+ string contents;
+ };
+
+ void Create(const string& path, int time, const string& contents) {
+ files_[path].mtime = time;
+ files_[path].contents = contents;
+ }
+
+ // DiskInterface
+ virtual int Stat(const string& path) {
+ FileMap::iterator i = files_.find(path);
+ if (i != files_.end())
+ return i->second.mtime;
+ return 0;
+ }
+ virtual bool MakeDir(const string& path) {
+ directories_made_.push_back(path);
+ return true; // success
+ }
+ virtual string ReadFile(const string& path, string* err) {
+ files_read_.push_back(path);
+ FileMap::iterator i = files_.find(path);
+ if (i != files_.end())
+ return i->second.contents;
+ return "";
+ }
+
+ vector<string> directories_made_;
+ vector<string> files_read_;
+ typedef map<string, Entry> FileMap;
+ FileMap files_;
+};
+
struct BuildTest : public StateTestWithBuiltinRules,
- public CommandRunner,
- public DiskInterface {
+ public CommandRunner {
BuildTest() : config_(MakeConfig()), builder_(&state_, config_), now_(1),
last_command_(NULL) {
- builder_.disk_interface_ = this;
+ builder_.disk_interface_ = &fs_;
builder_.command_runner_ = 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_, "");
}
// Mark a path dirty.
virtual bool WaitForCommands();
virtual Edge* NextFinishedCommand(bool* success);
- // DiskInterface
- virtual int Stat(const string& path) {
- return now_;
- }
- virtual bool MakeDir(const string& path) {
- directories_made_.push_back(path);
- return true; // success
- }
- virtual string ReadFile(const string& path, string* err) {
- files_read_.push_back(path);
- map<string, string>::iterator i = file_contents_.find(path);
- if (i != file_contents_.end())
- return i->second;
- return "";
- }
-
BuildConfig MakeConfig() {
BuildConfig config;
config.verbosity = BuildConfig::QUIET;
BuildConfig config_;
Builder builder_;
int now_;
- map<string, string> file_contents_;
+
+ VirtualFileSystem fs_;
+
vector<string> commands_ran_;
- vector<string> directories_made_;
- vector<string> files_read_;
Edge* last_command_;
};
// we should rebuild the target.
Dirty("cat1");
string err;
- ASSERT_TRUE(builder_.AddTarget("cat1", &err));
+ EXPECT_TRUE(builder_.AddTarget("cat1", &err));
+ ASSERT_EQ("", err);
EXPECT_TRUE(builder_.Build(&err));
- EXPECT_EQ("", err);
+ ASSERT_EQ("", err);
ASSERT_EQ(1, commands_ran_.size());
EXPECT_EQ("cat in1 > cat1", commands_ran_[0]);
"build c5: cat c4\n"));
ResetDirty();
+ fs_.Create("c1", now_, "");
string err;
EXPECT_TRUE(builder_.AddTarget("c5", &err));
now_ = 0; // Make all stat()s return file not found.
EXPECT_TRUE(builder_.Build(&err));
ASSERT_EQ("", err);
- ASSERT_EQ(2, directories_made_.size());
- EXPECT_EQ("subdir", directories_made_[0]);
- EXPECT_EQ("subdir/dir2", directories_made_[1]);
+ ASSERT_EQ(2, fs_.directories_made_.size());
+ EXPECT_EQ("subdir", fs_.directories_made_[0]);
+ EXPECT_EQ("subdir/dir2", fs_.directories_made_[1]);
}
TEST_F(BuildTest, DepFileMissing) {
"rule cc\n command = cc $in\n depfile = $out.d\n"
"build foo.o: cc foo.c\n"));
ResetDirty();
+ fs_.Create("foo.c", now_, "");
+
EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
ASSERT_EQ("", err);
- ASSERT_EQ(1, files_read_.size());
- EXPECT_EQ("foo.o.d", files_read_[0]);
+ ASSERT_EQ(1, fs_.files_read_.size());
+ EXPECT_EQ("foo.o.d", fs_.files_read_[0]);
}
TEST_F(BuildTest, DepFileOK) {
"rule cc\n command = cc $in\n depfile = $out.d\n"
"build foo.o: cc foo.c\n"));
ResetDirty();
+ fs_.Create("foo.c", now_, "");
GetNode("bar.h")->dirty_ = true; // Mark bar.h as missing.
- file_contents_["foo.o.d"] = "foo.o: blah.h bar.h\n";
+ fs_.Create("foo.o.d", now_, "foo.o: blah.h bar.h\n");
EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
ASSERT_EQ("", err);
- ASSERT_EQ(1, files_read_.size());
- EXPECT_EQ("foo.o.d", files_read_[0]);
+ ASSERT_EQ(1, fs_.files_read_.size());
+ EXPECT_EQ("foo.o.d", fs_.files_read_[0]);
// Expect our edge to now have three inputs: foo.c and two headers.
ASSERT_EQ(orig_edges + 1, state_.edges_.size());
"rule cc\n command = cc $in\n depfile = $out.d\n"
"build foo.o: cc foo.c\n"));
ResetDirty();
- file_contents_["foo.o.d"] = "foo.o blah.h bar.h\n";
+ fs_.Create("foo.c", now_, "");
+ fs_.Create("foo.o.d", now_, "foo.o blah.h bar.h\n");
EXPECT_FALSE(builder_.AddTarget("foo.o", &err));
EXPECT_EQ("line 1, col 7: expected ':', got 'blah.h'", err);
}
"rule cc\n command = cc $in\n depfile = $out.d\n"
"build foo.o: cc foo.c | otherfile\n"));
ResetDirty();
- file_contents_["foo.o.d"] = "foo.o: blah.h bar.h\n";
+ fs_.Create("foo.c", now_, "");
+ fs_.Create("otherfile", now_, "");
+ fs_.Create("foo.o.d", now_, "foo.o: blah.h bar.h\n");
EXPECT_TRUE(builder_.AddTarget("foo.o", &err));
+ ASSERT_EQ("", err);
Edge* edge = state_.edges_.back();
// One explicit, two implicit, one order only.
"build out: cat bar.cc\n"
"build all: phony out\n"));
ResetDirty();
+ fs_.Create("bar.cc", now_, "");
EXPECT_TRUE(builder_.AddTarget("all", &err));
+ ASSERT_EQ("", err);
// Only one command to run, because phony runs no command.
EXPECT_TRUE(builder_.Build(&err));