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             state.satisfiable_signals);
    197 
    198   // The producer |hp| should be writable.
    199   EXPECT_EQ(MOJO_RESULT_OK,
    200             MojoWait(hp, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &state));
    201 
    202   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, state.satisfied_signals);
    203   EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    204             state.satisfiable_signals);
    205 
    206   // Try to read from |hc|.
    207   buffer_size = static_cast<uint32_t>(sizeof(buffer));
    208   EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
    209             MojoReadData(hc, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
    210 
    211   // Try to begin a two-phase read from |hc|.
    212   read_pointer = nullptr;
    213   EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
    214             MojoBeginReadData(hc, &read_pointer, &buffer_size,
    215                               MOJO_READ_DATA_FLAG_NONE));
    216 
    217   // Write to |hp|.
    218   static const char kHello[] = "hello ";
    219   // Don't include terminating null.
    220   buffer_size = static_cast<uint32_t>(strlen(kHello));
    221   EXPECT_EQ(MOJO_RESULT_OK, MojoWriteData(hp, kHello, &buffer_size,
    222                                           MOJO_WRITE_MESSAGE_FLAG_NONE));
    223 
    224   // |hc| should be(come) readable.
    225   uint32_t result_index = 1;
    226   MojoHandleSignalsState states[1];
    227   sig = MOJO_HANDLE_SIGNAL_READABLE;
    228   EXPECT_EQ(MOJO_RESULT_OK, MojoWaitMany(&hc, &sig, 1, MOJO_DEADLINE_INDEFINITE,
    229                                          &result_index, states));
    230 
    231   EXPECT_EQ(0u, result_index);
    232   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, states[0].satisfied_signals);
    233   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    234             states[0].satisfiable_signals);
    235 
    236   // Do a two-phase write to |hp|.
    237   EXPECT_EQ(MOJO_RESULT_OK, MojoBeginWriteData(hp, &write_pointer, &buffer_size,
    238                                                MOJO_WRITE_DATA_FLAG_NONE));
    239   static const char kWorld[] = "world";
    240   ASSERT_GE(buffer_size, sizeof(kWorld));
    241   // Include the terminating null.
    242   memcpy(write_pointer, kWorld, sizeof(kWorld));
    243   EXPECT_EQ(MOJO_RESULT_OK,
    244             MojoEndWriteData(hp, static_cast<uint32_t>(sizeof(kWorld))));
    245 
    246   // Read one character from |hc|.
    247   memset(buffer, 0, sizeof(buffer));
    248   buffer_size = 1;
    249   EXPECT_EQ(MOJO_RESULT_OK,
    250             MojoReadData(hc, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
    251 
    252   // Close |hp|.
    253   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hp));
    254 
    255   // |hc| should still be readable.
    256   EXPECT_EQ(MOJO_RESULT_OK,
    257             MojoWait(hc, MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    258                      MOJO_DEADLINE_INDEFINITE, &state));
    259 
    260   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    261             state.satisfied_signals);
    262   EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
    263             state.satisfiable_signals);
    264 
    265   // Do a two-phase read from |hc|.
    266   read_pointer = nullptr;
    267   EXPECT_EQ(MOJO_RESULT_OK, MojoBeginReadData(hc, &read_pointer, &buffer_size,
    268                                               MOJO_READ_DATA_FLAG_NONE));
    269   ASSERT_LE(buffer_size, sizeof(buffer) - 1);
    270   memcpy(&buffer[1], read_pointer, buffer_size);
    271   EXPECT_EQ(MOJO_RESULT_OK, MojoEndReadData(hc, buffer_size));
    272   EXPECT_STREQ("hello world", buffer);
    273 
    274   // |hc| should no longer be readable.
    275   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
    276             MojoWait(hc, MOJO_HANDLE_SIGNAL_READABLE, 1000, &state));
    277 
    278   EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfied_signals);
    279   EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, state.satisfiable_signals);
    280 
    281   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hc));
    282 
    283   // TODO(vtl): Test the other way around -- closing the consumer should make
    284   // the producer never-writable?
    285 }
    286 
    287 TEST(CoreTest, BasicSharedBuffer) {
    288   MojoHandle h0, h1;
    289   void* pointer;
    290 
    291   // Create a shared buffer (|h0|).
    292   h0 = MOJO_HANDLE_INVALID;
    293   EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(nullptr, 100, &h0));
    294   EXPECT_NE(h0, MOJO_HANDLE_INVALID);
    295 
    296   // Map everything.
    297   pointer = nullptr;
    298   EXPECT_EQ(MOJO_RESULT_OK,
    299             MojoMapBuffer(h0, 0, 100, &pointer, MOJO_MAP_BUFFER_FLAG_NONE));
    300   ASSERT_TRUE(pointer);
    301   static_cast<char*>(pointer)[50] = 'x';
    302 
    303   // Duplicate |h0| to |h1|.
    304   h1 = MOJO_HANDLE_INVALID;
    305   EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(h0, nullptr, &h1));
    306   EXPECT_NE(h1, MOJO_HANDLE_INVALID);
    307 
    308   // Close |h0|.
    309   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0));
    310 
    311   // The mapping should still be good.
    312   static_cast<char*>(pointer)[51] = 'y';
    313 
    314   // Unmap it.
    315   EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer));
    316 
    317   // Map half of |h1|.
    318   pointer = nullptr;
    319   EXPECT_EQ(MOJO_RESULT_OK,
    320             MojoMapBuffer(h1, 50, 50, &pointer, MOJO_MAP_BUFFER_FLAG_NONE));
    321   ASSERT_TRUE(pointer);
    322 
    323   // It should have what we wrote.
    324   EXPECT_EQ('x', static_cast<char*>(pointer)[0]);
    325   EXPECT_EQ('y', static_cast<char*>(pointer)[1]);
    326 
    327   // Unmap it.
    328   EXPECT_EQ(MOJO_RESULT_OK, MojoUnmapBuffer(pointer));
    329 
    330   EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
    331 }
    332 
    333 // Defined in core_unittest_pure_c.c.
    334 extern "C" const char* MinimalCTest(void);
    335 
    336 // This checks that things actually work in C (not C++).
    337 TEST(CoreTest, MinimalCTest) {
    338   const char* failure = MinimalCTest();
    339   EXPECT_FALSE(failure) << failure;
    340 }
    341 
    342 // TODO(vtl): Add multi-threaded tests.
    343 
    344 }  // namespace
    345 }  // namespace mojo
    346