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
MojoTestBase()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
~MojoTestBase()42 MojoTestBase::~MojoTestBase() {}
43
StartClient(const std::string & client_name)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
ClientController(const std::string & client_name,MojoTestBase * test,const ProcessErrorCallback & process_error_callback,LaunchType launch_type)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
~ClientController()74 MojoTestBase::ClientController::~ClientController() {
75 CHECK(was_shutdown_)
76 << "Test clients should be waited on explicitly with WaitForShutdown().";
77 }
78
ClosePeerConnection()79 void MojoTestBase::ClientController::ClosePeerConnection() {
80 #if !defined(OS_IOS)
81 helper_.ClosePeerConnection();
82 #endif
83 }
84
WaitForShutdown()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
CloseHandle(MojoHandle h)101 void MojoTestBase::CloseHandle(MojoHandle h) {
102 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h));
103 }
104
105 // static
CreateMessagePipe(MojoHandle * p0,MojoHandle * p1)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
WriteMessageWithHandles(MojoHandle mp,const std::string & message,const MojoHandle * handles,uint32_t num_handles)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
WriteMessage(MojoHandle mp,const std::string & message)124 void MojoTestBase::WriteMessage(MojoHandle mp, const std::string& message) {
125 WriteMessageWithHandles(mp, message, nullptr, 0);
126 }
127
128 // static
ReadMessageWithHandles(MojoHandle mp,MojoHandle * handles,uint32_t expected_num_handles)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
ReadMessageWithOptionalHandle(MojoHandle mp,MojoHandle * handle)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
ReadMessage(MojoHandle mp)186 std::string MojoTestBase::ReadMessage(MojoHandle mp) {
187 return ReadMessageWithHandles(mp, nullptr, 0);
188 }
189
190 // static
ReadMessage(MojoHandle mp,char * data,size_t num_bytes)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
VerifyTransmission(MojoHandle source,MojoHandle dest,const std::string & message)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
VerifyEcho(MojoHandle mp,const std::string & message)224 void MojoTestBase::VerifyEcho(MojoHandle mp,
225 const std::string& message) {
226 VerifyTransmission(mp, mp, message);
227 }
228
229 // static
CreateBuffer(uint64_t size)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
DuplicateBuffer(MojoHandle h,bool read_only)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
WriteToBuffer(MojoHandle h,size_t offset,const base::StringPiece & s)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
ExpectBufferContents(MojoHandle h,size_t offset,const base::StringPiece & s)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
CreateDataPipe(MojoHandle * p0,MojoHandle * p1,size_t capacity)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
WriteData(MojoHandle producer,const std::string & data)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
ReadData(MojoHandle consumer,size_t size)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