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