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
21namespace mojo {
22namespace edk {
23namespace test {
24
25
26#if defined(OS_MACOSX) && !defined(OS_IOS)
27namespace {
28base::MachPortBroker* g_mach_broker = nullptr;
29}
30#endif
31
32MojoTestBase::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
42MojoTestBase::~MojoTestBase() {}
43
44MojoTestBase::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
51MojoTestBase::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
74MojoTestBase::ClientController::~ClientController() {
75  CHECK(was_shutdown_)
76      << "Test clients should be waited on explicitly with WaitForShutdown().";
77}
78
79void MojoTestBase::ClientController::ClosePeerConnection() {
80#if !defined(OS_IOS)
81  helper_.ClosePeerConnection();
82#endif
83}
84
85int 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
101void MojoTestBase::CloseHandle(MojoHandle h) {
102  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h));
103}
104
105// static
106void 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
113void 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
124void MojoTestBase::WriteMessage(MojoHandle mp, const std::string& message) {
125  WriteMessageWithHandles(mp, message, nullptr, 0);
126}
127
128// static
129std::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
155std::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
186std::string MojoTestBase::ReadMessage(MojoHandle mp) {
187  return ReadMessageWithHandles(mp, nullptr, 0);
188}
189
190// static
191void 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
214void 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
224void MojoTestBase::VerifyEcho(MojoHandle mp,
225                              const std::string& message) {
226  VerifyTransmission(mp, mp, message);
227}
228
229// static
230MojoHandle 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
237MojoHandle 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
251void 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
263void 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
275void 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
290void 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
302std::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