| OLD | NEW |
| (Empty) |
| 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++ 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 <map> | |
| 12 | |
| 13 #include "mojo/public/cpp/system/macros.h" | |
| 14 #include "testing/gtest/include/gtest/gtest.h" | |
| 15 | |
| 16 namespace mojo { | |
| 17 namespace { | |
| 18 | |
| 19 TEST(CoreCppTest, GetTimeTicksNow) { | |
| 20 const MojoTimeTicks start = GetTimeTicksNow(); | |
| 21 EXPECT_NE(static_cast<MojoTimeTicks>(0), start) | |
| 22 << "GetTimeTicksNow should return nonzero value"; | |
| 23 } | |
| 24 | |
| 25 TEST(CoreCppTest, Basic) { | |
| 26 // Basic |Handle| implementation: | |
| 27 { | |
| 28 EXPECT_EQ(MOJO_HANDLE_INVALID, kInvalidHandleValue); | |
| 29 | |
| 30 Handle h0; | |
| 31 EXPECT_EQ(kInvalidHandleValue, h0.value()); | |
| 32 EXPECT_EQ(kInvalidHandleValue, *h0.mutable_value()); | |
| 33 EXPECT_FALSE(h0.is_valid()); | |
| 34 | |
| 35 Handle h1(static_cast<MojoHandle>(123)); | |
| 36 EXPECT_EQ(static_cast<MojoHandle>(123), h1.value()); | |
| 37 EXPECT_EQ(static_cast<MojoHandle>(123), *h1.mutable_value()); | |
| 38 EXPECT_TRUE(h1.is_valid()); | |
| 39 *h1.mutable_value() = static_cast<MojoHandle>(456); | |
| 40 EXPECT_EQ(static_cast<MojoHandle>(456), h1.value()); | |
| 41 EXPECT_TRUE(h1.is_valid()); | |
| 42 | |
| 43 h1.swap(h0); | |
| 44 EXPECT_EQ(static_cast<MojoHandle>(456), h0.value()); | |
| 45 EXPECT_TRUE(h0.is_valid()); | |
| 46 EXPECT_FALSE(h1.is_valid()); | |
| 47 | |
| 48 h1.set_value(static_cast<MojoHandle>(789)); | |
| 49 h0.swap(h1); | |
| 50 EXPECT_EQ(static_cast<MojoHandle>(789), h0.value()); | |
| 51 EXPECT_TRUE(h0.is_valid()); | |
| 52 EXPECT_EQ(static_cast<MojoHandle>(456), h1.value()); | |
| 53 EXPECT_TRUE(h1.is_valid()); | |
| 54 | |
| 55 // Make sure copy constructor works. | |
| 56 Handle h2(h0); | |
| 57 EXPECT_EQ(static_cast<MojoHandle>(789), h2.value()); | |
| 58 // And assignment. | |
| 59 h2 = h1; | |
| 60 EXPECT_EQ(static_cast<MojoHandle>(456), h2.value()); | |
| 61 | |
| 62 // Make sure that we can put |Handle|s into |std::map|s. | |
| 63 h0 = Handle(static_cast<MojoHandle>(987)); | |
| 64 h1 = Handle(static_cast<MojoHandle>(654)); | |
| 65 h2 = Handle(static_cast<MojoHandle>(321)); | |
| 66 Handle h3; | |
| 67 std::map<Handle, int> handle_to_int; | |
| 68 handle_to_int[h0] = 0; | |
| 69 handle_to_int[h1] = 1; | |
| 70 handle_to_int[h2] = 2; | |
| 71 handle_to_int[h3] = 3; | |
| 72 | |
| 73 EXPECT_EQ(4u, handle_to_int.size()); | |
| 74 EXPECT_FALSE(handle_to_int.find(h0) == handle_to_int.end()); | |
| 75 EXPECT_EQ(0, handle_to_int[h0]); | |
| 76 EXPECT_FALSE(handle_to_int.find(h1) == handle_to_int.end()); | |
| 77 EXPECT_EQ(1, handle_to_int[h1]); | |
| 78 EXPECT_FALSE(handle_to_int.find(h2) == handle_to_int.end()); | |
| 79 EXPECT_EQ(2, handle_to_int[h2]); | |
| 80 EXPECT_FALSE(handle_to_int.find(h3) == handle_to_int.end()); | |
| 81 EXPECT_EQ(3, handle_to_int[h3]); | |
| 82 EXPECT_TRUE(handle_to_int.find(Handle(static_cast<MojoHandle>(13579))) == | |
| 83 handle_to_int.end()); | |
| 84 | |
| 85 // TODO(vtl): With C++11, support |std::unordered_map|s, etc. (Or figure out | |
| 86 // how to support the variations of |hash_map|.) | |
| 87 } | |
| 88 | |
| 89 // |Handle|/|ScopedHandle| functions: | |
| 90 { | |
| 91 ScopedHandle h; | |
| 92 | |
| 93 EXPECT_EQ(kInvalidHandleValue, h.get().value()); | |
| 94 | |
| 95 // This should be a no-op. | |
| 96 Close(h.Pass()); | |
| 97 | |
| 98 // It should still be invalid. | |
| 99 EXPECT_EQ(kInvalidHandleValue, h.get().value()); | |
| 100 | |
| 101 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
| 102 Wait(h.get(), MOJO_WAIT_FLAG_EVERYTHING, 1000000)); | |
| 103 | |
| 104 std::vector<Handle> wh; | |
| 105 wh.push_back(h.get()); | |
| 106 std::vector<MojoWaitFlags> wf; | |
| 107 wf.push_back(MOJO_WAIT_FLAG_EVERYTHING); | |
| 108 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
| 109 WaitMany(wh, wf, MOJO_DEADLINE_INDEFINITE)); | |
| 110 } | |
| 111 | |
| 112 // |MakeScopedHandle| (just compilation tests): | |
| 113 { | |
| 114 EXPECT_FALSE(MakeScopedHandle(Handle()).is_valid()); | |
| 115 EXPECT_FALSE(MakeScopedHandle(MessagePipeHandle()).is_valid()); | |
| 116 EXPECT_FALSE(MakeScopedHandle(DataPipeProducerHandle()).is_valid()); | |
| 117 EXPECT_FALSE(MakeScopedHandle(DataPipeConsumerHandle()).is_valid()); | |
| 118 EXPECT_FALSE(MakeScopedHandle(SharedBufferHandle()).is_valid()); | |
| 119 } | |
| 120 | |
| 121 // |MessagePipeHandle|/|ScopedMessagePipeHandle| functions: | |
| 122 { | |
| 123 MessagePipeHandle h_invalid; | |
| 124 EXPECT_FALSE(h_invalid.is_valid()); | |
| 125 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
| 126 WriteMessageRaw(h_invalid, | |
| 127 NULL, 0, | |
| 128 NULL, 0, | |
| 129 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 130 char buffer[10] = { 0 }; | |
| 131 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
| 132 WriteMessageRaw(h_invalid, | |
| 133 buffer, sizeof(buffer), | |
| 134 NULL, 0, | |
| 135 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 136 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
| 137 ReadMessageRaw(h_invalid, | |
| 138 NULL, NULL, | |
| 139 NULL, NULL, | |
| 140 MOJO_READ_MESSAGE_FLAG_NONE)); | |
| 141 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
| 142 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
| 143 ReadMessageRaw(h_invalid, | |
| 144 buffer, &buffer_size, | |
| 145 NULL, NULL, | |
| 146 MOJO_READ_MESSAGE_FLAG_NONE)); | |
| 147 | |
| 148 // Basic tests of waiting and closing. | |
| 149 MojoHandle hv0 = kInvalidHandleValue; | |
| 150 { | |
| 151 ScopedMessagePipeHandle h0; | |
| 152 ScopedMessagePipeHandle h1; | |
| 153 EXPECT_FALSE(h0.get().is_valid()); | |
| 154 EXPECT_FALSE(h1.get().is_valid()); | |
| 155 | |
| 156 CreateMessagePipe(&h0, &h1); | |
| 157 EXPECT_TRUE(h0.get().is_valid()); | |
| 158 EXPECT_TRUE(h1.get().is_valid()); | |
| 159 EXPECT_NE(h0.get().value(), h1.get().value()); | |
| 160 // Save the handle values, so we can check that things got closed | |
| 161 // correctly. | |
| 162 hv0 = h0.get().value(); | |
| 163 MojoHandle hv1 = h1.get().value(); | |
| 164 | |
| 165 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, | |
| 166 Wait(h0.get(), MOJO_WAIT_FLAG_READABLE, 0)); | |
| 167 std::vector<Handle> wh; | |
| 168 wh.push_back(h0.get()); | |
| 169 wh.push_back(h1.get()); | |
| 170 std::vector<MojoWaitFlags> wf; | |
| 171 wf.push_back(MOJO_WAIT_FLAG_READABLE); | |
| 172 wf.push_back(MOJO_WAIT_FLAG_WRITABLE); | |
| 173 EXPECT_EQ(1, WaitMany(wh, wf, 1000)); | |
| 174 | |
| 175 // Test closing |h1| explicitly. | |
| 176 Close(h1.Pass()); | |
| 177 EXPECT_FALSE(h1.get().is_valid()); | |
| 178 | |
| 179 // Make sure |h1| is closed. | |
| 180 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, | |
| 181 MojoWait(hv1, MOJO_WAIT_FLAG_EVERYTHING, | |
| 182 MOJO_DEADLINE_INDEFINITE)); | |
| 183 | |
| 184 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | |
| 185 Wait(h0.get(), MOJO_WAIT_FLAG_READABLE, | |
| 186 MOJO_DEADLINE_INDEFINITE)); | |
| 187 } | |
| 188 // |hv0| should have been closed when |h0| went out of scope, so this close | |
| 189 // should fail. | |
| 190 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0)); | |
| 191 | |
| 192 // Actually test writing/reading messages. | |
| 193 { | |
| 194 ScopedMessagePipeHandle h0; | |
| 195 ScopedMessagePipeHandle h1; | |
| 196 CreateMessagePipe(&h0, &h1); | |
| 197 | |
| 198 const char kHello[] = "hello"; | |
| 199 const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); | |
| 200 EXPECT_EQ(MOJO_RESULT_OK, | |
| 201 WriteMessageRaw(h0.get(), | |
| 202 kHello, kHelloSize, | |
| 203 NULL, 0, | |
| 204 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 205 EXPECT_EQ(MOJO_RESULT_OK, | |
| 206 Wait(h1.get(), MOJO_WAIT_FLAG_READABLE, | |
| 207 MOJO_DEADLINE_INDEFINITE)); | |
| 208 char buffer[10] = { 0 }; | |
| 209 uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
| 210 EXPECT_EQ(MOJO_RESULT_OK, | |
| 211 ReadMessageRaw(h1.get(), | |
| 212 buffer, &buffer_size, | |
| 213 NULL, NULL, | |
| 214 MOJO_READ_MESSAGE_FLAG_NONE)); | |
| 215 EXPECT_EQ(kHelloSize, buffer_size); | |
| 216 EXPECT_STREQ(kHello, buffer); | |
| 217 | |
| 218 // Send a handle over the previously-establish message pipe. Use the | |
| 219 // |MessagePipe| wrapper (to test it), which automatically creates a | |
| 220 // message pipe. | |
| 221 MessagePipe mp; | |
| 222 | |
| 223 // Write a message to |mp.handle0|, before we send |mp.handle1|. | |
| 224 const char kWorld[] = "world!"; | |
| 225 const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); | |
| 226 EXPECT_EQ(MOJO_RESULT_OK, | |
| 227 WriteMessageRaw(mp.handle0.get(), | |
| 228 kWorld, kWorldSize, | |
| 229 NULL, 0, | |
| 230 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 231 | |
| 232 // Send |mp.handle1| over |h1| to |h0|. | |
| 233 MojoHandle handles[5]; | |
| 234 handles[0] = mp.handle1.release().value(); | |
| 235 EXPECT_NE(kInvalidHandleValue, handles[0]); | |
| 236 EXPECT_FALSE(mp.handle1.get().is_valid()); | |
| 237 uint32_t handles_count = 1; | |
| 238 EXPECT_EQ(MOJO_RESULT_OK, | |
| 239 WriteMessageRaw(h1.get(), | |
| 240 kHello, kHelloSize, | |
| 241 handles, handles_count, | |
| 242 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 243 // |handles[0]| should actually be invalid now. | |
| 244 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handles[0])); | |
| 245 | |
| 246 // Read "hello" and the sent handle. | |
| 247 EXPECT_EQ(MOJO_RESULT_OK, | |
| 248 Wait(h0.get(), MOJO_WAIT_FLAG_READABLE, | |
| 249 MOJO_DEADLINE_INDEFINITE)); | |
| 250 memset(buffer, 0, sizeof(buffer)); | |
| 251 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
| 252 for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++) | |
| 253 handles[i] = kInvalidHandleValue; | |
| 254 handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles)); | |
| 255 EXPECT_EQ(MOJO_RESULT_OK, | |
| 256 ReadMessageRaw(h0.get(), | |
| 257 buffer, &buffer_size, | |
| 258 handles, &handles_count, | |
| 259 MOJO_READ_MESSAGE_FLAG_NONE)); | |
| 260 EXPECT_EQ(kHelloSize, buffer_size); | |
| 261 EXPECT_STREQ(kHello, buffer); | |
| 262 EXPECT_EQ(1u, handles_count); | |
| 263 EXPECT_NE(kInvalidHandleValue, handles[0]); | |
| 264 | |
| 265 // Read from the sent/received handle. | |
| 266 mp.handle1.reset(MessagePipeHandle(handles[0])); | |
| 267 // Save |handles[0]| to check that it gets properly closed. | |
| 268 hv0 = handles[0]; | |
| 269 EXPECT_EQ(MOJO_RESULT_OK, | |
| 270 Wait(mp.handle1.get(), MOJO_WAIT_FLAG_READABLE, | |
| 271 MOJO_DEADLINE_INDEFINITE)); | |
| 272 memset(buffer, 0, sizeof(buffer)); | |
| 273 buffer_size = static_cast<uint32_t>(sizeof(buffer)); | |
| 274 for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++) | |
| 275 handles[i] = kInvalidHandleValue; | |
| 276 handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles)); | |
| 277 EXPECT_EQ(MOJO_RESULT_OK, | |
| 278 ReadMessageRaw(mp.handle1.get(), | |
| 279 buffer, &buffer_size, | |
| 280 handles, &handles_count, | |
| 281 MOJO_READ_MESSAGE_FLAG_NONE)); | |
| 282 EXPECT_EQ(kWorldSize, buffer_size); | |
| 283 EXPECT_STREQ(kWorld, buffer); | |
| 284 EXPECT_EQ(0u, handles_count); | |
| 285 } | |
| 286 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0)); | |
| 287 } | |
| 288 | |
| 289 // TODO(vtl): Test |CloseRaw()|. | |
| 290 // TODO(vtl): Test |reset()| more thoroughly? | |
| 291 } | |
| 292 | |
| 293 TEST(CoreCppTest, TearDownWithMessagesEnqueued) { | |
| 294 // Tear down a message pipe which still has a message enqueued, with the | |
| 295 // message also having a valid message pipe handle. | |
| 296 { | |
| 297 ScopedMessagePipeHandle h0; | |
| 298 ScopedMessagePipeHandle h1; | |
| 299 CreateMessagePipe(&h0, &h1); | |
| 300 | |
| 301 // Send a handle over the previously-establish message pipe. | |
| 302 ScopedMessagePipeHandle h2; | |
| 303 ScopedMessagePipeHandle h3; | |
| 304 CreateMessagePipe(&h2, &h3); | |
| 305 | |
| 306 // Write a message to |h2|, before we send |h3|. | |
| 307 const char kWorld[] = "world!"; | |
| 308 const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); | |
| 309 EXPECT_EQ(MOJO_RESULT_OK, | |
| 310 WriteMessageRaw(h2.get(), | |
| 311 kWorld, kWorldSize, | |
| 312 NULL, 0, | |
| 313 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 314 // And also a message to |h3|. | |
| 315 EXPECT_EQ(MOJO_RESULT_OK, | |
| 316 WriteMessageRaw(h3.get(), | |
| 317 kWorld, kWorldSize, | |
| 318 NULL, 0, | |
| 319 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 320 | |
| 321 // Send |h3| over |h1| to |h0|. | |
| 322 const char kHello[] = "hello"; | |
| 323 const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); | |
| 324 MojoHandle h3_value; | |
| 325 h3_value = h3.release().value(); | |
| 326 EXPECT_NE(kInvalidHandleValue, h3_value); | |
| 327 EXPECT_FALSE(h3.get().is_valid()); | |
| 328 EXPECT_EQ(MOJO_RESULT_OK, | |
| 329 WriteMessageRaw(h1.get(), | |
| 330 kHello, kHelloSize, | |
| 331 &h3_value, 1, | |
| 332 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 333 // |h3_value| should actually be invalid now. | |
| 334 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value)); | |
| 335 | |
| 336 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value())); | |
| 337 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value())); | |
| 338 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value())); | |
| 339 } | |
| 340 | |
| 341 // Do this in a different order: make the enqueued message pipe handle only | |
| 342 // half-alive. | |
| 343 { | |
| 344 ScopedMessagePipeHandle h0; | |
| 345 ScopedMessagePipeHandle h1; | |
| 346 CreateMessagePipe(&h0, &h1); | |
| 347 | |
| 348 // Send a handle over the previously-establish message pipe. | |
| 349 ScopedMessagePipeHandle h2; | |
| 350 ScopedMessagePipeHandle h3; | |
| 351 CreateMessagePipe(&h2, &h3); | |
| 352 | |
| 353 // Write a message to |h2|, before we send |h3|. | |
| 354 const char kWorld[] = "world!"; | |
| 355 const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld)); | |
| 356 EXPECT_EQ(MOJO_RESULT_OK, | |
| 357 WriteMessageRaw(h2.get(), | |
| 358 kWorld, kWorldSize, | |
| 359 NULL, 0, | |
| 360 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 361 // And also a message to |h3|. | |
| 362 EXPECT_EQ(MOJO_RESULT_OK, | |
| 363 WriteMessageRaw(h3.get(), | |
| 364 kWorld, kWorldSize, | |
| 365 NULL, 0, | |
| 366 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 367 | |
| 368 // Send |h3| over |h1| to |h0|. | |
| 369 const char kHello[] = "hello"; | |
| 370 const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello)); | |
| 371 MojoHandle h3_value; | |
| 372 h3_value = h3.release().value(); | |
| 373 EXPECT_NE(kInvalidHandleValue, h3_value); | |
| 374 EXPECT_FALSE(h3.get().is_valid()); | |
| 375 EXPECT_EQ(MOJO_RESULT_OK, | |
| 376 WriteMessageRaw(h1.get(), | |
| 377 kHello, kHelloSize, | |
| 378 &h3_value, 1, | |
| 379 MOJO_WRITE_MESSAGE_FLAG_NONE)); | |
| 380 // |h3_value| should actually be invalid now. | |
| 381 EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value)); | |
| 382 | |
| 383 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value())); | |
| 384 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value())); | |
| 385 EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value())); | |
| 386 } | |
| 387 } | |
| 388 | |
| 389 // TODO(vtl): Write data pipe tests. | |
| 390 | |
| 391 } // namespace | |
| 392 } // namespace mojo | |
| OLD | NEW |