EDK: Make ConnectionManagerTest not use base::MessageLoop/RunLoop.

Also add a QuitNow() method to mojo::platform::MessageLoop. I guess we
do need it.

R=vardhan@google.com

Review URL: https://codereview.chromium.org/1465203003 .
diff --git a/mojo/edk/base_edk/platform_message_loop_impl.cc b/mojo/edk/base_edk/platform_message_loop_impl.cc
index d8752ce..717d634 100644
--- a/mojo/edk/base_edk/platform_message_loop_impl.cc
+++ b/mojo/edk/base_edk/platform_message_loop_impl.cc
@@ -39,6 +39,10 @@
   base_message_loop_.QuitWhenIdle();
 }
 
+void PlatformMessageLoopImpl::QuitNow() {
+  base_message_loop_.QuitNow();
+}
+
 const RefPtr<TaskRunner>& PlatformMessageLoopImpl::GetTaskRunner() const {
   return task_runner_;
 }
diff --git a/mojo/edk/base_edk/platform_message_loop_impl.h b/mojo/edk/base_edk/platform_message_loop_impl.h
index a25b013..ae6b0a0 100644
--- a/mojo/edk/base_edk/platform_message_loop_impl.h
+++ b/mojo/edk/base_edk/platform_message_loop_impl.h
@@ -32,6 +32,7 @@
   void Run() override;
   void RunUntilIdle() override;
   void QuitWhenIdle() override;
+  void QuitNow() override;
   const mojo::util::RefPtr<mojo::platform::TaskRunner>& GetTaskRunner()
       const override;
   bool IsRunningOnCurrentThread() const override;
diff --git a/mojo/edk/base_edk/platform_message_loop_impl_unittest.cc b/mojo/edk/base_edk/platform_message_loop_impl_unittest.cc
index e5ea2e9..e74dcc4 100644
--- a/mojo/edk/base_edk/platform_message_loop_impl_unittest.cc
+++ b/mojo/edk/base_edk/platform_message_loop_impl_unittest.cc
@@ -69,6 +69,20 @@
   EXPECT_EQ(std::vector<int>({4, 5, 6}), stuff);
 
   stuff.clear();
+  task_runner->PostTask(ToClosure([&stuff, &message_loop, &task_runner]() {
+    EXPECT_TRUE(message_loop.IsRunningOnCurrentThread());
+    stuff.push_back(7);
+    message_loop.QuitNow();
+    task_runner->PostTask(ToClosure([&stuff]() { stuff.push_back(9); }));
+  }));
+  task_runner->PostTask(ToClosure([&stuff]() { stuff.push_back(8); }));
+  message_loop.Run();
+  EXPECT_EQ(std::vector<int>({7}), stuff);
+  stuff.clear();
+  message_loop.RunUntilIdle();
+  EXPECT_EQ(std::vector<int>({8, 9}), stuff);
+
+  stuff.clear();
   message_loop.RunUntilIdle();
   EXPECT_TRUE(stuff.empty());
 
@@ -86,19 +100,19 @@
     std::thread other_thread([&stuff, &message_loop, task_runner]() {
       EXPECT_FALSE(message_loop.IsRunningOnCurrentThread());
       EXPECT_EQ(task_runner, message_loop.GetTaskRunner());
-      stuff.push_back(7);
+      stuff.push_back(10);
       task_runner->PostTask(ToClosure([&stuff, &message_loop]() {
         EXPECT_TRUE(message_loop.IsRunningOnCurrentThread());
-        stuff.push_back(8);
+        stuff.push_back(11);
         message_loop.QuitWhenIdle();
       }));
     });
     other_thread.join();
-    EXPECT_EQ(std::vector<int>({7}), stuff);
+    EXPECT_EQ(std::vector<int>({10}), stuff);
     stuff.clear();
   }));
   message_loop.Run();
