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