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