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