• 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/core/test/mojo_test_base.h"
6 
7 #include "base/memory/ptr_util.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/run_loop.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "build/build_config.h"
12 #include "mojo/core/embedder/embedder.h"
13 #include "mojo/public/c/system/buffer.h"
14 #include "mojo/public/c/system/data_pipe.h"
15 #include "mojo/public/c/system/functions.h"
16 #include "mojo/public/c/system/trap.h"
17 #include "mojo/public/cpp/system/handle.h"
18 #include "mojo/public/cpp/system/message_pipe.h"
19 #include "mojo/public/cpp/system/wait.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 
22 #if defined(OS_MACOSX) && !defined(OS_IOS)
23 #include "base/mac/mach_port_broker.h"
24 #endif
25 
26 namespace mojo {
27 namespace core {
28 namespace test {
29 
30 #if defined(OS_MACOSX) && !defined(OS_IOS)
31 namespace {
32 base::MachPortBroker* g_mach_broker = nullptr;
33 }
34 #endif
35 
MojoTestBase()36 MojoTestBase::MojoTestBase() {
37 #if defined(OS_MACOSX) && !defined(OS_IOS)
38   if (!g_mach_broker) {
39     g_mach_broker = new base::MachPortBroker("mojo_test");
40     CHECK(g_mach_broker->Init());
41     SetMachPortProvider(g_mach_broker);
42   }
43 #endif
44 }
45 
~MojoTestBase()46 MojoTestBase::~MojoTestBase() {}
47 
StartClient(const std::string & client_name)48 MojoTestBase::ClientController& MojoTestBase::StartClient(
49     const std::string& client_name) {
50   clients_.push_back(
51       std::make_unique<ClientController>(client_name, this, launch_type_));
52   return *clients_.back();
53 }
54 
ClientController(const std::string & client_name,MojoTestBase * test,LaunchType launch_type)55 MojoTestBase::ClientController::ClientController(const std::string& client_name,
56                                                  MojoTestBase* test,
57                                                  LaunchType launch_type) {
58 #if !defined(OS_IOS)
59 #if defined(OS_MACOSX)
60   // This lock needs to be held while launching the child because the Mach port
61   // broker only allows task ports to be received from known child processes.
62   // However, it can only know the child process's pid after the child has
63   // launched. To prevent a race where the child process sends its task port
64   // before the pid has been registered, the lock needs to be held over both
65   // launch and child pid registration.
66   base::AutoLock lock(g_mach_broker->GetLock());
67 #endif
68   pipe_ = helper_.StartChild(client_name, launch_type);
69 #if defined(OS_MACOSX)
70   g_mach_broker->AddPlaceholderForPid(helper_.test_child().Handle());
71 #endif
72 #endif
73 }
74 
~ClientController()75 MojoTestBase::ClientController::~ClientController() {
76   CHECK(was_shutdown_)
77       << "Test clients should be waited on explicitly with WaitForShutdown().";
78 }
79 
WaitForShutdown()80 int MojoTestBase::ClientController::WaitForShutdown() {
81   was_shutdown_ = true;
82 #if !defined(OS_IOS)
83   int retval = helper_.WaitForChildShutdown();
84 #if defined(OS_MACOSX)
85   base::AutoLock lock(g_mach_broker->GetLock());
86   g_mach_broker->InvalidatePid(helper_.test_child().Handle());
87 #endif
88   return retval;
89 #else
90   NOTREACHED();
91   return 1;
92 #endif
93 }
94 
95 // static
CloseHandle(MojoHandle h)96 void MojoTestBase::CloseHandle(MojoHandle h) {
97   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h));
98 }
99 
100 // static
CreateMessagePipe(MojoHandle * p0,MojoHandle * p1)101 void MojoTestBase::CreateMessagePipe(MojoHandle* p0, MojoHandle* p1) {
102   MojoCreateMessagePipe(nullptr, p0, p1);
103   CHECK_NE(*p0, MOJO_HANDLE_INVALID);
104   CHECK_NE(*p1, MOJO_HANDLE_INVALID);
105 }
106 
107 // static
WriteMessageWithHandles(MojoHandle mp,const std::string & message,const MojoHandle * handles,uint32_t num_handles)108 void MojoTestBase::WriteMessageWithHandles(MojoHandle mp,
109                                            const std::string& message,
110                                            const MojoHandle* handles,
111                                            uint32_t num_handles) {
112   CHECK_EQ(WriteMessageRaw(MessagePipeHandle(mp), message.data(),
113                            static_cast<uint32_t>(message.size()), handles,
114                            num_handles, MOJO_WRITE_MESSAGE_FLAG_NONE),
115            MOJO_RESULT_OK);
116 }
117 
118 // static
WriteMessage(MojoHandle mp,const std::string & message)119 void MojoTestBase::WriteMessage(MojoHandle mp, const std::string& message) {
120   WriteMessageWithHandles(mp, message, nullptr, 0);
121 }
122 
123 // static
ReadMessageWithHandles(MojoHandle mp,MojoHandle * out_handles,uint32_t expected_num_handles)124 std::string MojoTestBase::ReadMessageWithHandles(
125     MojoHandle mp,
126     MojoHandle* out_handles,
127     uint32_t expected_num_handles) {
128   CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK);
129 
130   std::vector<uint8_t> bytes;
131   std::vector<ScopedHandle> handles;
132   CHECK_EQ(MOJO_RESULT_OK,
133            ReadMessageRaw(MessagePipeHandle(mp), &bytes, &handles,
134                           MOJO_READ_MESSAGE_FLAG_NONE));
135   CHECK_EQ(expected_num_handles, handles.size());
136   for (size_t i = 0; i < handles.size(); ++i)
137     out_handles[i] = handles[i].release().value();
138 
139   return std::string(bytes.begin(), bytes.end());
140 }
141 
142 // static
ReadMessageWithOptionalHandle(MojoHandle mp,MojoHandle * handle)143 std::string MojoTestBase::ReadMessageWithOptionalHandle(MojoHandle mp,
144                                                         MojoHandle* handle) {
145   CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK);
146 
147   std::vector<uint8_t> bytes;
148   std::vector<ScopedHandle> handles;
149   CHECK_EQ(MOJO_RESULT_OK,
150            ReadMessageRaw(MessagePipeHandle(mp), &bytes, &handles,
151                           MOJO_READ_MESSAGE_FLAG_NONE));
152   CHECK(handles.size() == 0 || handles.size() == 1);
153   CHECK(handle);
154 
155   if (handles.size() == 1)
156     *handle = handles[0].release().value();
157   else
158     *handle = MOJO_HANDLE_INVALID;
159 
160   return std::string(bytes.begin(), bytes.end());
161 }
162 
163 // static
ReadMessage(MojoHandle mp)164 std::string MojoTestBase::ReadMessage(MojoHandle mp) {
165   return ReadMessageWithHandles(mp, nullptr, 0);
166 }
167 
168 // static
ReadMessage(MojoHandle mp,char * data,size_t num_bytes)169 void MojoTestBase::ReadMessage(MojoHandle mp, char* data, size_t num_bytes) {
170   CHECK_EQ(WaitForSignals(mp, MOJO_HANDLE_SIGNAL_READABLE), MOJO_RESULT_OK);
171 
172   std::vector<uint8_t> bytes;
173   std::vector<ScopedHandle> handles;
174   CHECK_EQ(MOJO_RESULT_OK,
175            ReadMessageRaw(MessagePipeHandle(mp), &bytes, &handles,
176                           MOJO_READ_MESSAGE_FLAG_NONE));
177   CHECK_EQ(0u, handles.size());
178   CHECK_EQ(num_bytes, bytes.size());
179   memcpy(data, bytes.data(), bytes.size());
180 }
181 
182 // static
VerifyTransmission(MojoHandle source,MojoHandle dest,const std::string & message)183 void MojoTestBase::VerifyTransmission(MojoHandle source,
184                                       MojoHandle dest,
185                                       const std::string& message) {
186   WriteMessage(source, message);
187 
188   // We don't use EXPECT_EQ; failures on really long messages make life hard.
189   EXPECT_TRUE(message == ReadMessage(dest));
190 }
191 
192 // static
VerifyEcho(MojoHandle mp,const std::string & message)193 void MojoTestBase::VerifyEcho(MojoHandle mp, const std::string& message) {
194   VerifyTransmission(mp, mp, message);
195 }
196 
197 // static
CreateBuffer(uint64_t size)198 MojoHandle MojoTestBase::CreateBuffer(uint64_t size) {
199   MojoHandle h;
200   EXPECT_EQ(MojoCreateSharedBuffer(size, nullptr, &h), MOJO_RESULT_OK);
201   return h;
202 }
203 
204 // static
DuplicateBuffer(MojoHandle h,bool read_only)205 MojoHandle MojoTestBase::DuplicateBuffer(MojoHandle h, bool read_only) {
206   MojoHandle new_handle;
207   MojoDuplicateBufferHandleOptions options = {
208       sizeof(MojoDuplicateBufferHandleOptions),
209       MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_NONE};
210   if (read_only)
211     options.flags |= MOJO_DUPLICATE_BUFFER_HANDLE_FLAG_READ_ONLY;
212   EXPECT_EQ(MOJO_RESULT_OK,
213             MojoDuplicateBufferHandle(h, &options, &new_handle));
214   return new_handle;
215 }
216 
217 // static
WriteToBuffer(MojoHandle h,size_t offset,const base::StringPiece & s)218 void MojoTestBase::WriteToBuffer(MojoHandle h,
219                                  size_t offset,
220                                  const base::StringPiece& s) {
221   char* data;
222   EXPECT_EQ(MOJO_RESULT_OK, MojoMapBuffer(h, offset, s.size(), nullptr,
223                                           reinterpret_cast<void**>(&data)));
224   memcpy(data, s.data(), s.size());
225   EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(static_cast<void*>(data)));
226 }
227 
228 // static
ExpectBufferContents(MojoHandle h,size_t offset,const base::StringPiece & s)229 void MojoTestBase::ExpectBufferContents(MojoHandle h,
230                                         size_t offset,
231                                         const base::StringPiece& s) {
232   char* data;
233   EXPECT_EQ(MOJO_RESULT_OK, MojoMapBuffer(h, offset, s.size(), nullptr,
234                                           reinterpret_cast<void**>(&data)));
235   EXPECT_EQ(s, base::StringPiece(data, s.size()));
236   EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(static_cast<void*>(data)));
237 }
238 
239 // static
CreateDataPipe(MojoHandle * p0,MojoHandle * p1,size_t capacity)240 void MojoTestBase::CreateDataPipe(MojoHandle* p0,
241                                   MojoHandle* p1,
242                                   size_t capacity) {
243   MojoCreateDataPipeOptions options;
244   options.struct_size = static_cast<uint32_t>(sizeof(options));
245   options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
246   options.element_num_bytes = 1;
247   options.capacity_num_bytes = static_cast<uint32_t>(capacity);
248 
249   MojoCreateDataPipe(&options, p0, p1);
250   CHECK_NE(*p0, MOJO_HANDLE_INVALID);
251   CHECK_NE(*p1, MOJO_HANDLE_INVALID);
252 }
253 
254 // static
WriteData(MojoHandle producer,const std::string & data)255 void MojoTestBase::WriteData(MojoHandle producer, const std::string& data) {
256   CHECK_EQ(WaitForSignals(producer, MOJO_HANDLE_SIGNAL_WRITABLE),
257            MOJO_RESULT_OK);
258   uint32_t num_bytes = static_cast<uint32_t>(data.size());
259   MojoWriteDataOptions options;
260   options.struct_size = sizeof(options);
261   options.flags = MOJO_WRITE_DATA_FLAG_ALL_OR_NONE;
262   CHECK_EQ(MojoWriteData(producer, data.data(), &num_bytes, &options),
263            MOJO_RESULT_OK);
264   CHECK_EQ(num_bytes, static_cast<uint32_t>(data.size()));
265 }
266 
267 // static
ReadData(MojoHandle consumer,size_t size)268 std::string MojoTestBase::ReadData(MojoHandle consumer, size_t size) {
269   CHECK_EQ(WaitForSignals(consumer, MOJO_HANDLE_SIGNAL_READABLE),
270            MOJO_RESULT_OK);
271   std::vector<char> buffer(size);
272   uint32_t num_bytes = static_cast<uint32_t>(size);
273   MojoReadDataOptions options;
274   options.struct_size = sizeof(options);
275   options.flags = MOJO_READ_DATA_FLAG_ALL_OR_NONE;
276   CHECK_EQ(MojoReadData(consumer, &options, buffer.data(), &num_bytes),
277            MOJO_RESULT_OK);
278   CHECK_EQ(num_bytes, static_cast<uint32_t>(size));
279 
280   return std::string(buffer.begin(), buffer.end());
281 }
282 
283 // static
GetSignalsState(MojoHandle handle)284 MojoHandleSignalsState MojoTestBase::GetSignalsState(MojoHandle handle) {
285   MojoHandleSignalsState signals_state;
286   CHECK_EQ(MOJO_RESULT_OK, MojoQueryHandleSignalsState(handle, &signals_state));
287   return signals_state;
288 }
289 
290 // static
WaitForSignals(MojoHandle handle,MojoHandleSignals signals,MojoTriggerCondition condition,MojoHandleSignalsState * state)291 MojoResult MojoTestBase::WaitForSignals(MojoHandle handle,
292                                         MojoHandleSignals signals,
293                                         MojoTriggerCondition condition,
294                                         MojoHandleSignalsState* state) {
295   return Wait(Handle(handle), signals, condition, state);
296 }
297 
298 // static
WaitForSignals(MojoHandle handle,MojoHandleSignals signals,MojoHandleSignalsState * state)299 MojoResult MojoTestBase::WaitForSignals(MojoHandle handle,
300                                         MojoHandleSignals signals,
301                                         MojoHandleSignalsState* state) {
302   return Wait(Handle(handle), signals, MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
303               state);
304 }
305 
306 }  // namespace test
307 }  // namespace core
308 }  // namespace mojo
309