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