Home | History | Annotate | Download | only in message_pump
      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