Home | History | Annotate | Download | only in tests
      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 API.
      6 
      7 #include "mojo/public/c/system/core.h"
      8 
      9 #include <stdint.h>
     10 #include <string.h>
     11 
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 namespace mojo {
     15 namespace {
     16 
     17 const MojoHandleSignals kSignalReadadableWritable =
     18     MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE;
     19 
     20 const MojoHandleSignals kSignalAll = MOJO_HANDLE_SIGNAL_READABLE |
     21                                      MOJO_HANDLE_SIGNAL_WRITABLE |
     22                                      MOJO_HANDLE_SIGNAL_PEER_CLOSED;
     23 
     24 TEST(CoreTest, GetTimeTicksNow) {
     25   const MojoTimeTicks start = MojoGetTimeTicksNow();
     26   EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
     27       << "MojoGetTimeTicksNow should return nonzero value";
     28 }
     29 
     30 // The only handle that's guaranteed to be invalid is |MOJO_HANDLE_INVALID|.
     31 // Tests that everything that takes a handle properly recognizes it.
     32 TEST(CoreTest, InvalidHandle) {
     33   MojoHandle h0, h1;
     34   MojoHandleSignals sig;
     35   char buffer[10] = {0};
     36   uint32_t buffer_size;
     37   void* write_pointer;
     38   const void* read_pointer;
     39 
     40   // Close:
     41   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(MOJO_HANDLE_INVALID));
     42 
     43   // Wait:
     44   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     45             MojoWait(MOJO_HANDLE_INVALID, ~MOJO_HANDLE_SIGNAL_NONE, 1000000,
     46                      nullptr));
     47 
     48   h0 = MOJO_HANDLE_INVALID;
     49   sig = ~MOJO_HANDLE_SIGNAL_NONE;
     50   EXPECT_EQ(
     51       MOJO_RESULT_INVALID_ARGUMENT,
     52       MojoWaitMany(&h0, &sig, 1, MOJO_DEADLINE_INDEFINITE, nullptr, nullptr));
     53 
     54   // Message pipe:
     55   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     56             MojoWriteMessage(h0, buffer, 3, nullptr, 0,
     57                              MOJO_WRITE_MESSAGE_FLAG_NONE));
     58   buffer_size = static_cast<uint32_t>(sizeof(buffer));
     59   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     60             MojoReadMessage(h0, buffer, &buffer_size, nullptr, nullptr,
     61                             MOJO_READ_MESSAGE_FLAG_NONE));
     62 
     63   // Data pipe:
     64   buffer_size = static_cast<uint32_t>(sizeof(buffer));
     65   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     66             MojoWriteData(h0, buffer, &buffer_size, MOJO_WRITE_DATA_FLAG_NONE));
     67   write_pointer = nullptr;
     68   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     69             MojoBeginWriteData(h0, &write_pointer, &buffer_size,
     70                                MOJO_WRITE_DATA_FLAG_NONE));
     71   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoEndWriteData(h0, 1));
     72   buffer_size = static_cast<uint32_t>(sizeof(buffer));
     73   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     74             MojoReadData(h0, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
     75   read_pointer = nullptr;
     76   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     77             MojoBeginReadData(h0, &read_pointer, &buffer_size,
     78                               MOJO_READ_DATA_FLAG_NONE));
     79   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoEndReadData(h0, 1));
     80 
     81   // Shared buffer:
     82   h1 = MOJO_HANDLE_INVALID;
     83   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     84             MojoDuplicateBufferHandle(h0, nullptr, &h1));
     85   EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
     86             MojoMapBuffer(h0, 0, 1, &write_pointer, MOJO_MAP_BUFFER_FLAG_NONE));
     87 }
     88 
     89 TEST(CoreTest, BasicMessagePipe) {
     90   MojoHandle h0, h1;
     91   MojoHandleSignals sig;
     92   char buffer[10] = {0};
     93   uint32_t buffer_size;
     94 
     95   h0 = MOJO_HANDLE_INVALID;
     96   h1 = MOJO_HANDLE_INVALID;
     97   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(nullptr, &h0, &h1));
     98   EXPECT_NE(h0, MOJO_HANDLE_INVALID);
     99   EXPECT_NE(h1, MOJO_HANDLE_INVALID);
    100 
    101   // Shouldn't be readable, we haven't written anything.
    102   MojoHandleSignalsState state;
    103   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
    104             MojoWait(h0, MOJO_HANDLE_SIGNAL_READABLE, 0, &state));
    105   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
    106   EXPECT_EQ(kSignalAll, state.satisfiable_signals);
    107 
    108   // Should be writable.
    109   EXPECT_EQ(MOJO_RESULT_OK,
    110             MojoWait(h0, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &state));
    111   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
    112   EXPECT_EQ(kSignalAll, state.satisfiable_signals);
    113 
    114   // Last parameter is optional.
    115   EXPECT_EQ(MOJO_RESULT_OK,
    116             MojoWait(h0, MOJO_HANDLE_SIGNAL_WRITABLE, 0, nullptr));
    117 
    118   // Try to read.
    119   buffer_size = static_cast<uint32_t>(sizeof(buffer));
    120   EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
    121             MojoReadMessage(h0, buffer, &buffer_size, nullptr, nullptr,
    122                             MOJO_READ_MESSAGE_FLAG_NONE));
    123 
    124   // Write to |h1|.
    125   static const char kHello[] = "hello";
    126   buffer_size = static_cast<uint32_t>(sizeof(kHello));
    127   EXPECT_EQ(MOJO_RESULT_OK, MojoWriteMessage(h1, kHello, buffer_size, nullptr,
    128                                              0, MOJO_WRITE_MESSAGE_FLAG_NONE));
    129 
    130   // |h0| should be readable.
    131   uint32_t result_index = 1;
    132   MojoHandleSignalsState states[1];
    133   sig = MOJO_HANDLE_SIGNAL_READABLE;
    134   EXPECT_EQ(MOJO_RESULT_OK, MojoWaitMany(&h0, &sig, 1, MOJO_DEADLINE_INDEFINITE,
    135                                          &result_index, states));
    136 
    137   EXPECT_EQ(0u, result_index);
    138   EXPECT_EQ(kSignalReadadableWritable, states[0].satisfied_signals);
    139   EXPECT_EQ(kSignalAll, states[0].satisfiable_signals);
    140 
    141   // Read from |h0|.
    142   buffer_size = static_cast<uint32_t>(sizeof(buffer));
    143   EXPECT_EQ(MOJO_RESULT_OK,
    144             MojoReadMessage(h0, buffer, &buffer_size, nullptr, nullptr,
    145                             MOJO_READ_MESSAGE_FLAG_NONE));
    146   EXPECT_EQ(static_cast<uint32_t>(sizeof(kHello)), buffer_size);
    147   EXPECT_STREQ(kHello, buffer);
    148 
    149   // |h0| should no longer be readable.
    150   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
    151             MojoWait(h0, MOJO_HANDLE_SIGNAL_READABLE, 10, &state));
    152 
    153   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
    154   EXPECT_EQ(kSignalAll, state.satisfiable_signals);
    155 
    156   // Close |h0|.
    157   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0));
    158 
    159   EXPECT_EQ(MOJO_RESULT_OK,
    160             MojoWait(h1, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    161                      MOJO_DEADLINE_INDEFINITE, &state));
    162 
    163   // |h1| should no longer be readable or writable.
    164   EXPECT_EQ(
    165       MOJO_RESULT_FAILED_PRECONDITION,
    166       MojoWait(h1, MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
    167                1000, &state));
    168 
    169   EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals);
    170   EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals);
    171 
    172   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
    173 }
    174 
    175 TEST(CoreTest, BasicDataPipe) {
    176   MojoHandle hp, hc;
    177   MojoHandleSignals sig;
    178   char buffer[20] = {0};
    179   uint32_t buffer_size;
    180   void* write_pointer;
    181   const void* read_pointer;
    182 
    183   hp = MOJO_HANDLE_INVALID;
    184   hc = MOJO_HANDLE_INVALID;
    185   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(nullptr, &hp, &hc));
    186   EXPECT_NE(hp, MOJO_HANDLE_INVALID);
    187   EXPECT_NE(hc, MOJO_HANDLE_INVALID);
    188 
    189   // The consumer |hc| shouldn't be readable.
    190   MojoHandleSignalsState state;
    191   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
    192             MojoWait(hc, MOJO_HANDLE_SIGNAL_READABLE, 0, &state));
    193 
    194   EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, state.satisfied_signals);
    195   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
    196                 MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE,
    197             state.satisfiable_signals);
    198 
    199   // The producer |hp| should be writable.
    200   EXPECT_EQ(MOJO_RESULT_OK,
    201             MojoWait(hp, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &state));
    202 
    203   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
    204   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    205             state.satisfiable_signals);
    206 
    207   // Try to read from |hc|.
    208   buffer_size = static_cast<uint32_t>(sizeof(buffer));
    209   EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
    210             MojoReadData(hc, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
    211 
    212   // Try to begin a two-phase read from |hc|.
    213   read_pointer = nullptr;
    214   EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
    215             MojoBeginReadData(hc, &read_pointer, &buffer_size,
    216                               MOJO_READ_DATA_FLAG_NONE));
    217 
    218   // Write to |hp|.
    219   static const char kHello[] = "hello ";
    220   // Don't include terminating null.
    221   buffer_size = static_cast<uint32_t>(strlen(kHello));
    222   EXPECT_EQ(MOJO_RESULT_OK, MojoWriteData(hp, kHello, &buffer_size,
    223                                           MOJO_WRITE_MESSAGE_FLAG_NONE));
    224 
    225   // |hc| should be(come) readable.
    226   uint32_t result_index = 1;
    227   MojoHandleSignalsState states[1];
    228   sig = MOJO_HANDLE_SIGNAL_READABLE;
    229   EXPECT_EQ(MOJO_RESULT_OK, MojoWaitMany(&hc, &sig, 1, MOJO_DEADLINE_INDEFINITE,
    230                                          &result_index, states));
    231 
    232   EXPECT_EQ(0u, result_index);
    233   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE,
    234             states[0].satisfied_signals);
    235   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED |
    236                 MOJO_HANDLE_SIGNAL_NEW_DATA_READABLE,
    237             states[0].satisfiable_signals);
    238 
    239   // Do a two-phase write to |hp|.
    240   EXPECT_EQ(MOJO_RESULT_OK, MojoBeginWriteData(hp, &write_pointer, &buffer_size,
    241                                                MOJO_WRITE_DATA_FLAG_NONE));
    242   static const char kWorld[] = "world";
    243   ASSERT_GE(buffer_size, sizeof(kWorld));
    244   // Include the terminating null.
    245   memcpy(write_pointer, kWorld, sizeof(kWorld));
    246   EXPECT_EQ(MOJO_RESULT_OK,
    247             MojoEndWriteData(hp, static_cast<uint32_t>(sizeof(kWorld))));
    248 
    249   // Read one character from |hc|.
    250   memset(buffer, 0, sizeof(buffer));
    251   buffer_size = 1;
    252   EXPECT_EQ(MOJO_RESULT_OK,
    253             MojoReadData(hc, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
    254 
    255   // Close |hp|.
    256   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hp));
    257 
    258   // |hc| should still be readable.
    259   EXPECT_EQ(MOJO_RESULT_OK,
    260             MojoWait(hc, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    261                      MOJO_DEADLINE_INDEFINITE, &state));
    262 
    263   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    264             state.satisfied_signals);
    265   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    266             state.satisfiable_signals);
    267 
    268   // Do a two-phase read from |hc|.
    269   read_pointer = nullptr;
    270   EXPECT_EQ(MOJO_RESULT_OK, MojoBeginReadData(hc, &read_pointer, &buffer_size,
    271                                               MOJO_READ_DATA_FLAG_NONE));
    272   ASSERT_LE(buffer_size, sizeof(buffer) - 1);
    273   memcpy(&buffer[1], read_pointer, buffer_size);
    274   EXPECT_EQ(MOJO_RESULT_OK, MojoEndReadData(hc, buffer_size));
    275   EXPECT_STREQ("hello world", buffer);
    276 
    277   // |hc| should no longer be readable.
    278   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
    279             MojoWait(hc, MOJO_HANDLE_SIGNAL_READABLE, 1000, &state));
    280 
    281   EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals);
    282   EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals);
    283 
    284   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hc));
    285 
    286   // TODO(vtl): Test the other way around -- closing the consumer should make
    287   // the producer never-writable?
    288 }
    289 
    290 TEST(CoreTest, BasicSharedBuffer) {
    291   MojoHandle h0, h1;
    292   void* pointer;
    293 
    294   // Create a shared buffer (|h0|).
    295   h0 = MOJO_HANDLE_INVALID;
    296   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(nullptr, 100, &h0));
    297   EXPECT_NE(h0, MOJO_HANDLE_INVALID);
    298 
    299   // Map everything.
    300   pointer = nullptr;
    301   EXPECT_EQ(MOJO_RESULT_OK,
    302             MojoMapBuffer(h0, 0, 100, &pointer, MOJO_MAP_BUFFER_FLAG_NONE));
    303   ASSERT_TRUE(pointer);
    304   static_cast<char*>(pointer)[50] = 'x';
    305 
    306   // Duplicate |h0| to |h1|.
    307   h1 = MOJO_HANDLE_INVALID;
    308   EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(h0, nullptr, &h1));
    309   EXPECT_NE(h1, MOJO_HANDLE_INVALID);
    310 
    311   // Close |h0|.
    312   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0));
    313 
    314   // The mapping should still be good.
    315   static_cast<char*>(pointer)[51] = 'y';
    316 
    317   // Unmap it.
    318   EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer));
    319 
    320   // Map half of |h1|.
    321   pointer = nullptr;
    322   EXPECT_EQ(MOJO_RESULT_OK,
    323             MojoMapBuffer(h1, 50, 50, &pointer, MOJO_MAP_BUFFER_FLAG_NONE));
    324   ASSERT_TRUE(pointer);
    325 
    326   // It should have what we wrote.
    327   EXPECT_EQ('x', static_cast<char*>(pointer)[0]);
    328   EXPECT_EQ('y', static_cast<char*>(pointer)[1]);
    329 
    330   // Unmap it.
    331   EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer));
    332 
    333   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
    334 }
    335 
    336 // Defined in core_unittest_pure_c.c.
    337 extern "C" const char* MinimalCTest(void);
    338 
    339 // This checks that things actually work in C (not C++).
    340 TEST(CoreTest, MinimalCTest) {
    341   const char* failure = MinimalCTest();
    342   EXPECT_FALSE(failure) << failure;
    343 }
    344 
    345 // TODO(vtl): Add multi-threaded tests.
    346 
    347 }  // namespace
    348 }  // namespace mojo
    349