all_i_currently_care_about: ninja_test
-ninja_test: LDFLAGS = -lgtest -lgtest_main
+ninja_test: LDFLAGS = -lgtest -lgmock -lgmock_main -lpthread
ninja_test: ninja_test.o
ninja_test.o: ninja_test.cc ninja.h manifest_parser.h
}
bool ManifestParser::ParseEdge(string* err) {
- vector<string> ins, outs;
string rule;
+ vector<string> ins, outs;
SkipWhitespace();
for (;;) {
if (!NextToken())
return Error("expected output file list", err);
if (token_ == ":")
break;
- ins.push_back(token_);
+ outs.push_back(token_);
}
if (!NextToken())
return Error("expected build command name", err);
for (;;) {
if (!NextToken())
break;
- outs.push_back(token_);
+ ins.push_back(token_);
}
if (!Newline(err))
return false;
}
struct Plan {
- Plan(State* state) : state_(state) {}
+ explicit Plan(State* state) : state_(state) {}
void AddTarget(const string& path);
bool AddTarget(Node* node);
State* state_;
set<Node*> want_;
queue<Edge*> ready_;
+
+private:
+ Plan();
+ Plan(const Plan&);
};
void Plan::AddTarget(const string& path) {
}
#include "manifest_parser.h"
+
+struct Shell {
+ virtual ~Shell() {}
+ virtual bool RunCommand(const string& command) = 0;
+};
+
+struct Builder {
+ Builder(State* state) : plan_(state) {}
+ virtual ~Builder() {}
+
+ void AddTarget(const string& name) {
+ plan_.AddTarget(name);
+ }
+ bool Build(Shell* shell, string* err);
+
+ Plan plan_;
+};
+
+bool Builder::Build(Shell* shell, string* err) {
+ while (Edge* edge = plan_.FindWork()) {
+ string command = edge->EvaluateCommand();
+ if (!shell->RunCommand(command)) {
+ err->assign("command '" + command + "' failed.");
+ return false;
+ }
+ // XXX tell plan about the files we've updated, so we have more
+ // work to do
+ }
+ return true;
+}
env.vars["$var"] = "there";
EXPECT_EQ("hi there", str.Evaluate(&env));
}
+
+#include <gmock/gmock.h>
+using ::testing::Return;
+using ::testing::_;
+
+struct MockShell : public Shell {
+ MOCK_METHOD1(RunCommand, bool(const string& command));
+};
+
+TEST(Build, OneStep) {
+ State state;
+ ManifestParser parser(&state);
+ string err;
+ ASSERT_TRUE(parser.Parse(
+"rule cat\n"
+"command cat @in > $out\n"
+"\n"
+"build lib: cat in1 in2\n"
+"build bin: cat main lib\n",
+ &err));
+ ASSERT_EQ("", err);
+
+ {
+ MockShell shell;
+ Builder builder(&state);
+ builder.AddTarget("bin");
+ EXPECT_CALL(shell, RunCommand(_))
+ .Times(0);
+ EXPECT_TRUE(builder.Build(&shell, &err));
+ EXPECT_EQ("", err);
+ }
+
+ {
+ MockShell shell;
+ Builder builder(&state);
+ state.stat_cache()->GetFile("in1")->Touch(1);
+ builder.AddTarget("bin");
+ EXPECT_CALL(shell, RunCommand("cat in1 in2 > lib"))
+ .WillOnce(Return(true));
+ EXPECT_TRUE(builder.Build(&shell, &err));
+ EXPECT_EQ("", err);
+ }
+}