OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdint.h> | 5 #include <stdint.h> |
6 #include <stdio.h> | 6 #include <stdio.h> |
| 7 #include <string.h> |
7 | 8 |
8 #include <string> | 9 #include <string> |
9 #include <vector> | 10 #include <vector> |
10 | 11 |
11 #include "base/bind.h" | 12 #include "base/bind.h" |
12 #include "base/file_util.h" | 13 #include "base/file_util.h" |
13 #include "base/files/file_path.h" | 14 #include "base/files/file_path.h" |
14 #include "base/files/scoped_file.h" | 15 #include "base/files/scoped_file.h" |
15 #include "base/location.h" | 16 #include "base/location.h" |
16 #include "base/logging.h" | 17 #include "base/logging.h" |
17 #include "base/macros.h" | 18 #include "base/macros.h" |
18 #include "base/threading/platform_thread.h" // For |Sleep()|. | 19 #include "base/threading/platform_thread.h" // For |Sleep()|. |
19 #include "build/build_config.h" // TODO(vtl): Remove this. | 20 #include "build/build_config.h" // TODO(vtl): Remove this. |
20 #include "mojo/common/test/multiprocess_test_helper.h" | 21 #include "mojo/common/test/multiprocess_test_helper.h" |
21 #include "mojo/common/test/test_utils.h" | 22 #include "mojo/common/test/test_utils.h" |
22 #include "mojo/embedder/scoped_platform_handle.h" | 23 #include "mojo/embedder/scoped_platform_handle.h" |
23 #include "mojo/system/channel.h" | 24 #include "mojo/system/channel.h" |
24 #include "mojo/system/dispatcher.h" | 25 #include "mojo/system/dispatcher.h" |
25 #include "mojo/system/local_message_pipe_endpoint.h" | 26 #include "mojo/system/local_message_pipe_endpoint.h" |
26 #include "mojo/system/message_pipe.h" | 27 #include "mojo/system/message_pipe.h" |
27 #include "mojo/system/platform_handle_dispatcher.h" | 28 #include "mojo/system/platform_handle_dispatcher.h" |
28 #include "mojo/system/proxy_message_pipe_endpoint.h" | 29 #include "mojo/system/proxy_message_pipe_endpoint.h" |
29 #include "mojo/system/raw_channel.h" | 30 #include "mojo/system/raw_channel.h" |
| 31 #include "mojo/system/raw_shared_buffer.h" |
| 32 #include "mojo/system/shared_buffer_dispatcher.h" |
30 #include "mojo/system/test_utils.h" | 33 #include "mojo/system/test_utils.h" |
31 #include "mojo/system/waiter.h" | 34 #include "mojo/system/waiter.h" |
32 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
33 | 36 |
34 namespace mojo { | 37 namespace mojo { |
35 namespace system { | 38 namespace system { |
36 namespace { | 39 namespace { |
37 | 40 |
38 class ChannelThread { | 41 class ChannelThread { |
39 public: | 42 public: |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 // "quitquitquit"). | 276 // "quitquitquit"). |
274 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 277 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
275 WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); | 278 WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); |
276 | 279 |
277 mp->Close(0); | 280 mp->Close(0); |
278 | 281 |
279 EXPECT_EQ(static_cast<int>(kNumMessages % 100), | 282 EXPECT_EQ(static_cast<int>(kNumMessages % 100), |
280 helper()->WaitForChildShutdown()); | 283 helper()->WaitForChildShutdown()); |
281 } | 284 } |
282 | 285 |
| 286 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckSharedBuffer) { |
| 287 ChannelThread channel_thread; |
| 288 embedder::ScopedPlatformHandle client_platform_handle = |
| 289 mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); |
| 290 CHECK(client_platform_handle.is_valid()); |
| 291 scoped_refptr<MessagePipe> mp(new MessagePipe( |
| 292 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
| 293 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
| 294 channel_thread.Start(client_platform_handle.Pass(), mp); |
| 295 |
| 296 // Wait for the first message from our parent. |
| 297 CHECK_EQ(WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE), MOJO_RESULT_OK); |
| 298 |
| 299 // It should have a shared buffer. |
| 300 std::string read_buffer(100, '\0'); |
| 301 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |
| 302 DispatcherVector dispatchers; |
| 303 uint32_t num_dispatchers = 10; // Maximum number to receive. |
| 304 CHECK_EQ(mp->ReadMessage(0, |
| 305 &read_buffer[0], &num_bytes, |
| 306 &dispatchers, &num_dispatchers, |
| 307 MOJO_READ_MESSAGE_FLAG_NONE), |
| 308 MOJO_RESULT_OK); |
| 309 read_buffer.resize(num_bytes); |
| 310 CHECK_EQ(read_buffer, std::string("go 1")); |
| 311 CHECK_EQ(num_dispatchers, 1u); |
| 312 |
| 313 CHECK_EQ(dispatchers[0]->GetType(), Dispatcher::kTypeSharedBuffer); |
| 314 |
| 315 scoped_refptr<SharedBufferDispatcher> dispatcher( |
| 316 static_cast<SharedBufferDispatcher*>(dispatchers[0].get())); |
| 317 |
| 318 // Make a mapping. |
| 319 scoped_ptr<RawSharedBufferMapping> mapping; |
| 320 CHECK_EQ(dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping), |
| 321 MOJO_RESULT_OK); |
| 322 CHECK(mapping); |
| 323 CHECK(mapping->base()); |
| 324 CHECK_EQ(mapping->length(), 100u); |
| 325 |
| 326 // Write some stuff to the shared buffer. |
| 327 static const char kHello[] = "hello"; |
| 328 memcpy(mapping->base(), kHello, sizeof(kHello)); |
| 329 |
| 330 // We should be able to close the dispatcher now. |
| 331 dispatcher->Close(); |
| 332 |
| 333 // And send a message to signal that we've written stuff. |
| 334 const std::string go2("go 2"); |
| 335 CHECK_EQ(mp->WriteMessage(0, |
| 336 &go2[0], |
| 337 static_cast<uint32_t>(go2.size()), |
| 338 NULL, |
| 339 MOJO_WRITE_MESSAGE_FLAG_NONE), |
| 340 MOJO_RESULT_OK); |
| 341 |
| 342 // Now wait for our parent to send us a message. |
| 343 CHECK_EQ(WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE), MOJO_RESULT_OK); |
| 344 |
| 345 read_buffer = std::string(100, '\0'); |
| 346 num_bytes = static_cast<uint32_t>(read_buffer.size()); |
| 347 CHECK_EQ(mp->ReadMessage(0, |
| 348 &read_buffer[0], &num_bytes, |
| 349 NULL, NULL, |
| 350 MOJO_READ_MESSAGE_FLAG_NONE), |
| 351 MOJO_RESULT_OK); |
| 352 read_buffer.resize(num_bytes); |
| 353 CHECK_EQ(read_buffer, std::string("go 3")); |
| 354 |
| 355 // It should have written something to the shared buffer. |
| 356 static const char kWorld[] = "world!!!"; |
| 357 CHECK_EQ(memcmp(mapping->base(), kWorld, sizeof(kWorld)), 0); |
| 358 |
| 359 // And we're done. |
| 360 mp->Close(0); |
| 361 |
| 362 return 0; |
| 363 } |
| 364 |
| 365 #if defined(OS_POSIX) |
| 366 #define MAYBE_SharedBufferPassing SharedBufferPassing |
| 367 #else |
| 368 // Not yet implemented (on Windows). |
| 369 #define MAYBE_SharedBufferPassing DISABLED_SharedBufferPassing |
| 370 #endif |
| 371 TEST_F(MultiprocessMessagePipeTest, MAYBE_SharedBufferPassing) { |
| 372 helper()->StartChild("CheckSharedBuffer"); |
| 373 |
| 374 scoped_refptr<MessagePipe> mp(new MessagePipe( |
| 375 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
| 376 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
| 377 Init(mp); |
| 378 |
| 379 // Make a shared buffer. |
| 380 scoped_refptr<SharedBufferDispatcher> dispatcher; |
| 381 MojoCreateSharedBufferOptions validated_options = {}; |
| 382 EXPECT_EQ(MOJO_RESULT_OK, |
| 383 SharedBufferDispatcher::ValidateOptions(NULL, &validated_options)); |
| 384 EXPECT_EQ(MOJO_RESULT_OK, |
| 385 SharedBufferDispatcher::Create(validated_options, 100, |
| 386 &dispatcher)); |
| 387 ASSERT_TRUE(dispatcher); |
| 388 |
| 389 // Make a mapping. |
| 390 scoped_ptr<RawSharedBufferMapping> mapping; |
| 391 EXPECT_EQ(MOJO_RESULT_OK, |
| 392 dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping)); |
| 393 ASSERT_TRUE(mapping); |
| 394 ASSERT_TRUE(mapping->base()); |
| 395 ASSERT_EQ(100u, mapping->length()); |
| 396 |
| 397 // Send the shared buffer. |
| 398 const std::string go1("go 1"); |
| 399 DispatcherTransport transport( |
| 400 test::DispatcherTryStartTransport(dispatcher.get())); |
| 401 ASSERT_TRUE(transport.is_valid()); |
| 402 |
| 403 std::vector<DispatcherTransport> transports; |
| 404 transports.push_back(transport); |
| 405 EXPECT_EQ(MOJO_RESULT_OK, |
| 406 mp->WriteMessage(0, |
| 407 &go1[0], |
| 408 static_cast<uint32_t>(go1.size()), |
| 409 &transports, |
| 410 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 411 transport.End(); |
| 412 |
| 413 EXPECT_TRUE(dispatcher->HasOneRef()); |
| 414 dispatcher = NULL; |
| 415 |
| 416 // Wait for a message from the child. |
| 417 EXPECT_EQ(MOJO_RESULT_OK, WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); |
| 418 |
| 419 std::string read_buffer(100, '\0'); |
| 420 uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size()); |
| 421 EXPECT_EQ(MOJO_RESULT_OK, |
| 422 mp->ReadMessage(0, |
| 423 &read_buffer[0], &num_bytes, |
| 424 NULL, NULL, |
| 425 MOJO_READ_MESSAGE_FLAG_NONE)); |
| 426 read_buffer.resize(num_bytes); |
| 427 EXPECT_EQ(std::string("go 2"), read_buffer); |
| 428 |
| 429 // After we get it, the child should have written something to the shared |
| 430 // buffer. |
| 431 static const char kHello[] = "hello"; |
| 432 EXPECT_EQ(0, memcmp(mapping->base(), kHello, sizeof(kHello))); |
| 433 |
| 434 // Now we'll write some stuff to the shared buffer. |
| 435 static const char kWorld[] = "world!!!"; |
| 436 memcpy(mapping->base(), kWorld, sizeof(kWorld)); |
| 437 |
| 438 // And send a message to signal that we've written stuff. |
| 439 const std::string go3("go 3"); |
| 440 EXPECT_EQ(MOJO_RESULT_OK, |
| 441 mp->WriteMessage(0, |
| 442 &go3[0], |
| 443 static_cast<uint32_t>(go3.size()), |
| 444 NULL, |
| 445 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
| 446 |
| 447 // Wait for |mp| to become readable, which should fail. |
| 448 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
| 449 WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); |
| 450 |
| 451 mp->Close(0); |
| 452 |
| 453 EXPECT_EQ(0, helper()->WaitForChildShutdown()); |
| 454 } |
| 455 |
283 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { | 456 MOJO_MULTIPROCESS_TEST_CHILD_MAIN(CheckPlatformHandleFile) { |
284 ChannelThread channel_thread; | 457 ChannelThread channel_thread; |
285 embedder::ScopedPlatformHandle client_platform_handle = | 458 embedder::ScopedPlatformHandle client_platform_handle = |
286 mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); | 459 mojo::test::MultiprocessTestHelper::client_platform_handle.Pass(); |
287 CHECK(client_platform_handle.is_valid()); | 460 CHECK(client_platform_handle.is_valid()); |
288 scoped_refptr<MessagePipe> mp(new MessagePipe( | 461 scoped_refptr<MessagePipe> mp(new MessagePipe( |
289 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), | 462 scoped_ptr<MessagePipeEndpoint>(new LocalMessagePipeEndpoint()), |
290 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); | 463 scoped_ptr<MessagePipeEndpoint>(new ProxyMessagePipeEndpoint()))); |
291 channel_thread.Start(client_platform_handle.Pass(), mp); | 464 channel_thread.Start(client_platform_handle.Pass(), mp); |
292 | 465 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); | 547 WaitIfNecessary(mp, MOJO_WAIT_FLAG_READABLE)); |
375 | 548 |
376 mp->Close(0); | 549 mp->Close(0); |
377 | 550 |
378 EXPECT_EQ(0, helper()->WaitForChildShutdown()); | 551 EXPECT_EQ(0, helper()->WaitForChildShutdown()); |
379 } | 552 } |
380 | 553 |
381 } // namespace | 554 } // namespace |
382 } // namespace system | 555 } // namespace system |
383 } // namespace mojo | 556 } // namespace mojo |
OLD | NEW |