Index: mojo/common/handle_watcher_unittest.cc |
diff --git a/mojo/common/handle_watcher_unittest.cc b/mojo/common/handle_watcher_unittest.cc |
deleted file mode 100644 |
index 41d5ffbe52bd8744769f04c82e2b82e69075665e..0000000000000000000000000000000000000000 |
--- a/mojo/common/handle_watcher_unittest.cc |
+++ /dev/null |
@@ -1,483 +0,0 @@ |
-// Copyright 2013 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "mojo/common/handle_watcher.h" |
- |
-#include <string> |
- |
-#include "base/at_exit.h" |
-#include "base/auto_reset.h" |
-#include "base/bind.h" |
-#include "base/memory/scoped_vector.h" |
-#include "base/run_loop.h" |
-#include "base/test/simple_test_tick_clock.h" |
-#include "base/threading/thread.h" |
-#include "mojo/common/message_pump_mojo.h" |
-#include "mojo/common/time_helper.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
-#include "third_party/mojo/src/mojo/public/cpp/system/core.h" |
-#include "third_party/mojo/src/mojo/public/cpp/test_support/test_utils.h" |
- |
-namespace mojo { |
-namespace common { |
-namespace test { |
- |
-enum MessageLoopConfig { |
- MESSAGE_LOOP_CONFIG_DEFAULT = 0, |
- MESSAGE_LOOP_CONFIG_MOJO = 1 |
-}; |
- |
-void ObserveCallback(bool* was_signaled, |
- MojoResult* result_observed, |
- MojoResult result) { |
- *was_signaled = true; |
- *result_observed = result; |
-} |
- |
-void RunUntilIdle() { |
- base::RunLoop run_loop; |
- run_loop.RunUntilIdle(); |
-} |
- |
-void DeleteWatcherAndForwardResult( |
- HandleWatcher* watcher, |
- base::Callback<void(MojoResult)> next_callback, |
- MojoResult result) { |
- delete watcher; |
- next_callback.Run(result); |
-} |
- |
-scoped_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) { |
- scoped_ptr<base::MessageLoop> loop; |
- if (config == MESSAGE_LOOP_CONFIG_DEFAULT) |
- loop.reset(new base::MessageLoop()); |
- else |
- loop.reset(new base::MessageLoop(MessagePumpMojo::Create())); |
- return loop.Pass(); |
-} |
- |
-// Helper class to manage the callback and running the message loop waiting for |
-// message to be received. Typical usage is something like: |
-// Schedule callback returned from GetCallback(). |
-// RunUntilGotCallback(); |
-// EXPECT_TRUE(got_callback()); |
-// clear_callback(); |
-class CallbackHelper { |
- public: |
- CallbackHelper() |
- : got_callback_(false), |
- run_loop_(NULL), |
- weak_factory_(this) {} |
- ~CallbackHelper() {} |
- |
- // See description above |got_callback_|. |
- bool got_callback() const { return got_callback_; } |
- void clear_callback() { got_callback_ = false; } |
- |
- // Runs the current MessageLoop until the callback returned from GetCallback() |
- // is notified. |
- void RunUntilGotCallback() { |
- ASSERT_TRUE(run_loop_ == NULL); |
- base::RunLoop run_loop; |
- base::AutoReset<base::RunLoop*> reseter(&run_loop_, &run_loop); |
- run_loop.Run(); |
- } |
- |
- base::Callback<void(MojoResult)> GetCallback() { |
- return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr()); |
- } |
- |
- void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) { |
- StartWithCallback(watcher, handle, GetCallback()); |
- } |
- |
- void StartWithCallback(HandleWatcher* watcher, |
- const MessagePipeHandle& handle, |
- const base::Callback<void(MojoResult)>& callback) { |
- watcher->Start(handle, MOJO_HANDLE_SIGNAL_READABLE, |
- MOJO_DEADLINE_INDEFINITE, callback); |
- } |
- |
- private: |
- void OnCallback(MojoResult result) { |
- got_callback_ = true; |
- if (run_loop_) |
- run_loop_->Quit(); |
- } |
- |
- // Set to true when the callback is called. |
- bool got_callback_; |
- |
- // If non-NULL we're in RunUntilGotCallback(). |
- base::RunLoop* run_loop_; |
- |
- base::WeakPtrFactory<CallbackHelper> weak_factory_; |
- |
- private: |
- DISALLOW_COPY_AND_ASSIGN(CallbackHelper); |
-}; |
- |
-class HandleWatcherTest : public testing::TestWithParam<MessageLoopConfig> { |
- public: |
- HandleWatcherTest() : message_loop_(CreateMessageLoop(GetParam())) {} |
- virtual ~HandleWatcherTest() { |
- test::SetTickClockForTest(NULL); |
- } |
- |
- protected: |
- void TearDownMessageLoop() { |
- message_loop_.reset(); |
- } |
- |
- void InstallTickClock() { |
- test::SetTickClockForTest(&tick_clock_); |
- } |
- |
- base::SimpleTestTickClock tick_clock_; |
- |
- private: |
- base::ShadowingAtExitManager at_exit_; |
- scoped_ptr<base::MessageLoop> message_loop_; |
- |
- DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest); |
-}; |
- |
-INSTANTIATE_TEST_CASE_P( |
- MultipleMessageLoopConfigs, HandleWatcherTest, |
- testing::Values(MESSAGE_LOOP_CONFIG_DEFAULT, MESSAGE_LOOP_CONFIG_MOJO)); |
- |
-// Trivial test case with a single handle to watch. |
-TEST_P(HandleWatcherTest, SingleHandler) { |
- MessagePipe test_pipe; |
- ASSERT_TRUE(test_pipe.handle0.is_valid()); |
- CallbackHelper callback_helper; |
- HandleWatcher watcher; |
- callback_helper.Start(&watcher, test_pipe.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper.got_callback()); |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), |
- std::string())); |
- callback_helper.RunUntilGotCallback(); |
- EXPECT_TRUE(callback_helper.got_callback()); |
-} |
- |
-// Creates three handles and notfies them in reverse order ensuring each one is |
-// notified appropriately. |
-TEST_P(HandleWatcherTest, ThreeHandles) { |
- MessagePipe test_pipe1; |
- MessagePipe test_pipe2; |
- MessagePipe test_pipe3; |
- CallbackHelper callback_helper1; |
- CallbackHelper callback_helper2; |
- CallbackHelper callback_helper3; |
- ASSERT_TRUE(test_pipe1.handle0.is_valid()); |
- ASSERT_TRUE(test_pipe2.handle0.is_valid()); |
- ASSERT_TRUE(test_pipe3.handle0.is_valid()); |
- |
- HandleWatcher watcher1; |
- callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- EXPECT_FALSE(callback_helper3.got_callback()); |
- |
- HandleWatcher watcher2; |
- callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- EXPECT_FALSE(callback_helper3.got_callback()); |
- |
- HandleWatcher watcher3; |
- callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- EXPECT_FALSE(callback_helper3.got_callback()); |
- |
- // Write to 3 and make sure it's notified. |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), |
- std::string())); |
- callback_helper3.RunUntilGotCallback(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- EXPECT_TRUE(callback_helper3.got_callback()); |
- callback_helper3.clear_callback(); |
- |
- // Write to 1 and 3. Only 1 should be notified since 3 was is no longer |
- // running. |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), |
- std::string())); |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), |
- std::string())); |
- callback_helper1.RunUntilGotCallback(); |
- EXPECT_TRUE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- EXPECT_FALSE(callback_helper3.got_callback()); |
- callback_helper1.clear_callback(); |
- |
- // Write to 1 and 2. Only 2 should be notified (since 1 was already notified). |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), |
- std::string())); |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), |
- std::string())); |
- callback_helper2.RunUntilGotCallback(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_TRUE(callback_helper2.got_callback()); |
- EXPECT_FALSE(callback_helper3.got_callback()); |
-} |
- |
-// Verifies Start() invoked a second time works. |
-TEST_P(HandleWatcherTest, Restart) { |
- MessagePipe test_pipe1; |
- MessagePipe test_pipe2; |
- CallbackHelper callback_helper1; |
- CallbackHelper callback_helper2; |
- ASSERT_TRUE(test_pipe1.handle0.is_valid()); |
- ASSERT_TRUE(test_pipe2.handle0.is_valid()); |
- |
- HandleWatcher watcher1; |
- callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- |
- HandleWatcher watcher2; |
- callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- |
- // Write to 1 and make sure it's notified. |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), |
- std::string())); |
- callback_helper1.RunUntilGotCallback(); |
- EXPECT_TRUE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- callback_helper1.clear_callback(); |
- EXPECT_TRUE(mojo::test::DiscardMessage(test_pipe1.handle0.get())); |
- |
- // Write to 2 and make sure it's notified. |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), |
- std::string())); |
- callback_helper2.RunUntilGotCallback(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_TRUE(callback_helper2.got_callback()); |
- callback_helper2.clear_callback(); |
- |
- // Listen on 1 again. |
- callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- |
- // Write to 1 and make sure it's notified. |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), |
- std::string())); |
- callback_helper1.RunUntilGotCallback(); |
- EXPECT_TRUE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
-} |
- |
-// Verifies Start() invoked a second time on the same handle works. |
-TEST_P(HandleWatcherTest, RestartOnSameHandle) { |
- MessagePipe test_pipe; |
- CallbackHelper callback_helper; |
- ASSERT_TRUE(test_pipe.handle0.is_valid()); |
- |
- HandleWatcher watcher; |
- callback_helper.Start(&watcher, test_pipe.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper.got_callback()); |
- |
- callback_helper.Start(&watcher, test_pipe.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper.got_callback()); |
-} |
- |
-// Verifies deadline is honored. |
-TEST_P(HandleWatcherTest, Deadline) { |
- InstallTickClock(); |
- |
- MessagePipe test_pipe1; |
- MessagePipe test_pipe2; |
- MessagePipe test_pipe3; |
- CallbackHelper callback_helper1; |
- CallbackHelper callback_helper2; |
- CallbackHelper callback_helper3; |
- ASSERT_TRUE(test_pipe1.handle0.is_valid()); |
- ASSERT_TRUE(test_pipe2.handle0.is_valid()); |
- ASSERT_TRUE(test_pipe3.handle0.is_valid()); |
- |
- // Add a watcher with an infinite timeout. |
- HandleWatcher watcher1; |
- callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- EXPECT_FALSE(callback_helper3.got_callback()); |
- |
- // Add another watcher wth a timeout of 500 microseconds. |
- HandleWatcher watcher2; |
- watcher2.Start(test_pipe2.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 500, |
- callback_helper2.GetCallback()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_FALSE(callback_helper2.got_callback()); |
- EXPECT_FALSE(callback_helper3.got_callback()); |
- |
- // Advance the clock passed the deadline. We also have to start another |
- // watcher to wake up the background thread. |
- tick_clock_.Advance(base::TimeDelta::FromMicroseconds(501)); |
- |
- HandleWatcher watcher3; |
- callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); |
- |
- callback_helper2.RunUntilGotCallback(); |
- EXPECT_FALSE(callback_helper1.got_callback()); |
- EXPECT_TRUE(callback_helper2.got_callback()); |
- EXPECT_FALSE(callback_helper3.got_callback()); |
-} |
- |
-TEST_P(HandleWatcherTest, DeleteInCallback) { |
- MessagePipe test_pipe; |
- CallbackHelper callback_helper; |
- |
- HandleWatcher* watcher = new HandleWatcher(); |
- callback_helper.StartWithCallback(watcher, test_pipe.handle1.get(), |
- base::Bind(&DeleteWatcherAndForwardResult, |
- watcher, |
- callback_helper.GetCallback())); |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle0.get(), |
- std::string())); |
- callback_helper.RunUntilGotCallback(); |
- EXPECT_TRUE(callback_helper.got_callback()); |
-} |
- |
-TEST_P(HandleWatcherTest, AbortedOnMessageLoopDestruction) { |
- bool was_signaled = false; |
- MojoResult result = MOJO_RESULT_OK; |
- |
- MessagePipe pipe; |
- HandleWatcher watcher; |
- watcher.Start(pipe.handle0.get(), |
- MOJO_HANDLE_SIGNAL_READABLE, |
- MOJO_DEADLINE_INDEFINITE, |
- base::Bind(&ObserveCallback, &was_signaled, &result)); |
- |
- // Now, let the MessageLoop get torn down. We expect our callback to run. |
- TearDownMessageLoop(); |
- |
- EXPECT_TRUE(was_signaled); |
- EXPECT_EQ(MOJO_RESULT_ABORTED, result); |
-} |
- |
-void NeverReached(MojoResult result) { |
- FAIL() << "Callback should never be invoked " << result; |
-} |
- |
-// Called on the main thread when a thread is done. Decrements |active_count| |
-// and if |active_count| is zero quits |run_loop|. |
-void StressThreadDone(base::RunLoop* run_loop, int* active_count) { |
- (*active_count)--; |
- EXPECT_GE(*active_count, 0); |
- if (*active_count == 0) |
- run_loop->Quit(); |
-} |
- |
-// See description of StressTest. This is called on the background thread. |
-// |count| is the number of HandleWatchers to create. |active_count| is the |
-// number of outstanding threads, |task_runner| the task runner for the main |
-// thread and |run_loop| the run loop that should be quit when there are no more |
-// threads running. When done StressThreadDone() is invoked on the main thread. |
-// |active_count| and |run_loop| should only be used on the main thread. |
-void RunStressTest(int count, |
- scoped_refptr<base::TaskRunner> task_runner, |
- base::RunLoop* run_loop, |
- int* active_count) { |
- struct TestData { |
- MessagePipe pipe; |
- HandleWatcher watcher; |
- }; |
- ScopedVector<TestData> data_vector; |
- for (int i = 0; i < count; ++i) { |
- if (i % 20 == 0) { |
- // Every so often we wait. This results in some level of thread balancing |
- // as well as making sure HandleWatcher has time to actually start some |
- // watches. |
- MessagePipe test_pipe; |
- ASSERT_TRUE(test_pipe.handle0.is_valid()); |
- CallbackHelper callback_helper; |
- HandleWatcher watcher; |
- callback_helper.Start(&watcher, test_pipe.handle0.get()); |
- RunUntilIdle(); |
- EXPECT_FALSE(callback_helper.got_callback()); |
- EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), |
- std::string())); |
- base::MessageLoop::ScopedNestableTaskAllower scoper( |
- base::MessageLoop::current()); |
- callback_helper.RunUntilGotCallback(); |
- EXPECT_TRUE(callback_helper.got_callback()); |
- } else { |
- scoped_ptr<TestData> test_data(new TestData); |
- ASSERT_TRUE(test_data->pipe.handle0.is_valid()); |
- test_data->watcher.Start(test_data->pipe.handle0.get(), |
- MOJO_HANDLE_SIGNAL_READABLE, |
- MOJO_DEADLINE_INDEFINITE, |
- base::Bind(&NeverReached)); |
- data_vector.push_back(test_data.release()); |
- } |
- if (i % 15 == 0) |
- data_vector.clear(); |
- } |
- task_runner->PostTask(FROM_HERE, |
- base::Bind(&StressThreadDone, run_loop, |
- active_count)); |
-} |
- |
-// This test is meant to stress HandleWatcher. It uses from various threads |
-// repeatedly starting and stopping watches. It spins up kThreadCount |
-// threads. Each thread creates kWatchCount watches. Every so often each thread |
-// writes to a pipe and waits for the response. |
-TEST(HandleWatcherCleanEnvironmentTest, StressTest) { |
-#if defined(NDEBUG) |
- const int kThreadCount = 15; |
- const int kWatchCount = 400; |
-#else |
- const int kThreadCount = 10; |
- const int kWatchCount = 250; |
-#endif |
- |
- base::ShadowingAtExitManager at_exit; |
- base::MessageLoop message_loop; |
- base::RunLoop run_loop; |
- ScopedVector<base::Thread> threads; |
- int threads_active_counter = kThreadCount; |
- // Starts the threads first and then post the task in hopes of having more |
- // threads running at once. |
- for (int i = 0; i < kThreadCount; ++i) { |
- scoped_ptr<base::Thread> thread(new base::Thread("test thread")); |
- if (i % 2) { |
- base::Thread::Options thread_options; |
- thread_options.message_pump_factory = |
- base::Bind(&MessagePumpMojo::Create); |
- thread->StartWithOptions(thread_options); |
- } else { |
- thread->Start(); |
- } |
- threads.push_back(thread.release()); |
- } |
- for (int i = 0; i < kThreadCount; ++i) { |
- threads[i]->task_runner()->PostTask( |
- FROM_HERE, base::Bind(&RunStressTest, kWatchCount, |
- message_loop.task_runner(), |
- &run_loop, &threads_active_counter)); |
- } |
- run_loop.Run(); |
- ASSERT_EQ(0, threads_active_counter); |
-} |
- |
-} // namespace test |
-} // namespace common |
-} // namespace mojo |