• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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