Home | History | Annotate | Download | only in system
      1 // Copyright 2014 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 #include <stdio.h>
      7 #include <string.h>
      8 
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/bind.h"
     13 #include "base/location.h"
     14 #include "base/logging.h"
     15 #include "base/macros.h"
     16 #include "base/pickle.h"
     17 #include "base/strings/stringprintf.h"
     18 #include "base/test/perf_time_logger.h"
     19 #include "base/time/time.h"
     20 #include "mojo/common/test/test_utils.h"
     21 #include "mojo/embedder/scoped_platform_handle.h"
     22 #include "mojo/system/channel.h"
     23 #include "mojo/system/local_message_pipe_endpoint.h"
     24 #include "mojo/system/message_pipe.h"
     25 #include "mojo/system/message_pipe_test_utils.h"
     26 #include "mojo/system/proxy_message_pipe_endpoint.h"
     27 #include "mojo/system/raw_channel.h"
     28 #include "mojo/system/test_utils.h"
     29 #include "testing/gtest/include/gtest/gtest.h"
     30 
     31 namespace mojo {
     32 namespace system {
     33 namespace {
     34 
     35 class MultiprocessMessagePipePerfTest
     36     : public test::MultiprocessMessagePipeTestBase {
     37  public:
     38   MultiprocessMessagePipePerfTest() : message_count_(0), message_size_(0) {}
     39 
     40   void SetUpMeasurement(int message_count, size_t message_size) {
     41     message_count_ = message_count;
     42     message_size_ = message_size;
     43     payload_ = Pickle();
     44     payload_.WriteString(std::string(message_size, '*'));
     45     read_buffer_.resize(message_size * 2);
     46   }
     47 
     48  protected:
     49   void WriteWaitThenRead(scoped_refptr<MessagePipe> mp) {
     50     CHECK_EQ(mp->WriteMessage(0,
     51                               UserPointer<const void>(payload_.data()),
     52                               static_cast<uint32_t>(payload_.size()),
     53                               nullptr,
     54                               MOJO_WRITE_MESSAGE_FLAG_NONE),
     55              MOJO_RESULT_OK);
     56     HandleSignalsState hss;
     57     CHECK_EQ(test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss),
     58              MOJO_RESULT_OK);
     59     uint32_t read_buffer_size = static_cast<uint32_t>(read_buffer_.size());
     60     CHECK_EQ(mp->ReadMessage(0,
     61                              UserPointer<void>(&read_buffer_[0]),
     62                              MakeUserPointer(&read_buffer_size),
     63                              nullptr,
     64                              nullptr,
     65                              MOJO_READ_MESSAGE_FLAG_NONE),
     66              MOJO_RESULT_OK);
     67     CHECK_EQ(read_buffer_size, static_cast<uint32_t>(payload_.size()));
     68   }
     69 
     70   void SendQuitMessage(scoped_refptr<MessagePipe> mp) {
     71     CHECK_EQ(mp->WriteMessage(0,
     72                               UserPointer<const void>(""),
     73                               0,
     74                               nullptr,
     75                               MOJO_WRITE_MESSAGE_FLAG_NONE),
     76              MOJO_RESULT_OK);
     77   }
     78 
     79   void Measure(scoped_refptr<MessagePipe> mp) {
     80     // Have one ping-pong to ensure channel being established.
     81     WriteWaitThenRead(mp);
     82 
     83     std::string test_name =
     84         base::StringPrintf("IPC_Perf_%dx_%u",
     85                            message_count_,
     86                            static_cast<unsigned>(message_size_));
     87     base::PerfTimeLogger logger(test_name.c_str());
     88 
     89     for (int i = 0; i < message_count_; ++i)
     90       WriteWaitThenRead(mp);
     91 
     92     logger.Done();
     93   }
     94 
     95  private:
     96   int message_count_;
     97   size_t message_size_;
     98   Pickle payload_;
     99   std::string read_buffer_;
    100   scoped_ptr<base::PerfTimeLogger> perf_logger_;
    101 };
    102 
    103 // For each message received, sends a reply message with the same contents
    104 // repeated twice, until the other end is closed or it receives "quitquitquit"
    105 // (which it doesn't reply to). It'll return the number of messages received,
    106 // not including any "quitquitquit" message, modulo 100.
    107 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(PingPongClient) {
    108   embedder::SimplePlatformSupport platform_support;
    109   test::ChannelThread channel_thread(&platform_support);
    110   embedder::ScopedPlatformHandle client_platform_handle =
    111       mojo::test::MultiprocessTestHelper::client_platform_handle.Pass();
    112   CHECK(client_platform_handle.is_valid());
    113   scoped_refptr<ChannelEndpoint> ep;
    114   scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
    115   channel_thread.Start(client_platform_handle.Pass(), ep);
    116 
    117   std::string buffer(1000000, '\0');
    118   int rv = 0;
    119   while (true) {
    120     // Wait for our end of the message pipe to be readable.
    121     HandleSignalsState hss;
    122     MojoResult result =
    123         test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss);
    124     if (result != MOJO_RESULT_OK) {
    125       rv = result;
    126       break;
    127     }
    128 
    129     uint32_t read_size = static_cast<uint32_t>(buffer.size());
    130     CHECK_EQ(mp->ReadMessage(0,
    131                              UserPointer<void>(&buffer[0]),
    132                              MakeUserPointer(&read_size),
    133                              nullptr,
    134                              nullptr,
    135                              MOJO_READ_MESSAGE_FLAG_NONE),
    136              MOJO_RESULT_OK);
    137 
    138     // Empty message indicates quitting
    139     if (0 == read_size)
    140       break;
    141 
    142     CHECK_EQ(mp->WriteMessage(0,
    143                               UserPointer<const void>(&buffer[0]),
    144                               static_cast<uint32_t>(read_size),
    145                               nullptr,
    146                               MOJO_WRITE_MESSAGE_FLAG_NONE),
    147              MOJO_RESULT_OK);
    148   }
    149 
    150   mp->Close(0);
    151   return rv;
    152 }
    153 
    154 // Repeatedly sends messages as previous one got replied by the child.
    155 // Waits for the child to close its end before quitting once specified
    156 // number of messages has been sent.
    157 TEST_F(MultiprocessMessagePipePerfTest, PingPong) {
    158   helper()->StartChild("PingPongClient");
    159 
    160   scoped_refptr<ChannelEndpoint> ep;
    161   scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalProxy(&ep));
    162   Init(ep);
    163 
    164   // This values are set to align with one at ipc_pertests.cc for comparison.
    165   const size_t kMsgSize[5] = {12, 144, 1728, 20736, 248832};
    166   const int kMessageCount[5] = {50000, 50000, 50000, 12000, 1000};
    167 
    168   for (size_t i = 0; i < 5; i++) {
    169     SetUpMeasurement(kMessageCount[i], kMsgSize[i]);
    170     Measure(mp);
    171   }
    172 
    173   SendQuitMessage(mp);
    174   mp->Close(0);
    175   EXPECT_EQ(0, helper()->WaitForChildShutdown());
    176 }
    177 
    178 }  // namespace
    179 }  // namespace system
    180 }  // namespace mojo
    181