-  EXPECT_EQ(std::vector<int>({8}), stuff);
+  EXPECT_EQ(std::vector<int>({11}), stuff);
 }
 
 TEST(PlatformMessageLoopImpl, TypeIO) {
diff --git a/mojo/edk/platform/message_loop.h b/mojo/edk/platform/message_loop.h
index ad50177..4d6ae15 100644
--- a/mojo/edk/platform/message_loop.h
+++ b/mojo/edk/platform/message_loop.h
@@ -28,20 +28,24 @@
  public:
   virtual ~MessageLoop() {}
 
-  // Runs the message loop until it is told to quit (via |QuitWhenIdle()|).
+  // Runs the message loop until it is told to quit (via |QuitNow() or
+  // |QuitWhenIdle()|).
   virtual void Run() = 0;
 
   // Runs the message loop until there are no more tasks available to execute
   // immediately (i.e., not including delayed tasks).
   virtual void RunUntilIdle() = 0;
 
-  // Quits the message loop when there are no more tasks available to execute
-  // immediately. (Note that this includes "future" tasks, i.e., those that are
-  // posted as a result of executing other tasks, so this may never quit.
-  // However, it does not include delayed tasks.)
-  // TODO(vtl): Do we also want a |QuitNow()|?
+  // If running, quits the message loop when there are no more tasks available
+  // to execute immediately. (Note that this includes "future" tasks, i.e.,
+  // those that are posted as a result of executing other tasks, so this may
+  // never quit. However, it does not include delayed tasks.)
   virtual void QuitWhenIdle() = 0;
 
+  // If running, quits the message loop now (i.e., do not process any further
+  // tasks until |Run()| or |RunUntilIdle()|) is called again.
+  virtual void QuitNow() = 0;
+
   // Gets the |TaskRunner| for this message loop, which can be used to post
   // tasks to it. For a given |MessageLoop| instance, this will always return a
   // reference to the same |TaskRunner| (and different |MessageLoop| instances
diff --git a/mojo/edk/system/BUILD.gn b/mojo/edk/system/BUILD.gn
index d76668c..0a27354 100644
--- a/mojo/edk/system/BUILD.gn
+++ b/mojo/edk/system/BUILD.gn
@@ -175,6 +175,7 @@
 
   mojo_edk_deps = [
     "mojo/edk/base_edk",
+    "mojo/edk/base_edk:test_base_edk",
     "mojo/edk/system/test",
     "mojo/edk/test:test_support",
     "mojo/edk/util",
diff --git a/mojo/edk/system/connection_manager_unittest.cc b/mojo/edk/system/connection_manager_unittest.cc
index c28e67c..8e2e219 100644
--- a/mojo/edk/system/connection_manager_unittest.cc
+++ b/mojo/edk/system/connection_manager_unittest.cc
@@ -9,16 +9,17 @@
 
 #include <stdint.h>
 
+#include <memory>
 #include <string>
 
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
 #include "base/threading/thread_checker.h"
 #include "mojo/edk/base_edk/platform_task_runner_impl.h"
 #include "mojo/edk/embedder/master_process_delegate.h"
 #include "mojo/edk/embedder/platform_channel_pair.h"
 #include "mojo/edk/embedder/simple_platform_support.h"
 #include "mojo/edk/embedder/slave_process_delegate.h"
+#include "mojo/edk/platform/message_loop.h"
+#include "mojo/edk/platform/test_message_loop.h"
 #include "mojo/edk/system/master_connection_manager.h"
 #include "mojo/edk/system/slave_connection_manager.h"
 #include "mojo/edk/test/test_utils.h"
@@ -26,7 +27,9 @@
 #include "mojo/public/cpp/system/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using mojo::platform::MessageLoop;
 using mojo::platform::TaskRunner;
+using mojo::platform::test::CreateTestMessageLoop;
 using mojo::util::MakeRefCounted;
 using mojo::util::RefPtr;
 
@@ -87,15 +90,14 @@
 class MockMasterProcessDelegate : public embedder::MasterProcessDelegate {
  public:
   MockMasterProcessDelegate()
-      : current_run_loop_(), on_slave_disconnect_calls_(0) {}
+      : current_message_loop_(), on_slave_disconnect_calls_(0) {}
   ~MockMasterProcessDelegate() override {}
 
-  void RunUntilNotified() {
-    CHECK(!current_run_loop_);
-    base::RunLoop run_loop;
-    current_run_loop_ = &run_loop;
-    run_loop.Run();
-    current_run_loop_ = nullptr;
+  void RunUntilNotified(MessageLoop* message_loop) {
+    CHECK(!current_message_loop_);
+    current_message_loop_ = message_loop;
+    message_loop->Run();
+    current_message_loop_ = nullptr;
   }
 
   unsigned on_slave_disconnect_calls() const {
@@ -117,13 +119,13 @@
              << last_slave_disconnect_name_;
     delete static_cast<TestSlaveInfo*>(slave_info);
 
-    if (current_run_loop_)
-      current_run_loop_->Quit();
+    if (current_message_loop_)
+      current_message_loop_->QuitNow();
   }
 
  private:
   base::ThreadChecker thread_checker_;
-  base::RunLoop* current_run_loop_;
+  MessageLoop* current_message_loop_;
 
   unsigned on_slave_disconnect_calls_;
   std::string last_slave_disconnect_name_;
@@ -134,15 +136,14 @@
 class MockSlaveProcessDelegate : public embedder::SlaveProcessDelegate {
  public:
   MockSlaveProcessDelegate()
-      : current_run_loop_(), on_master_disconnect_calls_(0) {}
+      : current_message_loop_(), on_master_disconnect_calls_(0) {}
   ~MockSlaveProcessDelegate() override {}
 
-  void RunUntilNotified() {
-    CHECK(!current_run_loop_);
-    base::RunLoop run_loop;
-    current_run_loop_ = &run_loop;
-    run_loop.Run();
-    current_run_loop_ = nullptr;
+  void RunUntilNotified(MessageLoop* message_loop) {
+    CHECK(!current_message_loop_);
+    current_message_loop_ = message_loop;
+    message_loop->Run();
+    current_message_loop_ = nullptr;
   }
 
   unsigned on_master_disconnect_calls() const {
@@ -157,13 +158,13 @@
     on_master_disconnect_calls_++;
     DVLOG(1) << "Disconnected from master process";
 
-    if (current_run_loop_)
-      current_run_loop_->Quit();
+    if (current_message_loop_)
+      current_message_loop_->QuitNow();
   }
 
  private:
   base::ThreadChecker thread_checker_;
-  base::RunLoop* current_run_loop_;
+  MessageLoop* current_message_loop_;
 
   unsigned on_master_disconnect_calls_;
 
@@ -172,13 +173,14 @@
 
 class ConnectionManagerTest : public testing::Test {
  protected:
-  ConnectionManagerTest()
-      : task_runner_(MakeRefCounted<base_edk::PlatformTaskRunnerImpl>(
-            message_loop_.task_runner())) {}
+  ConnectionManagerTest() : message_loop_(CreateTestMessageLoop()) {}
   ~ConnectionManagerTest() override {}
 
   embedder::PlatformSupport* platform_support() { return &platform_support_; }
-  const RefPtr<TaskRunner>& task_runner() { return task_runner_; }
+  MessageLoop* message_loop() { return message_loop_.get(); }
+  const RefPtr<TaskRunner>& task_runner() {
+    return message_loop_->GetTaskRunner();
+  }
   MockMasterProcessDelegate& master_process_delegate() {
     return master_process_delegate_;
   }
@@ -195,15 +197,14 @@
     ProcessIdentifier slave_process_identifier =
         master->AddSlave(new TestSlaveInfo(slave_name),
                          platform_channel_pair.PassServerHandle());
-    slave->Init(task_runner_.Clone(), slave_process_delegate,
+    slave->Init(task_runner().Clone(), slave_process_delegate,
                 platform_channel_pair.PassClientHandle());
     return slave_process_identifier;
   }
 
  private:
   embedder::SimplePlatformSupport platform_support_;
-  base::MessageLoop message_loop_;
-  RefPtr<TaskRunner> task_runner_;
+  std::unique_ptr<MessageLoop> message_loop_;
   MockMasterProcessDelegate master_process_delegate_;
 
   MOJO_DISALLOW_COPY_AND_ASSIGN(ConnectionManagerTest);
@@ -252,27 +253,27 @@
 
   // The process manager shouldn't have gotten any notifications yet. (Spin the
   // message loop to make sure none were enqueued.)
-  base::RunLoop().RunUntilIdle();
+  message_loop()->RunUntilIdle();
   EXPECT_EQ(0u, master_process_delegate().on_slave_disconnect_calls());
 
   slave1.Shutdown();
 
   // |OnSlaveDisconnect()| should be called once.
-  master_process_delegate().RunUntilNotified();
+  master_process_delegate().RunUntilNotified(message_loop());
   EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls());
   EXPECT_EQ("slave1", master_process_delegate().last_slave_disconnect_name());
 
   slave2.Shutdown();
 
   // |OnSlaveDisconnect()| should be called again.
-  master_process_delegate().RunUntilNotified();
+  master_process_delegate().RunUntilNotified(message_loop());
   EXPECT_EQ(2u, master_process_delegate().on_slave_disconnect_calls());
   EXPECT_EQ("slave2", master_process_delegate().last_slave_disconnect_name());
 
   master.Shutdown();
 
   // None of the above should result in |OnMasterDisconnect()| being called.
-  base::RunLoop().RunUntilIdle();
+  message_loop()->RunUntilIdle();
   EXPECT_EQ(0u, slave1_process_delegate.on_master_disconnect_calls());
   EXPECT_EQ(0u, slave2_process_delegate.on_master_disconnect_calls());
 }
@@ -289,18 +290,18 @@
 
   // The process manager shouldn't have gotten any notifications yet. (Spin the
   // message loop to make sure none were enqueued.)
-  base::RunLoop().RunUntilIdle();
+  message_loop()->RunUntilIdle();
   EXPECT_EQ(0u, master_process_delegate().on_slave_disconnect_calls());
 
   master.Shutdown();
 
   // |OnSlaveDisconnect()| should be called.
-  master_process_delegate().RunUntilNotified();
+  master_process_delegate().RunUntilNotified(message_loop());
   EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls());
   EXPECT_EQ("slave", master_process_delegate().last_slave_disconnect_name());
 
   // |OnMasterDisconnect()| should also be (or have been) called.
-  slave_process_delegate.RunUntilNotified();
+  slave_process_delegate.RunUntilNotified(message_loop());
   EXPECT_EQ(1u, slave_process_delegate.on_master_disconnect_calls());
 
   slave.Shutdown();
@@ -369,7 +370,7 @@
   // |OnSlaveDisconnect()| should be called. After it's called, this means that
   // the disconnect has been detected and handled, including the removal of the
   // pending connection.
-  master_process_delegate().RunUntilNotified();
+  master_process_delegate().RunUntilNotified(message_loop());
   EXPECT_EQ(1u, master_process_delegate().on_slave_disconnect_calls());
 
   ProcessIdentifier peer2 = kInvalidProcessIdentifier;