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.
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 <stddef.h>
12#include <stdint.h>
13#include <map>
14#include <utility>
15
16#include "testing/gtest/include/gtest/gtest.h"
17
18namespace mojo {
19namespace {
20
21const MojoHandleSignals kSignalReadableWritable =
22    MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE;
23
24const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE |
25                                     MOJO_HANDLE_SIGNAL_WRITABLE |
26                                     MOJO_HANDLE_SIGNAL_PEER_CLOSED;
27
28TEST(CoreCppTest, GetTimeTicksNow) {
29  const MojoTimeTicks start = GetTimeTicksNow();
30  EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
31      << "GetTimeTicksNow should return nonzero value";
32}
33
34TEST(CoreCppTest, Basic) {
35  // Basic |Handle| implementation:
36  {
37    EXPECT_EQ(MOJO_HANDLE_INVALID, kInvalidHandleValue);
38
39    Handle h0;
40    EXPECT_EQ(kInvalidHandleValue, h0.value());
41    EXPECT_EQ(kInvalidHandleValue, *h0.mutable_value());
42    EXPECT_FALSE(h0.is_valid());
43
44    Handle h1(static_cast<MojoHandle>(123));
45    EXPECT_EQ(static_cast<MojoHandle>(123), h1.value());
46    EXPECT_EQ(static_cast<MojoHandle>(123), *h1.mutable_value());
47    EXPECT_TRUE(h1.is_valid());
48    *h1.mutable_value() = static_cast<MojoHandle>(456);
49    EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
50    EXPECT_TRUE(h1.is_valid());
51
52    h1.swap(h0);
53    EXPECT_EQ(static_cast<MojoHandle>(456), h0.value());
54    EXPECT_TRUE(h0.is_valid());
55    EXPECT_FALSE(h1.is_valid());
56
57    h1.set_value(static_cast<MojoHandle>(789));
58    h0.swap(h1);
59    EXPECT_EQ(static_cast<MojoHandle>(789), h0.value());
60    EXPECT_TRUE(h0.is_valid());
61    EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
62    EXPECT_TRUE(h1.is_valid());
63
64    // Make sure copy constructor works.
65    Handle h2(h0);
66    EXPECT_EQ(static_cast<MojoHandle>(789), h2.value());
67    // And assignment.
68    h2 = h1;
69    EXPECT_EQ(static_cast<MojoHandle>(456), h2.value());
70
71    // Make sure that we can put |Handle|s into |std::map|s.
72    h0 = Handle(static_cast<MojoHandle>(987));
73    h1 = Handle(static_cast<MojoHandle>(654));
74    h2 = Handle(static_cast<MojoHandle>(321));
75    Handle h3;
76    std::map<Handle, int> handle_to_int;
77    handle_to_int[h0] = 0;
78    handle_to_int[h1] = 1;
79    handle_to_int[h2] = 2;
80    handle_to_int[h3] = 3;
81
82    EXPECT_EQ(4u, handle_to_int.size());
83    EXPECT_FALSE(handle_to_int.find(h0) == handle_to_int.end());
84    EXPECT_EQ(0, handle_to_int[h0]);
85    EXPECT_FALSE(handle_to_int.find(h1) == handle_to_int.end());
86    EXPECT_EQ(1, handle_to_int[h1]);
87    EXPECT_FALSE(handle_to_int.find(h2) == handle_to_int.end());
88    EXPECT_EQ(2, handle_to_int[h2]);
89    EXPECT_FALSE(handle_to_int.find(h3) == handle_to_int.end());
90    EXPECT_EQ(3, handle_to_int[h3]);
91    EXPECT_TRUE(handle_to_int.find(Handle(static_cast<MojoHandle>(13579))) ==
92                handle_to_int.end());
93
94    // TODO(vtl): With C++11, support |std::unordered_map|s, etc. (Or figure out
95    // how to support the variations of |hash_map|.)
96  }
97
98  // |Handle|/|ScopedHandle| functions:
99  {
100    ScopedHandle h;
101
102    EXPECT_EQ(kInvalidHandleValue, h.get().value());
103
104    // This should be a no-op.
105    Close(std::move(h));
106
107    // It should still be invalid.
108    EXPECT_EQ(kInvalidHandleValue, h.get().value());
109
110    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
111              Wait(h.get(), ~MOJO_HANDLE_SIGNAL_NONE, 1000000, nullptr));
112
113    std::vector<Handle> wh;
114    wh.push_back(h.get());
115    std::vector<MojoHandleSignals> sigs;
116    sigs.push_back(~MOJO_HANDLE_SIGNAL_NONE);
117    WaitManyResult wait_many_result =
118        WaitMany(wh, sigs, MOJO_DEADLINE_INDEFINITE, nullptr);
119    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, wait_many_result.result);
120    EXPECT_TRUE(wait_many_result.IsIndexValid());
121    EXPECT_FALSE(wait_many_result.AreSignalsStatesValid());
122
123    // Make sure that our specialized template correctly handles |NULL| as well
124    // as |nullptr|.
125    wait_many_result = WaitMany(wh, sigs, MOJO_DEADLINE_INDEFINITE, NULL);
126    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, wait_many_result.result);
127    EXPECT_EQ(0u, wait_many_result.index);
128    EXPECT_TRUE(wait_many_result.IsIndexValid());
129    EXPECT_FALSE(wait_many_result.AreSignalsStatesValid());
130  }
131
132  // |MakeScopedHandle| (just compilation tests):
133  {
134    EXPECT_FALSE(MakeScopedHandle(Handle()).is_valid());
135    EXPECT_FALSE(MakeScopedHandle(MessagePipeHandle()).is_valid());
136    EXPECT_FALSE(MakeScopedHandle(DataPipeProducerHandle()).is_valid());
137    EXPECT_FALSE(MakeScopedHandle(DataPipeConsumerHandle()).is_valid());
138    EXPECT_FALSE(MakeScopedHandle(SharedBufferHandle()).is_valid());
139  }
140
141  // |MessagePipeHandle|/|ScopedMessagePipeHandle| functions:
142  {
143    MessagePipeHandle h_invalid;
144    EXPECT_FALSE(h_invalid.is_valid());
145    EXPECT_EQ(
146        MOJO_RESULT_INVALID_ARGUMENT,
147        WriteMessageRaw(
148            h_invalid, nullptr, 0, nullptr, 0, MOJO_WRITE_MESSAGE_FLAG_NONE));
149    char buffer[10] = {0};
150    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
151              WriteMessageRaw(h_invalid,
152                              buffer,
153                              sizeof(buffer),
154                              nullptr,
155                              0,
156                              MOJO_WRITE_MESSAGE_FLAG_NONE));
157    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
158              ReadMessageRaw(h_invalid,
159                             nullptr,
160                             nullptr,
161                             nullptr,
162                             nullptr,
163                             MOJO_READ_MESSAGE_FLAG_NONE));
164    uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
165    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
166              ReadMessageRaw(h_invalid,
167                             buffer,
168                             &buffer_size,
169                             nullptr,
170                             nullptr,
171                             MOJO_READ_MESSAGE_FLAG_NONE));
172
173    // Basic tests of waiting and closing.
174    MojoHandle hv0 = kInvalidHandleValue;
175    {
176      ScopedMessagePipeHandle h0;
177      ScopedMessagePipeHandle h1;
178      EXPECT_FALSE(h0.get().is_valid());
179      EXPECT_FALSE(h1.get().is_valid());
180
181      CreateMessagePipe(nullptr, &h0, &h1);
182      EXPECT_TRUE(h0.get().is_valid());
183      EXPECT_TRUE(h1.get().is_valid());
184      EXPECT_NE(h0.get().value(), h1.get().value());
185      // Save the handle values, so we can check that things got closed
186      // correctly.
187      hv0 = h0.get().value();
188      MojoHandle hv1 = h1.get().value();
189      MojoHandleSignalsState state;
190
191      EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
192                Wait(h0.get(), MOJO_HANDLE_SIGNAL_READABLE, 0, &state));
193
194      EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
195      EXPECT_EQ(kSignalAll, state.satisfiable_signals);
196
197      std::vector<Handle> wh;
198      wh.push_back(h0.get());
199      wh.push_back(h1.get());
200      std::vector<MojoHandleSignals> sigs;
201      sigs.push_back(MOJO_HANDLE_SIGNAL_READABLE);
202      sigs.push_back(MOJO_HANDLE_SIGNAL_WRITABLE);
203      std::vector<MojoHandleSignalsState> states(sigs.size());
204      WaitManyResult wait_many_result = WaitMany(wh, sigs, 1000, &states);
205      EXPECT_EQ(MOJO_RESULT_OK, wait_many_result.result);
206      EXPECT_EQ(1u, wait_many_result.index);
207      EXPECT_TRUE(wait_many_result.IsIndexValid());
208      EXPECT_TRUE(wait_many_result.AreSignalsStatesValid());
209      EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, states[0].satisfied_signals);
210      EXPECT_EQ(kSignalAll, states[0].satisfiable_signals);
211      EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, states[1].satisfied_signals);
212      EXPECT_EQ(kSignalAll, states[1].satisfiable_signals);
213
214      // Test closing |h1| explicitly.
215      Close(std::move(h1));
216      EXPECT_FALSE(h1.get().is_valid());
217
218      // Make sure |h1| is closed.
219      EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
220                Wait(Handle(hv1), ~MOJO_HANDLE_SIGNAL_NONE,
221                     MOJO_DEADLINE_INDEFINITE, nullptr));
222
223      EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
224                Wait(h0.get(), MOJO_HANDLE_SIGNAL_READABLE,
225                     MOJO_DEADLINE_INDEFINITE, &state));
226
227      EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals);
228      EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals);
229    }
230    // |hv0| should have been closed when |h0| went out of scope, so this close
231    // should fail.
232    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0));
233
234    // Actually test writing/reading messages.
235    {
236      ScopedMessagePipeHandle h0;
237      ScopedMessagePipeHandle h1;
238      CreateMessagePipe(nullptr, &h0, &h1);
239
240      const char kHello[] = "hello";
241      const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
242      EXPECT_EQ(MOJO_RESULT_OK,
243                WriteMessageRaw(h0.get(),
244                                kHello,
245                                kHelloSize,
246                                nullptr,
247                                0,
248                                MOJO_WRITE_MESSAGE_FLAG_NONE));
249
250      MojoHandleSignalsState state;
251      EXPECT_EQ(MOJO_RESULT_OK, Wait(h1.get(), MOJO_HANDLE_SIGNAL_READABLE,
252                                     MOJO_DEADLINE_INDEFINITE, &state));
253      EXPECT_EQ(kSignalReadableWritable, state.satisfied_signals);
254      EXPECT_EQ(kSignalAll, state.satisfiable_signals);
255
256      char buffer[10] = {0};
257      uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
258      EXPECT_EQ(MOJO_RESULT_OK,
259                ReadMessageRaw(h1.get(),
260                               buffer,
261                               &buffer_size,
262                               nullptr,
263                               nullptr,
264                               MOJO_READ_MESSAGE_FLAG_NONE));
265      EXPECT_EQ(kHelloSize, buffer_size);
266      EXPECT_STREQ(kHello, buffer);
267
268      // Send a handle over the previously-establish message pipe. Use the
269      // |MessagePipe| wrapper (to test it), which automatically creates a
270      // message pipe.
271      MessagePipe mp;
272
273      // Write a message to |mp.handle0|, before we send |mp.handle1|.
274      const char kWorld[] = "world!";
275      const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
276      EXPECT_EQ(MOJO_RESULT_OK,
277                WriteMessageRaw(mp.handle0.get(),
278                                kWorld,
279                                kWorldSize,
280                                nullptr,
281                                0,
282                                MOJO_WRITE_MESSAGE_FLAG_NONE));
283
284      // Send |mp.handle1| over |h1| to |h0|.
285      MojoHandle handles[5];
286      handles[0] = mp.handle1.release().value();
287      EXPECT_NE(kInvalidHandleValue, handles[0]);
288      EXPECT_FALSE(mp.handle1.get().is_valid());
289      uint32_t handles_count = 1;
290      EXPECT_EQ(MOJO_RESULT_OK,
291                WriteMessageRaw(h1.get(),
292                                kHello,
293                                kHelloSize,
294                                handles,
295                                handles_count,
296                                MOJO_WRITE_MESSAGE_FLAG_NONE));
297      // |handles[0]| should actually be invalid now.
298      EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handles[0]));
299
300      // Read "hello" and the sent handle.
301      EXPECT_EQ(MOJO_RESULT_OK, Wait(h0.get(), MOJO_HANDLE_SIGNAL_READABLE,
302                                     MOJO_DEADLINE_INDEFINITE, &state));
303      EXPECT_EQ(kSignalReadableWritable, state.satisfied_signals);
304      EXPECT_EQ(kSignalAll, state.satisfiable_signals);
305
306      memset(buffer, 0, sizeof(buffer));
307      buffer_size = static_cast<uint32_t>(sizeof(buffer));
308      for (size_t i = 0; i < arraysize(handles); i++)
309        handles[i] = kInvalidHandleValue;
310      handles_count = static_cast<uint32_t>(arraysize(handles));
311      EXPECT_EQ(MOJO_RESULT_OK,
312                ReadMessageRaw(h0.get(),
313                               buffer,
314                               &buffer_size,
315                               handles,
316                               &handles_count,
317                               MOJO_READ_MESSAGE_FLAG_NONE));
318      EXPECT_EQ(kHelloSize, buffer_size);
319      EXPECT_STREQ(kHello, buffer);
320      EXPECT_EQ(1u, handles_count);
321      EXPECT_NE(kInvalidHandleValue, handles[0]);
322
323      // Read from the sent/received handle.
324      mp.handle1.reset(MessagePipeHandle(handles[0]));
325      // Save |handles[0]| to check that it gets properly closed.
326      hv0 = handles[0];
327
328      EXPECT_EQ(MOJO_RESULT_OK,
329                Wait(mp.handle1.get(), MOJO_HANDLE_SIGNAL_READABLE,
330                     MOJO_DEADLINE_INDEFINITE, &state));
331      EXPECT_EQ(kSignalReadableWritable, state.satisfied_signals);
332      EXPECT_EQ(kSignalAll, state.satisfiable_signals);
333
334      memset(buffer, 0, sizeof(buffer));
335      buffer_size = static_cast<uint32_t>(sizeof(buffer));
336      for (size_t i = 0; i < arraysize(handles); i++)
337        handles[i] = kInvalidHandleValue;
338      handles_count = static_cast<uint32_t>(arraysize(handles));
339      EXPECT_EQ(MOJO_RESULT_OK,
340                ReadMessageRaw(mp.handle1.get(),
341                               buffer,
342                               &buffer_size,
343                               handles,
344                               &handles_count,
345                               MOJO_READ_MESSAGE_FLAG_NONE));
346      EXPECT_EQ(kWorldSize, buffer_size);
347      EXPECT_STREQ(kWorld, buffer);
348      EXPECT_EQ(0u, handles_count);
349    }
350    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0));
351  }
352
353  // TODO(vtl): Test |CloseRaw()|.
354  // TODO(vtl): Test |reset()| more thoroughly?
355}
356
357TEST(CoreCppTest, TearDownWithMessagesEnqueued) {
358  // Tear down a message pipe which still has a message enqueued, with the
359  // message also having a valid message pipe handle.
360  {
361    ScopedMessagePipeHandle h0;
362    ScopedMessagePipeHandle h1;
363    CreateMessagePipe(nullptr, &h0, &h1);
364
365    // Send a handle over the previously-establish message pipe.
366    ScopedMessagePipeHandle h2;
367    ScopedMessagePipeHandle h3;
368    if (CreateMessagePipe(nullptr, &h2, &h3) != MOJO_RESULT_OK)
369      CreateMessagePipe(nullptr, &h2, &h3);  // Must be old EDK.
370
371    // Write a message to |h2|, before we send |h3|.
372    const char kWorld[] = "world!";
373    const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
374    EXPECT_EQ(MOJO_RESULT_OK,
375              WriteMessageRaw(h2.get(),
376                              kWorld,
377                              kWorldSize,
378                              nullptr,
379                              0,
380                              MOJO_WRITE_MESSAGE_FLAG_NONE));
381    // And also a message to |h3|.
382    EXPECT_EQ(MOJO_RESULT_OK,
383              WriteMessageRaw(h3.get(),
384                              kWorld,
385                              kWorldSize,
386                              nullptr,
387                              0,
388                              MOJO_WRITE_MESSAGE_FLAG_NONE));
389
390    // Send |h3| over |h1| to |h0|.
391    const char kHello[] = "hello";
392    const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
393    MojoHandle h3_value;
394    h3_value = h3.release().value();
395    EXPECT_NE(kInvalidHandleValue, h3_value);
396    EXPECT_FALSE(h3.get().is_valid());
397    EXPECT_EQ(MOJO_RESULT_OK,
398              WriteMessageRaw(h1.get(),
399                              kHello,
400                              kHelloSize,
401                              &h3_value,
402                              1,
403                              MOJO_WRITE_MESSAGE_FLAG_NONE));
404    // |h3_value| should actually be invalid now.
405    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value));
406
407    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value()));
408    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value()));
409    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value()));
410  }
411
412  // Do this in a different order: make the enqueued message pipe handle only
413  // half-alive.
414  {
415    ScopedMessagePipeHandle h0;
416    ScopedMessagePipeHandle h1;
417    CreateMessagePipe(nullptr, &h0, &h1);
418
419    // Send a handle over the previously-establish message pipe.
420    ScopedMessagePipeHandle h2;
421    ScopedMessagePipeHandle h3;
422    if (CreateMessagePipe(nullptr, &h2, &h3) != MOJO_RESULT_OK)
423      CreateMessagePipe(nullptr, &h2, &h3);  // Must be old EDK.
424
425    // Write a message to |h2|, before we send |h3|.
426    const char kWorld[] = "world!";
427    const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
428    EXPECT_EQ(MOJO_RESULT_OK,
429              WriteMessageRaw(h2.get(),
430                              kWorld,
431                              kWorldSize,
432                              nullptr,
433                              0,
434                              MOJO_WRITE_MESSAGE_FLAG_NONE));
435    // And also a message to |h3|.
436    EXPECT_EQ(MOJO_RESULT_OK,
437              WriteMessageRaw(h3.get(),
438                              kWorld,
439                              kWorldSize,
440                              nullptr,
441                              0,
442                              MOJO_WRITE_MESSAGE_FLAG_NONE));
443
444    // Send |h3| over |h1| to |h0|.
445    const char kHello[] = "hello";
446    const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
447    MojoHandle h3_value;
448    h3_value = h3.release().value();
449    EXPECT_NE(kInvalidHandleValue, h3_value);
450    EXPECT_FALSE(h3.get().is_valid());
451    EXPECT_EQ(MOJO_RESULT_OK,
452              WriteMessageRaw(h1.get(),
453                              kHello,
454                              kHelloSize,
455                              &h3_value,
456                              1,
457                              MOJO_WRITE_MESSAGE_FLAG_NONE));
458    // |h3_value| should actually be invalid now.
459    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value));
460
461    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value()));
462    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value()));
463    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value()));
464  }
465}
466
467TEST(CoreCppTest, ScopedHandleMoveCtor) {
468  ScopedSharedBufferHandle buffer1 = SharedBufferHandle::Create(1024);
469  EXPECT_TRUE(buffer1.is_valid());
470
471  ScopedSharedBufferHandle buffer2 = SharedBufferHandle::Create(1024);
472  EXPECT_TRUE(buffer2.is_valid());
473
474  // If this fails to close buffer1, ScopedHandleBase::CloseIfNecessary() will
475  // assert.
476  buffer1 = std::move(buffer2);
477
478  EXPECT_TRUE(buffer1.is_valid());
479  EXPECT_FALSE(buffer2.is_valid());
480}
481
482TEST(CoreCppTest, BasicSharedBuffer) {
483  ScopedSharedBufferHandle h0 = SharedBufferHandle::Create(100);
484  ASSERT_TRUE(h0.is_valid());
485
486  // Map everything.
487  ScopedSharedBufferMapping mapping = h0->Map(100);
488  ASSERT_TRUE(mapping);
489  static_cast<char*>(mapping.get())[50] = 'x';
490
491  // Duplicate |h0| to |h1|.
492  ScopedSharedBufferHandle h1 =
493      h0->Clone(SharedBufferHandle::AccessMode::READ_ONLY);
494  ASSERT_TRUE(h1.is_valid());
495
496  // Close |h0|.
497  h0.reset();
498
499  // The mapping should still be good.
500  static_cast<char*>(mapping.get())[51] = 'y';
501
502  // Unmap it.
503  mapping.reset();
504
505  // Map half of |h1|.
506  mapping = h1->MapAtOffset(50, 50);
507  ASSERT_TRUE(mapping);
508
509  // It should have what we wrote.
510  EXPECT_EQ('x', static_cast<char*>(mapping.get())[0]);
511  EXPECT_EQ('y', static_cast<char*>(mapping.get())[1]);
512
513  // Unmap it.
514  mapping.reset();
515  h1.reset();
516
517  // Creating a 1 EB shared buffer should fail without crashing.
518  EXPECT_FALSE(SharedBufferHandle::Create(1ULL << 60).is_valid());
519}
520
521// TODO(vtl): Write data pipe tests.
522
523}  // namespace
524}  // namespace mojo
525