Index: remoting/host/setup/me2me_native_messaging_host_unittest.cc |
diff --git a/remoting/host/setup/me2me_native_messaging_host_unittest.cc b/remoting/host/setup/me2me_native_messaging_host_unittest.cc |
index dfa04d769e7e1f02ae482050c7e653ee22a84252..b43b270beeac3e4d7d3748266d249203d36fb960 100644 |
--- a/remoting/host/setup/me2me_native_messaging_host_unittest.cc |
+++ b/remoting/host/setup/me2me_native_messaging_host_unittest.cc |
@@ -222,11 +222,6 @@ class NativeMessagingHostTest : public testing::Test { |
virtual void SetUp() OVERRIDE; |
virtual void TearDown() OVERRIDE; |
- void Run(); |
- |
- // Deletes |host_|. |
- void DeleteHost(); |
- |
scoped_ptr<base::DictionaryValue> ReadMessageFromOutputPipe(); |
void WriteMessageToInputPipe(const base::Value& message); |
@@ -243,6 +238,10 @@ class NativeMessagingHostTest : public testing::Test { |
MockDaemonControllerDelegate* daemon_controller_delegate_; |
private: |
+ void StartHost(); |
+ void StopHost(); |
+ void ExitTest(); |
+ |
// Each test creates two unidirectional pipes: "input" and "output". |
// NativeMessagingHost reads from input_read_handle and writes to |
// output_write_handle. The unittest supplies data to input_write_handle, and |
@@ -252,16 +251,21 @@ class NativeMessagingHostTest : public testing::Test { |
base::PlatformFile input_write_handle_; |
base::PlatformFile output_read_handle_; |
- base::MessageLoop message_loop_; |
- base::RunLoop run_loop_; |
- scoped_refptr<AutoThreadTaskRunner> task_runner_; |
- scoped_ptr<remoting::NativeMessagingChannel> channel_; |
+ // Message loop of the test thread. |
+ scoped_ptr<base::MessageLoop> test_message_loop_; |
+ scoped_ptr<base::RunLoop> test_run_loop_; |
+ |
+ scoped_ptr<base::Thread> host_thread_; |
+ scoped_ptr<base::RunLoop> host_run_loop_; |
+ |
+ // Task runner of the host thread. |
+ scoped_refptr<AutoThreadTaskRunner> host_task_runner_; |
+ scoped_ptr<remoting::NativeMessagingHost> host_; |
DISALLOW_COPY_AND_ASSIGN(NativeMessagingHostTest); |
}; |
-NativeMessagingHostTest::NativeMessagingHostTest() |
- : message_loop_(base::MessageLoop::TYPE_IO) {} |
+NativeMessagingHostTest::NativeMessagingHostTest() {} |
NativeMessagingHostTest::~NativeMessagingHostTest() {} |
@@ -272,9 +276,35 @@ void NativeMessagingHostTest::SetUp() { |
ASSERT_TRUE(MakePipe(&input_read_handle, &input_write_handle_)); |
ASSERT_TRUE(MakePipe(&output_read_handle_, &output_write_handle)); |
- // Arrange to run |message_loop_| until no components depend on it. |
- task_runner_ = new AutoThreadTaskRunner( |
- message_loop_.message_loop_proxy(), run_loop_.QuitClosure()); |
+ test_message_loop_.reset(new base::MessageLoop()); |
+ test_run_loop_.reset(new base::RunLoop()); |
+ |
+ // Run the host on a dedicated thread. |
+ host_thread_.reset(new base::Thread("host_thread")); |
+ host_thread_->Start(); |
+ |
+ // Arrange to run |test_message_loop_| until no components depend on it. |
+ host_task_runner_ = new AutoThreadTaskRunner( |
+ host_thread_->message_loop_proxy(), |
+ base::Bind(&NativeMessagingHostTest::ExitTest, |
+ base::Unretained(this))); |
+ |
+ host_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&NativeMessagingHostTest::StartHost, base::Unretained(this))); |
+ |
+ // Wait until the host finishes starting. |
+ test_run_loop_->Run(); |
+} |
+ |
+void NativeMessagingHostTest::StartHost() { |
+ DCHECK(host_task_runner_->RunsTasksOnCurrentThread()); |
+ |
+ base::PlatformFile input_read_handle; |
+ base::PlatformFile output_write_handle; |
+ |
+ ASSERT_TRUE(MakePipe(&input_read_handle, &input_write_handle_)); |
+ ASSERT_TRUE(MakePipe(&output_read_handle_, &output_write_handle)); |
daemon_controller_delegate_ = new MockDaemonControllerDelegate(); |
scoped_refptr<DaemonController> daemon_controller( |
@@ -284,42 +314,61 @@ void NativeMessagingHostTest::SetUp() { |
scoped_refptr<PairingRegistry> pairing_registry = |
new SynchronousPairingRegistry(scoped_ptr<PairingRegistry::Delegate>( |
new MockPairingRegistryDelegate())); |
- scoped_ptr<NativeMessagingChannel::Delegate> host( |
- new NativeMessagingHost(daemon_controller, |
- pairing_registry, |
- scoped_ptr<remoting::OAuthClient>())); |
- channel_.reset( |
- new NativeMessagingChannel(host.Pass(), |
- input_read_handle, |
- output_write_handle)); |
+ |
+ scoped_ptr<NativeMessagingChannel> channel( |
+ new NativeMessagingChannel(input_read_handle, output_write_handle)); |
+ |
+ host_.reset(new NativeMessagingHost(channel.Pass(), |
+ daemon_controller, |
+ pairing_registry, |
+ scoped_ptr<remoting::OAuthClient>())); |
+ host_->Start(base::Bind(&NativeMessagingHostTest::StopHost, |
+ base::Unretained(this))); |
+ |
+ // Notify the test that the host has finished starting up. |
+ test_message_loop_->message_loop_proxy()->PostTask( |
+ FROM_HERE, test_run_loop_->QuitClosure()); |
} |
-void NativeMessagingHostTest::TearDown() { |
- // DaemonController destroys its internals asynchronously. Let these and any |
- // other pending tasks run to make sure we don't leak the memory owned by |
- // them. |
- message_loop_.RunUntilIdle(); |
- |
- // The NativeMessagingHost dtor closes the handles that are passed to it. |
- // |input_write_handle_| gets closed just before starting the host. So the |
- // only handle left to close is |output_read_handle_|. |
- base::ClosePlatformFile(output_read_handle_); |
+void NativeMessagingHostTest::StopHost() { |
+ DCHECK(host_task_runner_->RunsTasksOnCurrentThread()); |
+ |
+ host_.reset(); |
+ |
+ // Wait till all shutdown tasks have completed. |
+ base::MessageLoop::current()->RunUntilIdle(); |
+ |
+ // Trigger a test shutdown via ExitTest(). |
+ host_task_runner_ = NULL; |
} |
-void NativeMessagingHostTest::Run() { |
- // Close the write-end of input, so that the host sees EOF after reading |
- // messages and won't block waiting for more input. |
- base::ClosePlatformFile(input_write_handle_); |
- channel_->Start(base::Bind(&NativeMessagingHostTest::DeleteHost, |
- base::Unretained(this))); |
- run_loop_.Run(); |
+void NativeMessagingHostTest::ExitTest() { |
+ if (!test_message_loop_->message_loop_proxy()->RunsTasksOnCurrentThread()) { |
+ test_message_loop_->message_loop_proxy()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&NativeMessagingHostTest::ExitTest, |
+ base::Unretained(this))); |
+ return; |
+ } |
+ test_run_loop_->Quit(); |
} |
-void NativeMessagingHostTest::DeleteHost() { |
- // Destroy |channel_| so that it closes its end of the output pipe, so that |
- // TestBadRequest() will see EOF and won't block waiting for more data. |
- channel_.reset(); |
- task_runner_ = NULL; |
+void NativeMessagingHostTest::TearDown() { |
+ // Closing the write-end of the input will send an EOF to the native |
+ // messaging reader. This will trigger a host shutdown. |
+ base::ClosePlatformFile(input_write_handle_); |
+ |
+ // Start a new RunLoop and Wait until the host finishes shutting down. |
+ test_run_loop_.reset(new base::RunLoop()); |
+ test_run_loop_->Run(); |
+ |
+ // Verify there are no more message in the output pipe. |
+ scoped_ptr<base::DictionaryValue> response = ReadMessageFromOutputPipe(); |
+ EXPECT_FALSE(response); |
+ |
+ // The It2MeNativeMessagingHost dtor closes the handles that are passed to it. |
+ // So the only handle left to close is |output_read_handle_|. |
+ base::ClosePlatformFile(output_read_handle_); |
} |
scoped_ptr<base::DictionaryValue> |
@@ -370,8 +419,6 @@ void NativeMessagingHostTest::TestBadRequest(const base::Value& message) { |
WriteMessageToInputPipe(message); |
WriteMessageToInputPipe(good_message); |
- Run(); |
- |
// Read from output pipe, and verify responses. |
scoped_ptr<base::DictionaryValue> response = |
ReadMessageFromOutputPipe(); |
@@ -383,7 +430,7 @@ void NativeMessagingHostTest::TestBadRequest(const base::Value& message) { |
// TODO (weitaosu): crbug.com/323306. Re-enable these tests. |
// Test all valid request-types. |
-TEST_F(NativeMessagingHostTest, DISABLED_All) { |
+TEST_F(NativeMessagingHostTest, All) { |
int next_id = 0; |
base::DictionaryValue message; |
message.SetInteger("id", next_id++); |
@@ -437,8 +484,6 @@ TEST_F(NativeMessagingHostTest, DISABLED_All) { |
message.SetString("type", "startDaemon"); |
WriteMessageToInputPipe(message); |
- Run(); |
- |
void (*verify_routines[])(scoped_ptr<base::DictionaryValue>) = { |
&VerifyHelloResponse, |
&VerifyGetHostNameResponse, |
@@ -472,15 +517,13 @@ TEST_F(NativeMessagingHostTest, DISABLED_All) { |
} |
// Verify that response ID matches request ID. |
-TEST_F(NativeMessagingHostTest, DISABLED_Id) { |
+TEST_F(NativeMessagingHostTest, Id) { |
base::DictionaryValue message; |
message.SetString("type", "hello"); |
WriteMessageToInputPipe(message); |
message.SetString("id", "42"); |
WriteMessageToInputPipe(message); |
- Run(); |
- |
scoped_ptr<base::DictionaryValue> response = |
ReadMessageFromOutputPipe(); |
EXPECT_TRUE(response); |
@@ -494,26 +537,26 @@ TEST_F(NativeMessagingHostTest, DISABLED_Id) { |
} |
// Verify non-Dictionary requests are rejected. |
-TEST_F(NativeMessagingHostTest, DISABLED_WrongFormat) { |
+TEST_F(NativeMessagingHostTest, WrongFormat) { |
base::ListValue message; |
TestBadRequest(message); |
} |
// Verify requests with no type are rejected. |
-TEST_F(NativeMessagingHostTest, DISABLED_MissingType) { |
+TEST_F(NativeMessagingHostTest, MissingType) { |
base::DictionaryValue message; |
TestBadRequest(message); |
} |
// Verify rejection if type is unrecognized. |
-TEST_F(NativeMessagingHostTest, DISABLED_InvalidType) { |
+TEST_F(NativeMessagingHostTest, InvalidType) { |
base::DictionaryValue message; |
message.SetString("type", "xxx"); |
TestBadRequest(message); |
} |
// Verify rejection if getPinHash request has no hostId. |
-TEST_F(NativeMessagingHostTest, DISABLED_GetPinHashNoHostId) { |
+TEST_F(NativeMessagingHostTest, GetPinHashNoHostId) { |
base::DictionaryValue message; |
message.SetString("type", "getPinHash"); |
message.SetString("pin", "1234"); |
@@ -521,7 +564,7 @@ TEST_F(NativeMessagingHostTest, DISABLED_GetPinHashNoHostId) { |
} |
// Verify rejection if getPinHash request has no pin. |
-TEST_F(NativeMessagingHostTest, DISABLED_GetPinHashNoPin) { |
+TEST_F(NativeMessagingHostTest, GetPinHashNoPin) { |
base::DictionaryValue message; |
message.SetString("type", "getPinHash"); |
message.SetString("hostId", "my_host"); |
@@ -529,7 +572,7 @@ TEST_F(NativeMessagingHostTest, DISABLED_GetPinHashNoPin) { |
} |
// Verify rejection if updateDaemonConfig request has invalid config. |
-TEST_F(NativeMessagingHostTest, DISABLED_UpdateDaemonConfigInvalidConfig) { |
+TEST_F(NativeMessagingHostTest, UpdateDaemonConfigInvalidConfig) { |
base::DictionaryValue message; |
message.SetString("type", "updateDaemonConfig"); |
message.SetString("config", "xxx"); |
@@ -537,7 +580,7 @@ TEST_F(NativeMessagingHostTest, DISABLED_UpdateDaemonConfigInvalidConfig) { |
} |
// Verify rejection if startDaemon request has invalid config. |
-TEST_F(NativeMessagingHostTest, DISABLED_StartDaemonInvalidConfig) { |
+TEST_F(NativeMessagingHostTest, StartDaemonInvalidConfig) { |
base::DictionaryValue message; |
message.SetString("type", "startDaemon"); |
message.SetString("config", "xxx"); |
@@ -546,7 +589,7 @@ TEST_F(NativeMessagingHostTest, DISABLED_StartDaemonInvalidConfig) { |
} |
// Verify rejection if startDaemon request has no "consent" parameter. |
-TEST_F(NativeMessagingHostTest, DISABLED_StartDaemonNoConsent) { |
+TEST_F(NativeMessagingHostTest, StartDaemonNoConsent) { |
base::DictionaryValue message; |
message.SetString("type", "startDaemon"); |
message.Set("config", base::DictionaryValue().DeepCopy()); |