1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <stdint.h> 6 7 #include <string> 8 #include <utility> 9 10 #include "base/auto_reset.h" 11 #include "base/bind.h" 12 #include "base/macros.h" 13 #include "base/memory/scoped_vector.h" 14 #include "base/run_loop.h" 15 #include "base/time/time.h" 16 #include "mojo/message_pump/handle_watcher.h" 17 #include "mojo/message_pump/message_pump_mojo.h" 18 #include "mojo/public/cpp/test_support/test_support.h" 19 #include "mojo/public/cpp/test_support/test_utils.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 namespace mojo { 23 namespace common { 24 namespace test { 25 26 enum MessageLoopConfig { 27 MESSAGE_LOOP_CONFIG_DEFAULT = 0, 28 MESSAGE_LOOP_CONFIG_MOJO = 1 29 }; 30 31 std::unique_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) { 32 std::unique_ptr<base::MessageLoop> loop; 33 if (config == MESSAGE_LOOP_CONFIG_DEFAULT) 34 loop.reset(new base::MessageLoop()); 35 else 36 loop.reset(new base::MessageLoop(MessagePumpMojo::Create())); 37 return loop; 38 } 39 40 void OnWatcherSignaled(const base::Closure& callback, MojoResult /* result */) { 41 callback.Run(); 42 } 43 44 class ScopedPerfTimer { 45 public: 46 ScopedPerfTimer(const std::string& test_name, 47 const std::string& sub_test_name, 48 uint64_t iterations) 49 : test_name_(test_name), 50 sub_test_name_(sub_test_name), 51 iterations_(iterations), 52 start_time_(base::TimeTicks::Now()) {} 53 ~ScopedPerfTimer() { 54 base::TimeTicks end_time = base::TimeTicks::Now(); 55 mojo::test::LogPerfResult( 56 test_name_.c_str(), sub_test_name_.c_str(), 57 iterations_ / (end_time - start_time_).InSecondsF(), 58 "iterations/second"); 59 } 60 61 private: 62 const std::string test_name_; 63 const std::string sub_test_name_; 64 const uint64_t iterations_; 65 base::TimeTicks start_time_; 66 67 DISALLOW_COPY_AND_ASSIGN(ScopedPerfTimer); 68 }; 69 70 class HandleWatcherPerftest : public testing::TestWithParam<MessageLoopConfig> { 71 public: 72 HandleWatcherPerftest() : message_loop_(CreateMessageLoop(GetParam())) {} 73 74 protected: 75 std::string GetMessageLoopName() const { 76 return (GetParam() == MESSAGE_LOOP_CONFIG_DEFAULT) ? "DefaultMessageLoop" 77 : "MojoMessageLoop"; 78 } 79 80 private: 81 std::unique_ptr<base::MessageLoop> message_loop_; 82 83 DISALLOW_COPY_AND_ASSIGN(HandleWatcherPerftest); 84 }; 85 86 INSTANTIATE_TEST_CASE_P(MultipleMessageLoopConfigs, 87 HandleWatcherPerftest, 88 testing::Values(MESSAGE_LOOP_CONFIG_DEFAULT, 89 MESSAGE_LOOP_CONFIG_MOJO)); 90 91 void NeverReached(MojoResult result) { 92 FAIL() << "Callback should never be invoked " << result; 93 } 94 95 TEST_P(HandleWatcherPerftest, StartStop) { 96 const uint64_t kIterations = 100000; 97 MessagePipe pipe; 98 HandleWatcher watcher; 99 100 ScopedPerfTimer timer("StartStop", GetMessageLoopName(), kIterations); 101 for (uint64_t i = 0; i < kIterations; i++) { 102 watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 103 MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached)); 104 watcher.Stop(); 105 } 106 } 107 108 TEST_P(HandleWatcherPerftest, StartAllThenStop_1000Handles) { 109 const uint64_t kIterations = 100; 110 const uint64_t kHandles = 1000; 111 112 struct TestData { 113 MessagePipe pipe; 114 HandleWatcher watcher; 115 }; 116 ScopedVector<TestData> data_vector; 117 // Create separately from the start/stop loops to avoid affecting the 118 // benchmark. 119 for (uint64_t i = 0; i < kHandles; i++) { 120 std::unique_ptr<TestData> test_data(new TestData); 121 ASSERT_TRUE(test_data->pipe.handle0.is_valid()); 122 data_vector.push_back(std::move(test_data)); 123 } 124 125 ScopedPerfTimer timer("StartAllThenStop_1000Handles", GetMessageLoopName(), 126 kIterations * kHandles); 127 for (uint64_t iter = 0; iter < kIterations; iter++) { 128 for (uint64_t i = 0; i < kHandles; i++) { 129 TestData* test_data = data_vector[i]; 130 test_data->watcher.Start( 131 test_data->pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 132 MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached)); 133 } 134 for (uint64_t i = 0; i < kHandles; i++) { 135 TestData* test_data = data_vector[i]; 136 test_data->watcher.Stop(); 137 } 138 } 139 } 140 141 TEST_P(HandleWatcherPerftest, StartAndSignal) { 142 const uint64_t kIterations = 10000; 143 const std::string kMessage = "hello"; 144 MessagePipe pipe; 145 HandleWatcher watcher; 146 std::string received_message; 147 148 ScopedPerfTimer timer("StartAndSignal", GetMessageLoopName(), kIterations); 149 for (uint64_t i = 0; i < kIterations; i++) { 150 base::RunLoop run_loop; 151 watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 152 MOJO_DEADLINE_INDEFINITE, 153 base::Bind(&OnWatcherSignaled, run_loop.QuitClosure())); 154 ASSERT_TRUE(mojo::test::WriteTextMessage(pipe.handle1.get(), kMessage)); 155 run_loop.Run(); 156 watcher.Stop(); 157 158 ASSERT_TRUE( 159 mojo::test::ReadTextMessage(pipe.handle0.get(), &received_message)); 160 EXPECT_EQ(kMessage, received_message); 161 received_message.clear(); 162 } 163 } 164 165 TEST_P(HandleWatcherPerftest, StartAndSignal_1000Waiting) { 166 const uint64_t kIterations = 10000; 167 const uint64_t kWaitingHandles = 1000; 168 const std::string kMessage = "hello"; 169 MessagePipe pipe; 170 HandleWatcher watcher; 171 std::string received_message; 172 173 struct TestData { 174 MessagePipe pipe; 175 HandleWatcher watcher; 176 }; 177 ScopedVector<TestData> data_vector; 178 for (uint64_t i = 0; i < kWaitingHandles; i++) { 179 std::unique_ptr<TestData> test_data(new TestData); 180 ASSERT_TRUE(test_data->pipe.handle0.is_valid()); 181 test_data->watcher.Start( 182 test_data->pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 183 MOJO_DEADLINE_INDEFINITE, base::Bind(&NeverReached)); 184 data_vector.push_back(std::move(test_data)); 185 } 186 187 ScopedPerfTimer timer("StartAndSignal_1000Waiting", GetMessageLoopName(), 188 kIterations); 189 for (uint64_t i = 0; i < kIterations; i++) { 190 base::RunLoop run_loop; 191 watcher.Start(pipe.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 192 MOJO_DEADLINE_INDEFINITE, 193 base::Bind(&OnWatcherSignaled, run_loop.QuitClosure())); 194 ASSERT_TRUE(mojo::test::WriteTextMessage(pipe.handle1.get(), kMessage)); 195 run_loop.Run(); 196 watcher.Stop(); 197 198 ASSERT_TRUE( 199 mojo::test::ReadTextMessage(pipe.handle0.get(), &received_message)); 200 EXPECT_EQ(kMessage, received_message); 201 received_message.clear(); 202 } 203 } 204 205 } // namespace test 206 } // namespace common 207 } // namespace mojo 208