| // Copyright 2015 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/message_pump/handle_watcher.h" |
| |
| #include <string> |
| |
| #include "base/auto_reset.h" |
| #include "base/bind.h" |
| #include "base/memory/scoped_vector.h" |
| #include "base/run_loop.h" |
| #include "base/time/time.h" |
| #include "mojo/message_pump/message_pump_mojo.h" |
| #include "mojo/public/cpp/test_support/test_support.h" |
| #include "mojo/public/cpp/test_support/test_utils.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace mojo { |
| namespace common { |
| namespace test { |
| |
| enum MessageLoopConfig { |
| MESSAGE_LOOP_CONFIG_DEFAULT = 0, |
| MESSAGE_LOOP_CONFIG_MOJO = 1 |
| }; |
| |
| 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(); |
| } |
| |
| void OnWatcherSignaled(const base::Closure& callback, MojoResult /* result */) { |
| callback.Run(); |
| } |
| |
| class ScopedPerfTimer { |
| public: |
| ScopedPerfTimer(const std::string& test_name, |
| const std::string& sub_test_name, |
| uint64_t iterations) |
| : test_name_(test_name), |
| sub_test_name_(sub_test_name), |
| iterations_(iterations), |
| start_time_(base::TimeTicks::Now()) {} |
| ~ScopedPerfTimer() { |
| base::TimeTicks end_time = base::TimeTicks::Now(); |
| mojo::test::LogPerfResult( |
| test_name_.c_str(), sub_test_name_.c_str(), |
| iterations_ / (end_time - start_time_).InSecondsF(), |
| "iterations/second"); |
| } |
| |
| private: |
| const std::string test_name_; |
| const std::string sub_test_name_; |
| const uint64_t iterations_; |
| base::TimeTicks start_time_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ScopedPerfTimer); |
| }; |
| |
| class HandleWatcherPerftest : public testing::TestWithParam<MessageLoopConfig> { |
| public: |
| HandleWatcherPerftest() : message_loop_(CreateMessageLoop(GetParam())) {} |
| |
| protected: |
| std::string GetMessageLoopName() const { |
| return (GetParam() == MESSAGE_LOOP_CONFIG_DEFAULT) ? "DefaultMessageLoop" |
| : "MojoMessageLoop"; |
| } |
| |
| private: |
| scoped_ptr<base::MessageLoop> message_loop_; |
| |
| DISALLOW_COPY_AND_ASSIGN(HandleWatcherPerftest); |
| }; |
| |
| INSTANTIATE_TEST_CASE_P(MultipleMessageLoopConfigs, |
| HandleWatcherPerftest, |
| testing::Values(MESSAGE_LOOP_CONFIG_DEFAULT, |
| MESSAGE_LOOP_CONFIG_MOJO)); |
| |
| void NeverReached(MojoResult result) { |
| FAIL() << "Callback should never be invoked " << result; |
| } |
| |
| TEST_P(HandleWatcherPerftest, StartStop) { |
| const uint64_t kIterations = 100000; |
| MessagePipe pipe; |
| HandleWatcher watcher; |
| |
| ScopedPerfTimer timer("StartStop", GetMessageLoopName(), kIterations); |
| for (uint64_t i = 0; i < kIterations; i++) { |
| watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached)); |
| watcher.Stop(); |
| } |
| } |
| |
| TEST_P(HandleWatcherPerftest, StartAllThenStop_1000Handles) { |
| const uint64_t kIterations = 10; |
| const uint64_t kHandles = 1000; |
| |
| struct TestData { |
| MessagePipe pipe; |
| HandleWatcher watcher; |
| }; |
| ScopedVector<TestData> data_vector; |
| // Create separately from the start/stop loops to avoid affecting the |
| // benchmark. |
| for (uint64_t i = 0; i < kHandles; i++) { |
| scoped_ptr<TestData> test_data(new TestData); |
| ASSERT_TRUE(test_data->pipe.handle0.is_valid()); |
| data_vector.push_back(test_data.Pass()); |
| } |
| |
| ScopedPerfTimer timer("StartAllThenStop_1000Handles", GetMessageLoopName(), |
| kIterations * kHandles); |
| for (uint64_t iter = 0; iter < kIterations; iter++) { |
| for (uint64_t i = 0; i < kHandles; i++) { |
| TestData* test_data = data_vector[i]; |
| test_data->watcher.Start( |
| test_data->pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached)); |
| } |
| for (uint64_t i = 0; i < kHandles; i++) { |
| TestData* test_data = data_vector[i]; |
| test_data->watcher.Stop(); |
| } |
| } |
| } |
| |
| TEST_P(HandleWatcherPerftest, StartAndSignal) { |
| const uint64_t kIterations = 10000; |
| const std::string kMessage = "hello"; |
| MessagePipe pipe; |
| HandleWatcher watcher; |
| std::string received_message; |
| |
| ScopedPerfTimer timer("StartAndSignal", GetMessageLoopName(), kIterations); |
| for (uint64_t i = 0; i < kIterations; i++) { |
| base::RunLoop run_loop; |
| watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| MOJO_DEADLINE_INDEFINITE, |
| base::Bind(&OnWatcherSignaled, run_loop.QuitClosure())); |
| ASSERT_TRUE(mojo::test::WriteTextMessage(pipe.handle1.get(), kMessage)); |
| run_loop.Run(); |
| watcher.Stop(); |
| |
| ASSERT_TRUE( |
| mojo::test::ReadTextMessage(pipe.handle0.get(), &received_message)); |
| EXPECT_EQ(kMessage, received_message); |
| received_message.clear(); |
| } |
| } |
| |
| TEST_P(HandleWatcherPerftest, StartAndSignal_1000Waiting) { |
| const uint64_t kIterations = 1000; |
| const uint64_t kWaitingHandles = 1000; |
| const std::string kMessage = "hello"; |
| MessagePipe pipe; |
| HandleWatcher watcher; |
| std::string received_message; |
| |
| struct TestData { |
| MessagePipe pipe; |
| HandleWatcher watcher; |
| }; |
| ScopedVector<TestData> data_vector; |
| for (uint64_t i = 0; i < kWaitingHandles; i++) { |
| 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.Pass()); |
| } |
| |
| ScopedPerfTimer timer("StartAndSignal_1000Waiting", GetMessageLoopName(), |
| kIterations); |
| for (uint64_t i = 0; i < kIterations; i++) { |
| base::RunLoop run_loop; |
| watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, |
| MOJO_DEADLINE_INDEFINITE, |
| base::Bind(&OnWatcherSignaled, run_loop.QuitClosure())); |
| ASSERT_TRUE(mojo::test::WriteTextMessage(pipe.handle1.get(), kMessage)); |
| run_loop.Run(); |
| watcher.Stop(); |
| |
| ASSERT_TRUE( |
| mojo::test::ReadTextMessage(pipe.handle0.get(), &received_message)); |
| EXPECT_EQ(kMessage, received_message); |
| received_message.clear(); |
| } |
| } |
| |
| } // namespace test |
| } // namespace common |
| } // namespace mojo |