• 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_));
48   return *clients_.back();
49 }
50 
ClientController(const std::string & client_name,MojoTestBase * test,const ProcessErrorCallback & process_error_callback)51 MojoTestBase::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 
~ClientController()73 MojoTestBase::ClientController::~ClientController() {
74   CHECK(was_shutdown_)
75       << "Test clients should be waited on explicitly with WaitForShutdown().";
76 }
77 
WaitForShutdown()78 int 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
CloseHandle(MojoHandle h)94 void MojoTestBase::CloseHandle(MojoHandle h) {
95   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h));
96 }
97 
98 // static
CreateMessagePipe(MojoHandle * p0,MojoHandle * p1)99 void 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
WriteMessageWithHandles(MojoHandle mp,const std::string & message,const MojoHandle * handles,uint32_t num_handles)106 void 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
WriteMessage(MojoHandle mp,const std::string & message)117 void MojoTestBase::WriteMessage(MojoHandle mp, const std::string& message) {
118   WriteMessageWithHandles(mp, message, nullptr, 0);
119 }
120 
121 // static
ReadMessageWithHandles(MojoHandle mp,MojoHandle * handles,uint32_t expected_num_handles)122 std::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
ReadMessageWithOptionalHandle(MojoHandle mp,MojoHandle * handle)148 std::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
ReadMessage(MojoHandle mp)179 std::string MojoTestBase::ReadMessage(MojoHandle mp) {
180   return ReadMessageWithHandles(mp, nullptr, 0);
181 }
182 
183 // static
ReadMessage(MojoHandle mp,char * data,size_t num_bytes)184 void 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
VerifyTransmission(MojoHandle source,MojoHandle dest,const std::string & message)207 void 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
VerifyEcho(MojoHandle mp,const std::string & message)217 void MojoTestBase::VerifyEcho(MojoHandle mp,
218                               const std::string& message) {
219   VerifyTransmission(mp, mp, message);
220 }
221 
222 // static
CreateBuffer(uint64_t size)223 MojoHandle 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
DuplicateBuffer(MojoHandle h,bool read_only)230 MojoHandle 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
WriteToBuffer(MojoHandle h,size_t offset,const base::StringPiece & s)244 void 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
ExpectBufferContents(MojoHandle h,size_t offset,const base::StringPiece & s)256 void 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
CreateDataPipe(MojoHandle * p0,MojoHandle * p1,size_t capacity)268 void 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
WriteData(MojoHandle producer,const std::string & data)283 void 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
ReadData(MojoHandle consumer,size_t size)295 std::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