Teach FakeCommandRunner to support multiple active commands

Replace our single active edge pointer with a vector and add a
parameter that tests can set to limit the number of concurrent
edges.  Set the default to 1 to preserve the current behavior.
Specific tests will be able to override it later to simulate
concurrent builds.
diff --git a/src/build_test.cc b/src/build_test.cc
index b50b66f..0ca7c3d 100644
--- a/src/build_test.cc
+++ b/src/build_test.cc
@@ -21,6 +21,12 @@
 #include "graph.h"
 #include "test.h"
 
+struct CompareEdgesByOutput {
+  static bool cmp(const Edge* a, const Edge* b) {
+    return a->outputs_[0]->path() < b->outputs_[0]->path();
+  }
+};
+
 /// Fixture for tests involving Plan.
 // Though Plan doesn't use State, it's useful to have one around
 // to create Nodes and Edges.
@@ -31,12 +37,6 @@
   // provide a means to get available Edges in order and in a format which is
   // easy to write tests around.
   void FindWorkSorted(deque<Edge*>* ret, int count) {
-    struct CompareEdgesByOutput {
-      static bool cmp(const Edge* a, const Edge* b) {
-        return a->outputs_[0]->path() < b->outputs_[0]->path();
-      }
-    };
-
     for (int i = 0; i < count; ++i) {
       ASSERT_TRUE(plan_.more_to_do());
       Edge* edge = plan_.FindWork();
@@ -467,7 +467,7 @@
 /// Fake implementation of CommandRunner, useful for tests.
 struct FakeCommandRunner : public CommandRunner {
   explicit FakeCommandRunner(VirtualFileSystem* fs) :
-      last_command_(NULL), fs_(fs) {}
+      max_active_edges_(1), fs_(fs) {}
 
   // CommandRunner impl
   virtual bool CanRunMore();
@@ -477,7 +477,8 @@
   virtual void Abort();
 
   vector<string> commands_ran_;
-  Edge* last_command_;
+  vector<Edge*> active_edges_;
+  size_t max_active_edges_;
   VirtualFileSystem* fs_;
 };
 
@@ -569,12 +570,13 @@
 }
 
 bool FakeCommandRunner::CanRunMore() {
-  // Only run one at a time.
-  return last_command_ == NULL;
+  return active_edges_.size() < max_active_edges_;
 }
 
 bool FakeCommandRunner::StartCommand(Edge* edge) {
-  assert(!last_command_);
+  assert(active_edges_.size() < max_active_edges_);
+  assert(find(active_edges_.begin(), active_edges_.end(), edge)
+         == active_edges_.end());
   commands_ran_.push_back(edge->EvaluateCommand());
   if (edge->rule().name() == "cat"  ||
       edge->rule().name() == "cat_rsp" ||
@@ -597,15 +599,25 @@
     return false;
   }
 
-  last_command_ = edge;
+  active_edges_.push_back(edge);
+
+  // Allow tests to control the order by the name of the first output.
+  sort(active_edges_.begin(), active_edges_.end(),
+       CompareEdgesByOutput::cmp);
+
   return true;
 }
 
 bool FakeCommandRunner::WaitForCommand(Result* result) {
-  if (!last_command_)
+  if (active_edges_.empty())
     return false;
 
-  Edge* edge = last_command_;
+  // All active edges were already completed immediately when started,
+  // so we can pick any edge here.  Pick the last edge.  Tests can
+  // control the order of edges by the name of the first output.
+  vector<Edge*>::iterator edge_iter = active_edges_.end() - 1;
+
+  Edge* edge = *edge_iter;
   result->edge = edge;
 
   if (edge->rule().name() == "interrupt" ||
@@ -619,7 +631,7 @@
       result->status = ExitSuccess;
     else
       result->status = ExitFailure;
-    last_command_ = NULL;
+    active_edges_.erase(edge_iter);
     return true;
   }
 
@@ -628,19 +640,33 @@
     result->status = ExitFailure;
   else
     result->status = ExitSuccess;
-  last_command_ = NULL;
+
+  // Provide a way for test cases to verify when an edge finishes that
+  // some other edge is still active.  This is useful for test cases
+  // covering behavior involving multiple active edges.
+  const string& verify_active_edge = edge->GetBinding("verify_active_edge");
+  if (!verify_active_edge.empty()) {
+    bool verify_active_edge_found = false;
+    for (vector<Edge*>::iterator i = active_edges_.begin();
+         i != active_edges_.end(); ++i) {
+      if ((*i)->outputs_.size() >= 1 &&
+          (*i)->outputs_[0]->path() == verify_active_edge) {
+        verify_active_edge_found = true;
+      }
+    }
+    EXPECT_TRUE(verify_active_edge_found);
+  }
+
+  active_edges_.erase(edge_iter);
   return true;
 }
 
 vector<Edge*> FakeCommandRunner::GetActiveEdges() {
-  vector<Edge*> edges;
-  if (last_command_)
-    edges.push_back(last_command_);
-  return edges;
+  return active_edges_;
 }
 
 void FakeCommandRunner::Abort() {
-  last_command_ = NULL;
+  active_edges_.clear();
 }
 
 void BuildTest::Dirty(const string& path) {