Home | History | Annotate | Download | only in test
      1 // Copyright 2016 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 "mojo/edk/test/mojo_test_base.h"
      6 
      7 #include "base/memory/ptr_util.h"
      8 #include "base/message_loop/message_loop.h"
      9 #include "base/run_loop.h"
     10 #include "mojo/edk/embedder/embedder.h"
     11 #include "mojo/edk/system/handle_signals_state.h"
     12 #include "mojo/public/c/system/buffer.h"
     13 #include "mojo/public/c/system/data_pipe.h"
     14 #include "mojo/public/c/system/functions.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 
     17 #if defined(OS_MACOSX) && !defined(OS_IOS)
     18 #include "base/mac/mach_port_broker.h"
     19 #endif
     20 
     21 namespace mojo {
     22 namespace edk {
     23 namespace test {
     24 
     25 
     26 #if defined(OS_MACOSX) && !defined(OS_IOS)
     27 namespace {
     28 base::MachPortBroker* g_mach_broker = nullptr;
     29 }
     30 #endif
     31 
     32 MojoTestBase::MojoTestBase() {
     33 #if defined(OS_MACOSX) && !defined(OS_IOS)
     34   if (!g_mach_broker) {
     35     g_mach_broker = new base::MachPortBroker("mojo_test");
     36     CHECK(g_mach_broker->Init());
     37     SetMachPortProvider(g_mach_broker);
     38   }
     39 #endif
     40 }
     41 
     42 MojoTestBase::~MojoTestBase() {}
     43 
     44 MojoTestBase::ClientController& MojoTestBase::StartClient(
     45     const std::string& client_name) {
     46   clients_.push_back(base::MakeUnique<ClientController>(
     47       client_name, this, process_error_callback_, launch_type_));
     48   return *clients_.back();
     49 }
     50 
     51 MojoTestBase::ClientController::ClientController(
     52     const std::string& client_name,
     53     MojoTestBase* test,
     54     const ProcessErrorCallback& process_error_callback,
     55     LaunchType launch_type) {
     56 #if !defined(OS_IOS)
     57 #if defined(OS_MACOSX)
     58   // This lock needs to be held while launching the child because the Mach port
     59   // broker only allows task ports to be received from known child processes.
     60   // However, it can only know the child process's pid after the child has
     61   // launched. To prevent a race where the child process sends its task port
     62   // before the pid has been registered, the lock needs to be held over both
     63   // launch and child pid registration.
     64   base::AutoLock lock(g_mach_broker->GetLock());
     65 #endif
     66   helper_.set_process_error_callback(process_error_callback);
     67   pipe_ = helper_.StartChild(client_name, launch_type);
     68 #if defined(OS_MACOSX)
     69   g_mach_broker->AddPlaceholderForPid(helper_.test_child().Handle());
     70 #endif
     71 #endif
     72 }
     73 
     74 MojoTestBase::ClientController::~ClientController() {
     75   CHECK(was_shutdown_)
     76       << "Test clients should be waited on explicitly with WaitForShutdown().";
     77 }
     78 
     79 void MojoTestBase::ClientController::ClosePeerConnection() {
     80 #if !defined(OS_IOS)
     81   helper_.ClosePeerConnection();
     82 #endif
     83 }
     84 
     85 int MojoTestBase::ClientController::WaitForShutdown() {
     86   was_shutdown_ = true;
     87 #if !defined(OS_IOS)
     88   int retval = helper_.WaitForChildShutdown();
     89 #if defined(OS_MACOSX)
     90   base::AutoLock lock(g_mach_broker->GetLock());
     91   g_mach_broker->InvalidatePid(helper_.test_child().Handle());
     92 #endif
     93   return retval;
     94 #else
     95   NOTREACHED();
     96   return 1;
     97 #endif
     98 }
     99 
    100 // static
    101 void MojoTestBase::CloseHandle(MojoHandle h) {
    102   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h));
    103 }
    104 
    105 // static
    106 void MojoTestBase::CreateMessagePipe(MojoHandle *p0, MojoHandle* p1) {
    107   MojoCreateMessagePipe(nullptr, p0, p1);
    108   CHECK_NE(*p0, MOJO_HANDLE_INVALID);
    109   CHECK_NE(*p1, MOJO_HANDLE_INVALID);
    110 }
    111 
    112 // static
    113 void MojoTestBase::WriteMessageWithHandles(MojoHandle mp,
    114                                            const std::string& message,
    115                                            const MojoHandle *handles,
    116                                            uint32_t num_handles) {
    117   CHECK_EQ(MojoWriteMessage(mp, message.data(),
    118                             static_cast<uint32_t>(message.size()),
    119                             handles, num_handles, MOJO_WRITE_MESSAGE_FLAG_NONE),
    120            MOJO_RESULT_OK);
    121 }
    122 
    123 // static
    124 void MojoTestBase::WriteMessage(MojoHandle mp, const std::string& message) {
    125   WriteMessageWithHandles(mp, message, nullptr, 0);
    126 }
    127 
    128 // static
    129 std::string MojoTestBase::ReadMessageWithHandles(
    130     MojoHandle mp,
    131     MojoHandle* handles,
    132     uint32_t expected_num_handles) {
    133   CHECK_EQ(MojoWait(mp, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE,
    134                     nullptr),
    135            MOJO_RESULT_OK);
    136 
    137   uint32_t message_size = 0;
    138   uint32_t num_handles = 0;
    139   CHECK_EQ(MojoReadMessage(mp, nullptr, &message_size, nullptr, &num_handles,
    140                            MOJO_READ_MESSAGE_FLAG_NONE),
    141            MOJO_RESULT_RESOURCE_EXHAUSTED);
    142   CHECK_EQ(expected_num_handles, num_handles);
    143 
    144   std::string message(message_size, 'x');
    145   CHECK_EQ(MojoReadMessage(mp, &message[0], &message_size, handles,
    146                            &num_handles, MOJO_READ_MESSAGE_FLAG_NONE),
    147            MOJO_RESULT_OK);
    148   CHECK_EQ(message_size, message.size());
    149   CHECK_EQ(num_handles, expected_num_handles);
    150 
    151   return message;
    152 }
    153 
    154 // static
    155 std::string MojoTestBase::ReadMessageWithOptionalHandle(MojoHandle mp,
    156                                                         MojoHandle* handle) {
    157   CHECK_EQ(MojoWait(mp, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE,
    158                     nullptr),
    159            MOJO_RESULT_OK);
    160 
    161   uint32_t message_size = 0;
    162   uint32_t num_handles = 0;
    163   CHECK_EQ(MojoReadMessage(mp, nullptr, &message_size, nullptr, &num_handles,
    164                            MOJO_READ_MESSAGE_FLAG_NONE),
    165            MOJO_RESULT_RESOURCE_EXHAUSTED);
    166   CHECK(num_handles == 0 || num_handles == 1);
    167 
    168   CHECK(handle);
    169 
    170   std::string message(message_size, 'x');
    171   CHECK_EQ(MojoReadMessage(mp, &message[0], &message_size, handle,
    172                            &num_handles, MOJO_READ_MESSAGE_FLAG_NONE),
    173            MOJO_RESULT_OK);
    174   CHECK_EQ(message_size, message.size());
    175   CHECK(num_handles == 0 || num_handles == 1);
    176 
    177   if (num_handles)
    178     CHECK_NE(*handle, MOJO_HANDLE_INVALID);
    179   else
    180     *handle = MOJO_HANDLE_INVALID;
    181 
    182   return message;
    183 }
    184 
    185 // static
    186 std::string MojoTestBase::ReadMessage(MojoHandle mp) {
    187   return ReadMessageWithHandles(mp, nullptr, 0);
    188 }
    189 
    190 // static
    191 void MojoTestBase::ReadMessage(MojoHandle mp,
    192                                char* data,
    193                                size_t num_bytes) {
    194   CHECK_EQ(MojoWait(mp, MOJO_HANDLE_SIGNAL_READABLE, MOJO_DEADLINE_INDEFINITE,
    195                     nullptr),
    196            MOJO_RESULT_OK);
    197 
    198   uint32_t message_size = 0;
    199   uint32_t num_handles = 0;
    200   CHECK_EQ(MojoReadMessage(mp, nullptr, &message_size, nullptr, &num_handles,
    201                            MOJO_READ_MESSAGE_FLAG_NONE),
    202            MOJO_RESULT_RESOURCE_EXHAUSTED);
    203   CHECK_EQ(num_handles, 0u);
    204   CHECK_EQ(message_size, num_bytes);
    205 
    206   CHECK_EQ(MojoReadMessage(mp, data, &message_size, nullptr, &num_handles,
    207                            MOJO_READ_MESSAGE_FLAG_NONE),
    208            MOJO_RESULT_OK);
    209   CHECK_EQ(num_handles, 0u);
    210   CHECK_EQ(message_size, num_bytes);
    211 }
    212 
    213 // static
    214 void MojoTestBase::VerifyTransmission(MojoHandle source,
    215                                       MojoHandle dest,
    216                                       const std::string& message) {
    217   WriteMessage(source, message);
    218 
    219   // We don't use EXPECT_EQ; failures on really long messages make life hard.
    220   EXPECT_TRUE(message == ReadMessage(dest));
    221 }
    222 
    223 // static
    224 void MojoTestBase::VerifyEcho(MojoHandle mp,
    225                               const std::string& message) {
    226   VerifyTransmission(mp, mp, message);
    227 }
    228 
    229 // static
    230 MojoHandle MojoTestBase::CreateBuffer(uint64_t size) {
    231   MojoHandle h;
    232   EXPECT_EQ(MojoCreateSharedBuffer(nullptr, size, &h), MOJO_RESULT_OK);
    233   return h;
    234 }
    235 
    236 // static
    237 MojoHandle MojoTestBase::DuplicateBuffer(MojoHandle h, bool read_only) {
    238   MojoHandle new_handle;
    239   MojoDuplicateBufferHandleOptions options = {
    240     sizeof(MojoDuplicateBufferHandleOptions),
    241     MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE
    242   };
    243   if (read_only)
    244     options.flags |= MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_READ_ONLY;
    245   EXPECT_EQ(MOJO_RESULT_OK,
    246             MojoDuplicateBufferHandle(h, &options, &new_handle));
    247   return new_handle;
    248 }
    249 
    250 // static
    251 void MojoTestBase::WriteToBuffer(MojoHandle h,
    252                                  size_t offset,
    253                                  const base::StringPiece& s) {
    254   char* data;
    255   EXPECT_EQ(MOJO_RESULT_OK,
    256             MojoMapBuffer(h, offset, s.size(), reinterpret_cast<void**>(&data),
    257                           MOJO_MAP_BUFFER_FLAG_NONE));
    258   memcpy(data, s.data(), s.size());
    259   EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(static_cast<void*>(data)));
    260 }
    261 
    262 // static
    263 void MojoTestBase::ExpectBufferContents(MojoHandle h,
    264                                         size_t offset,
    265                                         const base::StringPiece& s) {
    266   char* data;
    267   EXPECT_EQ(MOJO_RESULT_OK,
    268             MojoMapBuffer(h, offset, s.size(), reinterpret_cast<void**>(&data),
    269                           MOJO_MAP_BUFFER_FLAG_NONE));
    270   EXPECT_EQ(s, base::StringPiece(data, s.size()));
    271   EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(static_cast<void*>(data)));
    272 }
    273 
    274 // static
    275 void MojoTestBase::CreateDataPipe(MojoHandle *p0,
    276                                   MojoHandle* p1,
    277                                   size_t capacity) {
    278   MojoCreateDataPipeOptions options;
    279   options.struct_size = static_cast<uint32_t>(sizeof(options));
    280   options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
    281   options.element_num_bytes = 1;
    282   options.capacity_num_bytes = static_cast<uint32_t>(capacity);
    283 
    284   MojoCreateDataPipe(&options, p0, p1);
    285   CHECK_NE(*p0, MOJO_HANDLE_INVALID);
    286   CHECK_NE(*p1, MOJO_HANDLE_INVALID);
    287 }
    288 
    289 // static
    290 void MojoTestBase::WriteData(MojoHandle producer, const std::string& data) {
    291   CHECK_EQ(MojoWait(producer, MOJO_HANDLE_SIGNAL_WRITABLE,
    292                     MOJO_DEADLINE_INDEFINITE, nullptr),
    293            MOJO_RESULT_OK);
    294   uint32_t num_bytes = static_cast<uint32_t>(data.size());
    295   CHECK_EQ(MojoWriteData(producer, data.data(), &num_bytes,
    296                          MOJO_WRITE_DATA_FLAG_ALL_OR_NONE),
    297            MOJO_RESULT_OK);
    298   CHECK_EQ(num_bytes, static_cast<uint32_t>(data.size()));
    299 }
    300 
    301 // static
    302 std::string MojoTestBase::ReadData(MojoHandle consumer, size_t size) {
    303   CHECK_EQ(MojoWait(consumer, MOJO_HANDLE_SIGNAL_READABLE,
    304                     MOJO_DEADLINE_INDEFINITE, nullptr),
    305            MOJO_RESULT_OK);
    306   std::vector<char> buffer(size);
    307   uint32_t num_bytes = static_cast<uint32_t>(size);
    308   CHECK_EQ(MojoReadData(consumer, buffer.data(), &num_bytes,
    309                          MOJO_WRITE_DATA_FLAG_ALL_OR_NONE),
    310            MOJO_RESULT_OK);
    311   CHECK_EQ(num_bytes, static_cast<uint32_t>(size));
    312 
    313   return std::string(buffer.data(), buffer.size());
    314 }
    315 
    316 }  // namespace test
    317 }  // namespace edk
    318 }  // namespace mojo
    319