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_));
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#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
73MojoTestBase::ClientController::~ClientController() {
74  CHECK(was_shutdown_)
75      << "Test clients should be waited on explicitly with WaitForShutdown().";
76}
77
78int 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
94void MojoTestBase::CloseHandle(MojoHandle h) {
95  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h));
96}
97
98// static
99void 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
106void 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
117void MojoTestBase::WriteMessage(MojoHandle mp, const std::string& message) {
118  WriteMessageWithHandles(mp, message, nullptr, 0);
119}
120
121// static
122std::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
148std::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
179std::string MojoTestBase::ReadMessage(MojoHandle mp) {
180  return ReadMessageWithHandles(mp, nullptr, 0);
181}
182
183// static
184void 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
207void 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
217void MojoTestBase::VerifyEcho(MojoHandle mp,
218                              const std::string& message) {
219  VerifyTransmission(mp, mp, message);
220}
221
222// static
223MojoHandle 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
230MojoHandle 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
244void 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
256void 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
268void 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
283void 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
295std::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