OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 // 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. | |
8 | |
9 #include "mojo/public/cpp/system/core.h" | |
10 | |
11 #include <map> | |
12 | |
13 #include "mojo/public/cpp/system/macros.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 | |
16 namespace mojo { | |
17 namespace { | |
18 | |
19 TEST(CoreCppTest, GetTimeTicksNow) { | |
20 const MojoTimeTicks start = GetTimeTicksNow(); | |
21 EXPECT_NE(static_cast<MojoTimeTicks>(0), start) | |
22 << "GetTimeTicksNow should return nonzero value"; | |
23 } | |
24 | |
25 TEST(CoreCppTest, Basic) { | |
26 // Basic |Handle| implementation: | |
27 { | |
28 EXPECT_EQ(MOJO_HANDLE_INVALID, kInvalidHandleValue); | |
29 | |
30 Handle h0; | |
31 EXPECT_EQ(kInvalidHandleValue, h0.value()); | |
32 EXPECT_EQ(kInvalidHandleValue, *h0.mutable_value()); | |
33 EXPECT_FALSE(h0.is_valid()); | |
34 | |
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()); | |
42 | |
43 h1.swap(h0); | |
44 EXPECT_EQ(static_cast<MojoHandle>(456), h0.value()); | |
45 EXPECT_TRUE(h0.is_valid()); | |
46 EXPECT_FALSE(h1.is_valid()); | |
47 | |
48 h1.set_value(static_cast<MojoHandle>(789)); | |
49 h0.swap(h1); | |
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()); | |
54 | |
55 // Make sure copy constructor works. | |
56 Handle h2(h0); | |
57 EXPECT_EQ(static_cast<MojoHandle>(789), h2.value()); | |
58 // And assignment. | |
59 h2 = h1; | |
60 EXPECT_EQ(static_cast<MojoHandle>(456), h2.value()); | |
61 | |
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)); | |
66 Handle h3; | |
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; | |
72 | |
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))) == | |
83 handle_to_int.end()); | |
84 | |
85 // TODO(vtl): With C++11, support |std::unordered_map|s, etc. (Or figure out | |
86 // how to support the variations of |hash_map|.) | |
87 } | |
88 | |
89 // |Handle|/|ScopedHandle| functions: | |
90 { | |
91 ScopedHandle h; | |
92 | |
93 EXPECT_EQ(kInvalidHandleValue, h.get().value()); | |
94 | |
95 // This should be a no-op. | |
96 Close(h.Pass()); | |
97 | |
98 // It should still be invalid. | |
99 EXPECT_EQ(kInvalidHandleValue, h.get().value()); | |
100 | |
101 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
102 Wait(h.get(), MOJO_WAIT_FLAG_EVERYTHING, 1000000)); | |
103 | |
104 std::vector<Handle> wh; | |
105 wh.push_back(h.get()); | |
106 std::vector<MojoWaitFlags> wf; | |
107 wf.push_back(MOJO_WAIT_FLAG_EVERYTHING); | |
108 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
109 WaitMany(wh, wf, MOJO_DEADLINE_INDEFINITE)); | |
110 } | |
111 | |
112 // |MakeScopedHandle| (just compilation tests): | |
113 { | |
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()); | |
119 } | |
120 | |
121 // |MessagePipeHandle|/|ScopedMessagePipeHandle| functions: | |
122 { | |
123 MessagePipeHandle h_invalid; | |
124 EXPECT_FALSE(h_invalid.is_valid()); | |
125 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
126 WriteMessageRaw(h_invalid, | |
127 NULL, 0, | |
128 NULL, 0, | |
129 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
130 char buffer[10] = { 0 }; | |
131 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
132 WriteMessageRaw(h_invalid, | |
133 buffer, sizeof(buffer), | |
134 NULL, 0, | |
135 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
136 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
137 ReadMessageRaw(h_invalid, | |
138 NULL, NULL, | |
139 NULL, NULL, | |
140 MOJO_READ_MESSAGE_FLAG_NONE)); | |
141 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
142 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
143 ReadMessageRaw(h_invalid, | |
144 buffer, &buffer_size, | |
145 NULL, NULL, | |
146 MOJO_READ_MESSAGE_FLAG_NONE)); | |
147 | |
148 // Basic tests of waiting and closing. | |
149 MojoHandle hv0 = kInvalidHandleValue; | |
150 { | |
151 ScopedMessagePipeHandle h0; | |
152 ScopedMessagePipeHandle h1; | |
153 EXPECT_FALSE(h0.get().is_valid()); | |
154 EXPECT_FALSE(h1.get().is_valid()); | |
155 | |
156 CreateMessagePipe(&h0, &h1); | |
157 EXPECT_TRUE(h0.get().is_valid()); | |
158 EXPECT_TRUE(h1.get().is_valid()); | |
159 EXPECT_NE(h0.get().value(), h1.get().value()); | |
160 // Save the handle values, so we can check that things got closed | |
161 // correctly. | |
162 hv0 = h0.get().value(); | |
163 MojoHandle hv1 = h1.get().value(); | |
164 | |
165 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, | |
166 Wait(h0.get(), MOJO_WAIT_FLAG_READABLE, 0)); | |
167 std::vector<Handle> wh; | |
168 wh.push_back(h0.get()); | |
169 wh.push_back(h1.get()); | |
170 std::vector<MojoWaitFlags> wf; | |
171 wf.push_back(MOJO_WAIT_FLAG_READABLE); | |
172 wf.push_back(MOJO_WAIT_FLAG_WRITABLE); | |
173 EXPECT_EQ(1, WaitMany(wh, wf, 1000)); | |
174 | |
175 // Test closing |h1| explicitly. | |
176 Close(h1.Pass()); | |
177 EXPECT_FALSE(h1.get().is_valid()); | |
178 | |
179 // Make sure |h1| is closed. | |
180 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
181 MojoWait(hv1, MOJO_WAIT_FLAG_EVERYTHING, | |
182 MOJO_DEADLINE_INDEFINITE)); | |
183 | |
184 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
185 Wait(h0.get(), MOJO_WAIT_FLAG_READABLE, | |
186 MOJO_DEADLINE_INDEFINITE)); | |
187 } | |
188 // |hv0| should have been closed when |h0| went out of scope, so this close | |
189 // should fail. | |
190 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0)); | |
191 | |
192 // Actually test writing/reading messages. | |
193 { | |
194 ScopedMessagePipeHandle h0; | |
195 ScopedMessagePipeHandle h1; | |
196 CreateMessagePipe(&h0, &h1); | |
197 | |
198 const char kHello[] = "hello"; | |
199 const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); | |
200 EXPECT_EQ(MOJO_RESULT_OK, | |
201 WriteMessageRaw(h0.get(), | |
202 kHello, kHelloSize, | |
203 NULL, 0, | |
204 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
205 EXPECT_EQ(MOJO_RESULT_OK, | |
206 Wait(h1.get(), MOJO_WAIT_FLAG_READABLE, | |
207 MOJO_DEADLINE_INDEFINITE)); | |
208 char buffer[10] = { 0 }; | |
209 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
210 EXPECT_EQ(MOJO_RESULT_OK, | |
211 ReadMessageRaw(h1.get(), | |
212 buffer, &buffer_size, | |
213 NULL, NULL, | |
214 MOJO_READ_MESSAGE_FLAG_NONE)); | |
215 EXPECT_EQ(kHelloSize, buffer_size); | |
216 EXPECT_STREQ(kHello, buffer); | |
217 | |
218 // Send a handle over the previously-establish message pipe. Use the | |
219 // |MessagePipe| wrapper (to test it), which automatically creates a | |
220 // message pipe. | |
221 MessagePipe mp; | |
222 | |
223 // Write a message to |mp.handle0|, before we send |mp.handle1|. | |
224 const char kWorld[] = "world!"; | |
225 const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); | |
226 EXPECT_EQ(MOJO_RESULT_OK, | |
227 WriteMessageRaw(mp.handle0.get(), | |
228 kWorld, kWorldSize, | |
229 NULL, 0, | |
230 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
231 | |
232 // Send |mp.handle1| over |h1| to |h0|. | |
233 MojoHandle handles[5]; | |
234 handles[0] = mp.handle1.release().value(); | |
235 EXPECT_NE(kInvalidHandleValue, handles[0]); | |
236 EXPECT_FALSE(mp.handle1.get().is_valid()); | |
237 uint32_t handles_count = 1; | |
238 EXPECT_EQ(MOJO_RESULT_OK, | |
239 WriteMessageRaw(h1.get(), | |
240 kHello, kHelloSize, | |
241 handles, handles_count, | |
242 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
243 // |handles[0]| should actually be invalid now. | |
244 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handles[0])); | |
245 | |
246 // Read "hello" and the sent handle. | |
247 EXPECT_EQ(MOJO_RESULT_OK, | |
248 Wait(h0.get(), MOJO_WAIT_FLAG_READABLE, | |
249 MOJO_DEADLINE_INDEFINITE)); | |
250 memset(buffer, 0, sizeof(buffer)); | |
251 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
252 for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++) | |
253 handles[i] = kInvalidHandleValue; | |
254 handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles)); | |
255 EXPECT_EQ(MOJO_RESULT_OK, | |
256 ReadMessageRaw(h0.get(), | |
257 buffer, &buffer_size, | |
258 handles, &handles_count, | |
259 MOJO_READ_MESSAGE_FLAG_NONE)); | |
260 EXPECT_EQ(kHelloSize, buffer_size); | |
261 EXPECT_STREQ(kHello, buffer); | |
262 EXPECT_EQ(1u, handles_count); | |
263 EXPECT_NE(kInvalidHandleValue, handles[0]); | |
264 | |
265 // Read from the sent/received handle. | |
266 mp.handle1.reset(MessagePipeHandle(handles[0])); | |
267 // Save |handles[0]| to check that it gets properly closed. | |
268 hv0 = handles[0]; | |
269 EXPECT_EQ(MOJO_RESULT_OK, | |
270 Wait(mp.handle1.get(), MOJO_WAIT_FLAG_READABLE, | |
271 MOJO_DEADLINE_INDEFINITE)); | |
272 memset(buffer, 0, sizeof(buffer)); | |
273 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
274 for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++) | |
275 handles[i] = kInvalidHandleValue; | |
276 handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles)); | |
277 EXPECT_EQ(MOJO_RESULT_OK, | |
278 ReadMessageRaw(mp.handle1.get(), | |
279 buffer, &buffer_size, | |
280 handles, &handles_count, | |
281 MOJO_READ_MESSAGE_FLAG_NONE)); | |
282 EXPECT_EQ(kWorldSize, buffer_size); | |
283 EXPECT_STREQ(kWorld, buffer); | |
284 EXPECT_EQ(0u, handles_count); | |
285 } | |
286 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0)); | |
287 } | |
288 | |
289 // TODO(vtl): Test |CloseRaw()|. | |
290 // TODO(vtl): Test |reset()| more thoroughly? | |
291 } | |
292 | |
293 TEST(CoreCppTest, TearDownWithMessagesEnqueued) { | |
294 // Tear down a message pipe which still has a message enqueued, with the | |
295 // message also having a valid message pipe handle. | |
296 { | |
297 ScopedMessagePipeHandle h0; | |
298 ScopedMessagePipeHandle h1; | |
299 CreateMessagePipe(&h0, &h1); | |
300 | |
301 // Send a handle over the previously-establish message pipe. | |
302 ScopedMessagePipeHandle h2; | |
303 ScopedMessagePipeHandle h3; | |
304 CreateMessagePipe(&h2, &h3); | |
305 | |
306 // Write a message to |h2|, before we send |h3|. | |
307 const char kWorld[] = "world!"; | |
308 const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); | |
309 EXPECT_EQ(MOJO_RESULT_OK, | |
310 WriteMessageRaw(h2.get(), | |
311 kWorld, kWorldSize, | |
312 NULL, 0, | |
313 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
314 // And also a message to |h3|. | |
315 EXPECT_EQ(MOJO_RESULT_OK, | |
316 WriteMessageRaw(h3.get(), | |
317 kWorld, kWorldSize, | |
318 NULL, 0, | |
319 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
320 | |
321 // Send |h3| over |h1| to |h0|. | |
322 const char kHello[] = "hello"; | |
323 const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); | |
324 MojoHandle h3_value; | |
325 h3_value = h3.release().value(); | |
326 EXPECT_NE(kInvalidHandleValue, h3_value); | |
327 EXPECT_FALSE(h3.get().is_valid()); | |
328 EXPECT_EQ(MOJO_RESULT_OK, | |
329 WriteMessageRaw(h1.get(), | |
330 kHello, kHelloSize, | |
331 &h3_value, 1, | |
332 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
333 // |h3_value| should actually be invalid now. | |
334 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value)); | |
335 | |
336 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value())); | |
337 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value())); | |
338 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value())); | |
339 } | |
340 | |
341 // Do this in a different order: make the enqueued message pipe handle only | |
342 // half-alive. | |
343 { | |
344 ScopedMessagePipeHandle h0; | |
345 ScopedMessagePipeHandle h1; | |
346 CreateMessagePipe(&h0, &h1); | |
347 | |
348 // Send a handle over the previously-establish message pipe. | |
349 ScopedMessagePipeHandle h2; | |
350 ScopedMessagePipeHandle h3; | |
351 CreateMessagePipe(&h2, &h3); | |
352 | |
353 // Write a message to |h2|, before we send |h3|. | |
354 const char kWorld[] = "world!"; | |
355 const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); | |
356 EXPECT_EQ(MOJO_RESULT_OK, | |
357 WriteMessageRaw(h2.get(), | |
358 kWorld, kWorldSize, | |
359 NULL, 0, | |
360 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
361 // And also a message to |h3|. | |
362 EXPECT_EQ(MOJO_RESULT_OK, | |
363 WriteMessageRaw(h3.get(), | |
364 kWorld, kWorldSize, | |
365 NULL, 0, | |
366 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
367 | |
368 // Send |h3| over |h1| to |h0|. | |
369 const char kHello[] = "hello"; | |
370 const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); | |
371 MojoHandle h3_value; | |
372 h3_value = h3.release().value(); | |
373 EXPECT_NE(kInvalidHandleValue, h3_value); | |
374 EXPECT_FALSE(h3.get().is_valid()); | |
375 EXPECT_EQ(MOJO_RESULT_OK, | |
376 WriteMessageRaw(h1.get(), | |
377 kHello, kHelloSize, | |
378 &h3_value, 1, | |
379 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
380 // |h3_value| should actually be invalid now. | |
381 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value)); | |
382 | |
383 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value())); | |
384 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value())); | |
385 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value())); | |
386 } | |
387 } | |
388 | |
389 // TODO(vtl): Write data pipe tests. | |
390 | |
391 } // namespace | |
392 } // namespace mojo | |
OLD | NEW |