1 // Copyright 2014 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.
5 // This file tests the C++ Mojo system core wrappers.
6 // TODO(vtl): Maybe rename "CoreCppTest" -> "CoreTest" if/when this gets
7 // compiled into a different binary from the C API tests.
9 #include "mojo/public/cpp/system/core.h"
13 #include "mojo/public/cpp/system/macros.h"
14 #include "testing/gtest/include/gtest/gtest.h"
19 TEST(CoreCppTest
, GetTimeTicksNow
) {
20 const MojoTimeTicks start
= GetTimeTicksNow();
21 EXPECT_NE(static_cast<MojoTimeTicks
>(0), start
)
22 << "GetTimeTicksNow should return nonzero value";
25 TEST(CoreCppTest
, Basic
) {
26 // Basic |Handle| implementation:
28 EXPECT_EQ(MOJO_HANDLE_INVALID
, kInvalidHandleValue
);
31 EXPECT_EQ(kInvalidHandleValue
, h0
.value());
32 EXPECT_EQ(kInvalidHandleValue
, *h0
.mutable_value());
33 EXPECT_FALSE(h0
.is_valid());
35 Handle
h1(static_cast<MojoHandle
>(123));
36 EXPECT_EQ(static_cast<MojoHandle
>(123), h1
.value());
37 EXPECT_EQ(static_cast<MojoHandle
>(123), *h1
.mutable_value());
38 EXPECT_TRUE(h1
.is_valid());
39 *h1
.mutable_value() = static_cast<MojoHandle
>(456);
40 EXPECT_EQ(static_cast<MojoHandle
>(456), h1
.value());
41 EXPECT_TRUE(h1
.is_valid());
44 EXPECT_EQ(static_cast<MojoHandle
>(456), h0
.value());
45 EXPECT_TRUE(h0
.is_valid());
46 EXPECT_FALSE(h1
.is_valid());
48 h1
.set_value(static_cast<MojoHandle
>(789));
50 EXPECT_EQ(static_cast<MojoHandle
>(789), h0
.value());
51 EXPECT_TRUE(h0
.is_valid());
52 EXPECT_EQ(static_cast<MojoHandle
>(456), h1
.value());
53 EXPECT_TRUE(h1
.is_valid());
55 // Make sure copy constructor works.
57 EXPECT_EQ(static_cast<MojoHandle
>(789), h2
.value());
60 EXPECT_EQ(static_cast<MojoHandle
>(456), h2
.value());
62 // Make sure that we can put |Handle|s into |std::map|s.
63 h0
= Handle(static_cast<MojoHandle
>(987));
64 h1
= Handle(static_cast<MojoHandle
>(654));
65 h2
= Handle(static_cast<MojoHandle
>(321));
67 std::map
<Handle
, int> handle_to_int
;
68 handle_to_int
[h0
] = 0;
69 handle_to_int
[h1
] = 1;
70 handle_to_int
[h2
] = 2;
71 handle_to_int
[h3
] = 3;
73 EXPECT_EQ(4u, handle_to_int
.size());
74 EXPECT_FALSE(handle_to_int
.find(h0
) == handle_to_int
.end());
75 EXPECT_EQ(0, handle_to_int
[h0
]);
76 EXPECT_FALSE(handle_to_int
.find(h1
) == handle_to_int
.end());
77 EXPECT_EQ(1, handle_to_int
[h1
]);
78 EXPECT_FALSE(handle_to_int
.find(h2
) == handle_to_int
.end());
79 EXPECT_EQ(2, handle_to_int
[h2
]);
80 EXPECT_FALSE(handle_to_int
.find(h3
) == handle_to_int
.end());
81 EXPECT_EQ(3, handle_to_int
[h3
]);
82 EXPECT_TRUE(handle_to_int
.find(Handle(static_cast<MojoHandle
>(13579))) ==
85 // TODO(vtl): With C++11, support |std::unordered_map|s, etc. (Or figure out
86 // how to support the variations of |hash_map|.)
89 // |Handle|/|ScopedHandle| functions:
93 EXPECT_EQ(kInvalidHandleValue
, h
.get().value());
95 // This should be a no-op.
98 // It should still be invalid.
99 EXPECT_EQ(kInvalidHandleValue
, h
.get().value());
101 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
,
102 Wait(h
.get(), ~MOJO_HANDLE_SIGNAL_NONE
, 1000000));
104 std::vector
<Handle
> wh
;
105 wh
.push_back(h
.get());
106 std::vector
<MojoHandleSignals
> sigs
;
107 sigs
.push_back(~MOJO_HANDLE_SIGNAL_NONE
);
108 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
,
109 WaitMany(wh
, sigs
, MOJO_DEADLINE_INDEFINITE
));
112 // |MakeScopedHandle| (just compilation tests):
114 EXPECT_FALSE(MakeScopedHandle(Handle()).is_valid());
115 EXPECT_FALSE(MakeScopedHandle(MessagePipeHandle()).is_valid());
116 EXPECT_FALSE(MakeScopedHandle(DataPipeProducerHandle()).is_valid());
117 EXPECT_FALSE(MakeScopedHandle(DataPipeConsumerHandle()).is_valid());
118 EXPECT_FALSE(MakeScopedHandle(SharedBufferHandle()).is_valid());
121 // |MessagePipeHandle|/|ScopedMessagePipeHandle| functions:
123 MessagePipeHandle h_invalid
;
124 EXPECT_FALSE(h_invalid
.is_valid());
126 MOJO_RESULT_INVALID_ARGUMENT
,
128 h_invalid
, nullptr, 0, nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE
));
129 char buffer
[10] = {0};
130 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
,
131 WriteMessageRaw(h_invalid
,
136 MOJO_WRITE_MESSAGE_FLAG_NONE
));
137 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
,
138 ReadMessageRaw(h_invalid
,
143 MOJO_READ_MESSAGE_FLAG_NONE
));
144 uint32_t buffer_size
= static_cast<uint32_t>(sizeof(buffer
));
145 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
,
146 ReadMessageRaw(h_invalid
,
151 MOJO_READ_MESSAGE_FLAG_NONE
));
153 // Basic tests of waiting and closing.
154 MojoHandle hv0
= kInvalidHandleValue
;
156 ScopedMessagePipeHandle h0
;
157 ScopedMessagePipeHandle h1
;
158 EXPECT_FALSE(h0
.get().is_valid());
159 EXPECT_FALSE(h1
.get().is_valid());
161 CreateMessagePipe(nullptr, &h0
, &h1
);
162 EXPECT_TRUE(h0
.get().is_valid());
163 EXPECT_TRUE(h1
.get().is_valid());
164 EXPECT_NE(h0
.get().value(), h1
.get().value());
165 // Save the handle values, so we can check that things got closed
167 hv0
= h0
.get().value();
168 MojoHandle hv1
= h1
.get().value();
170 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED
,
171 Wait(h0
.get(), MOJO_HANDLE_SIGNAL_READABLE
, 0));
172 std::vector
<Handle
> wh
;
173 wh
.push_back(h0
.get());
174 wh
.push_back(h1
.get());
175 std::vector
<MojoHandleSignals
> sigs
;
176 sigs
.push_back(MOJO_HANDLE_SIGNAL_READABLE
);
177 sigs
.push_back(MOJO_HANDLE_SIGNAL_WRITABLE
);
178 EXPECT_EQ(1, WaitMany(wh
, sigs
, 1000));
180 // Test closing |h1| explicitly.
182 EXPECT_FALSE(h1
.get().is_valid());
184 // Make sure |h1| is closed.
186 MOJO_RESULT_INVALID_ARGUMENT
,
187 MojoWait(hv1
, ~MOJO_HANDLE_SIGNAL_NONE
, MOJO_DEADLINE_INDEFINITE
));
190 MOJO_RESULT_FAILED_PRECONDITION
,
192 h0
.get(), MOJO_HANDLE_SIGNAL_READABLE
, MOJO_DEADLINE_INDEFINITE
));
194 // |hv0| should have been closed when |h0| went out of scope, so this close
196 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
, MojoClose(hv0
));
198 // Actually test writing/reading messages.
200 ScopedMessagePipeHandle h0
;
201 ScopedMessagePipeHandle h1
;
202 CreateMessagePipe(nullptr, &h0
, &h1
);
204 const char kHello
[] = "hello";
205 const uint32_t kHelloSize
= static_cast<uint32_t>(sizeof(kHello
));
206 EXPECT_EQ(MOJO_RESULT_OK
,
207 WriteMessageRaw(h0
.get(),
212 MOJO_WRITE_MESSAGE_FLAG_NONE
));
216 h1
.get(), MOJO_HANDLE_SIGNAL_READABLE
, MOJO_DEADLINE_INDEFINITE
));
217 char buffer
[10] = {0};
218 uint32_t buffer_size
= static_cast<uint32_t>(sizeof(buffer
));
219 EXPECT_EQ(MOJO_RESULT_OK
,
220 ReadMessageRaw(h1
.get(),
225 MOJO_READ_MESSAGE_FLAG_NONE
));
226 EXPECT_EQ(kHelloSize
, buffer_size
);
227 EXPECT_STREQ(kHello
, buffer
);
229 // Send a handle over the previously-establish message pipe. Use the
230 // |MessagePipe| wrapper (to test it), which automatically creates a
234 // Write a message to |mp.handle0|, before we send |mp.handle1|.
235 const char kWorld
[] = "world!";
236 const uint32_t kWorldSize
= static_cast<uint32_t>(sizeof(kWorld
));
237 EXPECT_EQ(MOJO_RESULT_OK
,
238 WriteMessageRaw(mp
.handle0
.get(),
243 MOJO_WRITE_MESSAGE_FLAG_NONE
));
245 // Send |mp.handle1| over |h1| to |h0|.
246 MojoHandle handles
[5];
247 handles
[0] = mp
.handle1
.release().value();
248 EXPECT_NE(kInvalidHandleValue
, handles
[0]);
249 EXPECT_FALSE(mp
.handle1
.get().is_valid());
250 uint32_t handles_count
= 1;
251 EXPECT_EQ(MOJO_RESULT_OK
,
252 WriteMessageRaw(h1
.get(),
257 MOJO_WRITE_MESSAGE_FLAG_NONE
));
258 // |handles[0]| should actually be invalid now.
259 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
, MojoClose(handles
[0]));
261 // Read "hello" and the sent handle.
265 h0
.get(), MOJO_HANDLE_SIGNAL_READABLE
, MOJO_DEADLINE_INDEFINITE
));
266 memset(buffer
, 0, sizeof(buffer
));
267 buffer_size
= static_cast<uint32_t>(sizeof(buffer
));
268 for (size_t i
= 0; i
< MOJO_ARRAYSIZE(handles
); i
++)
269 handles
[i
] = kInvalidHandleValue
;
270 handles_count
= static_cast<uint32_t>(MOJO_ARRAYSIZE(handles
));
271 EXPECT_EQ(MOJO_RESULT_OK
,
272 ReadMessageRaw(h0
.get(),
277 MOJO_READ_MESSAGE_FLAG_NONE
));
278 EXPECT_EQ(kHelloSize
, buffer_size
);
279 EXPECT_STREQ(kHello
, buffer
);
280 EXPECT_EQ(1u, handles_count
);
281 EXPECT_NE(kInvalidHandleValue
, handles
[0]);
283 // Read from the sent/received handle.
284 mp
.handle1
.reset(MessagePipeHandle(handles
[0]));
285 // Save |handles[0]| to check that it gets properly closed.
287 EXPECT_EQ(MOJO_RESULT_OK
,
288 Wait(mp
.handle1
.get(),
289 MOJO_HANDLE_SIGNAL_READABLE
,
290 MOJO_DEADLINE_INDEFINITE
));
291 memset(buffer
, 0, sizeof(buffer
));
292 buffer_size
= static_cast<uint32_t>(sizeof(buffer
));
293 for (size_t i
= 0; i
< MOJO_ARRAYSIZE(handles
); i
++)
294 handles
[i
] = kInvalidHandleValue
;
295 handles_count
= static_cast<uint32_t>(MOJO_ARRAYSIZE(handles
));
296 EXPECT_EQ(MOJO_RESULT_OK
,
297 ReadMessageRaw(mp
.handle1
.get(),
302 MOJO_READ_MESSAGE_FLAG_NONE
));
303 EXPECT_EQ(kWorldSize
, buffer_size
);
304 EXPECT_STREQ(kWorld
, buffer
);
305 EXPECT_EQ(0u, handles_count
);
307 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
, MojoClose(hv0
));
310 // TODO(vtl): Test |CloseRaw()|.
311 // TODO(vtl): Test |reset()| more thoroughly?
314 TEST(CoreCppTest
, TearDownWithMessagesEnqueued
) {
315 // Tear down a message pipe which still has a message enqueued, with the
316 // message also having a valid message pipe handle.
318 ScopedMessagePipeHandle h0
;
319 ScopedMessagePipeHandle h1
;
320 CreateMessagePipe(nullptr, &h0
, &h1
);
322 // Send a handle over the previously-establish message pipe.
323 ScopedMessagePipeHandle h2
;
324 ScopedMessagePipeHandle h3
;
325 CreateMessagePipe(nullptr, &h2
, &h3
);
327 // Write a message to |h2|, before we send |h3|.
328 const char kWorld
[] = "world!";
329 const uint32_t kWorldSize
= static_cast<uint32_t>(sizeof(kWorld
));
330 EXPECT_EQ(MOJO_RESULT_OK
,
331 WriteMessageRaw(h2
.get(),
336 MOJO_WRITE_MESSAGE_FLAG_NONE
));
337 // And also a message to |h3|.
338 EXPECT_EQ(MOJO_RESULT_OK
,
339 WriteMessageRaw(h3
.get(),
344 MOJO_WRITE_MESSAGE_FLAG_NONE
));
346 // Send |h3| over |h1| to |h0|.
347 const char kHello
[] = "hello";
348 const uint32_t kHelloSize
= static_cast<uint32_t>(sizeof(kHello
));
350 h3_value
= h3
.release().value();
351 EXPECT_NE(kInvalidHandleValue
, h3_value
);
352 EXPECT_FALSE(h3
.get().is_valid());
353 EXPECT_EQ(MOJO_RESULT_OK
,
354 WriteMessageRaw(h1
.get(),
359 MOJO_WRITE_MESSAGE_FLAG_NONE
));
360 // |h3_value| should actually be invalid now.
361 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
, MojoClose(h3_value
));
363 EXPECT_EQ(MOJO_RESULT_OK
, MojoClose(h0
.release().value()));
364 EXPECT_EQ(MOJO_RESULT_OK
, MojoClose(h1
.release().value()));
365 EXPECT_EQ(MOJO_RESULT_OK
, MojoClose(h2
.release().value()));
368 // Do this in a different order: make the enqueued message pipe handle only
371 ScopedMessagePipeHandle h0
;
372 ScopedMessagePipeHandle h1
;
373 CreateMessagePipe(nullptr, &h0
, &h1
);
375 // Send a handle over the previously-establish message pipe.
376 ScopedMessagePipeHandle h2
;
377 ScopedMessagePipeHandle h3
;
378 CreateMessagePipe(nullptr, &h2
, &h3
);
380 // Write a message to |h2|, before we send |h3|.
381 const char kWorld
[] = "world!";
382 const uint32_t kWorldSize
= static_cast<uint32_t>(sizeof(kWorld
));
383 EXPECT_EQ(MOJO_RESULT_OK
,
384 WriteMessageRaw(h2
.get(),
389 MOJO_WRITE_MESSAGE_FLAG_NONE
));
390 // And also a message to |h3|.
391 EXPECT_EQ(MOJO_RESULT_OK
,
392 WriteMessageRaw(h3
.get(),
397 MOJO_WRITE_MESSAGE_FLAG_NONE
));
399 // Send |h3| over |h1| to |h0|.
400 const char kHello
[] = "hello";
401 const uint32_t kHelloSize
= static_cast<uint32_t>(sizeof(kHello
));
403 h3_value
= h3
.release().value();
404 EXPECT_NE(kInvalidHandleValue
, h3_value
);
405 EXPECT_FALSE(h3
.get().is_valid());
406 EXPECT_EQ(MOJO_RESULT_OK
,
407 WriteMessageRaw(h1
.get(),
412 MOJO_WRITE_MESSAGE_FLAG_NONE
));
413 // |h3_value| should actually be invalid now.
414 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT
, MojoClose(h3_value
));
416 EXPECT_EQ(MOJO_RESULT_OK
, MojoClose(h2
.release().value()));
417 EXPECT_EQ(MOJO_RESULT_OK
, MojoClose(h0
.release().value()));
418 EXPECT_EQ(MOJO_RESULT_OK
, MojoClose(h1
.release().value()));
422 TEST(CoreCppTest
, ScopedHandleMoveCtor
) {
423 ScopedSharedBufferHandle buffer1
;
424 EXPECT_EQ(MOJO_RESULT_OK
, CreateSharedBuffer(nullptr, 1024, &buffer1
));
425 EXPECT_TRUE(buffer1
.is_valid());
427 ScopedSharedBufferHandle buffer2
;
428 EXPECT_EQ(MOJO_RESULT_OK
, CreateSharedBuffer(nullptr, 1024, &buffer2
));
429 EXPECT_TRUE(buffer2
.is_valid());
431 // If this fails to close buffer1, ScopedHandleBase::CloseIfNecessary() will
433 buffer1
= buffer2
.Pass();
435 EXPECT_TRUE(buffer1
.is_valid());
436 EXPECT_FALSE(buffer2
.is_valid());
439 TEST(CoreCppTest
, ScopedHandleMoveCtorSelf
) {
440 ScopedSharedBufferHandle buffer1
;
441 EXPECT_EQ(MOJO_RESULT_OK
, CreateSharedBuffer(nullptr, 1024, &buffer1
));
442 EXPECT_TRUE(buffer1
.is_valid());
444 buffer1
= buffer1
.Pass();
446 EXPECT_TRUE(buffer1
.is_valid());
449 // TODO(vtl): Write data pipe tests.