| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/atomicops.h" |
| 5 #include "base/basictypes.h" | 6 #include "base/basictypes.h" |
| 6 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
| 7 #include "base/memory/shared_memory.h" | 8 #include "base/memory/shared_memory.h" |
| 8 #include "base/process/kill.h" | 9 #include "base/process/kill.h" |
| 9 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
| 10 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/sys_info.h" | 12 #include "base/sys_info.h" |
| 12 #include "base/test/multiprocess_test.h" | 13 #include "base/test/multiprocess_test.h" |
| 13 #include "base/threading/platform_thread.h" | 14 #include "base/threading/platform_thread.h" |
| 14 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 26 #include <sys/stat.h> | 27 #include <sys/stat.h> |
| 27 #include <sys/types.h> | 28 #include <sys/types.h> |
| 28 #include <unistd.h> | 29 #include <unistd.h> |
| 29 #endif | 30 #endif |
| 30 | 31 |
| 31 #if defined(OS_WIN) | 32 #if defined(OS_WIN) |
| 32 #include "base/win/scoped_handle.h" | 33 #include "base/win/scoped_handle.h" |
| 33 #endif | 34 #endif |
| 34 | 35 |
| 35 static const int kNumThreads = 5; | 36 static const int kNumThreads = 5; |
| 36 #if !defined(OS_IOS) // iOS does not allow multiple processes. | 37 #if !defined(OS_IOS) && !defined(OS_ANDROID) |
| 37 static const int kNumTasks = 5; | 38 static const int kNumTasks = 5; |
| 38 #endif | 39 #endif |
| 39 | 40 |
| 40 namespace base { | 41 namespace base { |
| 41 | 42 |
| 42 namespace { | 43 namespace { |
| 43 | 44 |
| 44 // Each thread will open the shared memory. Each thread will take a different 4 | 45 // Each thread will open the shared memory. Each thread will take a different 4 |
| 45 // byte int pointer, and keep changing it, with some small pauses in between. | 46 // byte int pointer, and keep changing it, with some small pauses in between. |
| 46 // Verify that each thread's value in the shared memory is always correct. | 47 // Verify that each thread's value in the shared memory is always correct. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 int16 id_; | 84 int16 id_; |
| 84 | 85 |
| 85 static const char* const s_test_name_; | 86 static const char* const s_test_name_; |
| 86 | 87 |
| 87 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); | 88 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); |
| 88 }; | 89 }; |
| 89 | 90 |
| 90 const char* const MultipleThreadMain::s_test_name_ = | 91 const char* const MultipleThreadMain::s_test_name_ = |
| 91 "SharedMemoryOpenThreadTest"; | 92 "SharedMemoryOpenThreadTest"; |
| 92 | 93 |
| 93 // TODO(port): | |
| 94 // This test requires the ability to pass file descriptors between processes. | |
| 95 // We haven't done that yet in Chrome for POSIX. | |
| 96 #if defined(OS_WIN) | |
| 97 // Each thread will open the shared memory. Each thread will take the memory, | |
| 98 // and keep changing it while trying to lock it, with some small pauses in | |
| 99 // between. Verify that each thread's value in the shared memory is always | |
| 100 // correct. | |
| 101 class MultipleLockThread : public PlatformThread::Delegate { | |
| 102 public: | |
| 103 explicit MultipleLockThread(int id) : id_(id) {} | |
| 104 ~MultipleLockThread() override {} | |
| 105 | |
| 106 // PlatformThread::Delegate interface. | |
| 107 void ThreadMain() override { | |
| 108 const uint32 kDataSize = sizeof(int); | |
| 109 SharedMemoryHandle handle = NULL; | |
| 110 { | |
| 111 SharedMemory memory1; | |
| 112 EXPECT_TRUE(memory1.CreateNamedDeprecated( | |
| 113 "SharedMemoryMultipleLockThreadTest", true, kDataSize)); | |
| 114 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); | |
| 115 // TODO(paulg): Implement this once we have a posix version of | |
| 116 // SharedMemory::ShareToProcess. | |
| 117 EXPECT_TRUE(true); | |
| 118 } | |
| 119 | |
| 120 SharedMemory memory2(handle, false); | |
| 121 EXPECT_TRUE(memory2.Map(kDataSize)); | |
| 122 volatile int* const ptr = static_cast<int*>(memory2.memory()); | |
| 123 | |
| 124 for (int idx = 0; idx < 20; idx++) { | |
| 125 memory2.LockDeprecated(); | |
| 126 int i = (id_ << 16) + idx; | |
| 127 *ptr = i; | |
| 128 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); | |
| 129 EXPECT_EQ(*ptr, i); | |
| 130 memory2.UnlockDeprecated(); | |
| 131 } | |
| 132 | |
| 133 memory2.Close(); | |
| 134 } | |
| 135 | |
| 136 private: | |
| 137 int id_; | |
| 138 | |
| 139 DISALLOW_COPY_AND_ASSIGN(MultipleLockThread); | |
| 140 }; | |
| 141 #endif | |
| 142 | |
| 143 } // namespace | 94 } // namespace |
| 144 | 95 |
| 145 // Android doesn't support SharedMemory::Open/Delete/ | 96 // Android doesn't support SharedMemory::Open/Delete/ |
| 146 // CreateNamedDeprecated(openExisting=true) | 97 // CreateNamedDeprecated(openExisting=true) |
| 147 #if !defined(OS_ANDROID) | 98 #if !defined(OS_ANDROID) |
| 148 TEST(SharedMemoryTest, OpenClose) { | 99 TEST(SharedMemoryTest, OpenClose) { |
| 149 const uint32 kDataSize = 1024; | 100 const uint32 kDataSize = 1024; |
| 150 std::string test_name = "SharedMemoryOpenCloseTest"; | 101 std::string test_name = "SharedMemoryOpenCloseTest"; |
| 151 | 102 |
| 152 // Open two handles to a memory segment, confirm that they are mapped | 103 // Open two handles to a memory segment, confirm that they are mapped |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 | 264 |
| 314 // Wait for the threads to finish. | 265 // Wait for the threads to finish. |
| 315 for (int index = 0; index < numthreads; index++) { | 266 for (int index = 0; index < numthreads; index++) { |
| 316 PlatformThread::Join(thread_handles[index]); | 267 PlatformThread::Join(thread_handles[index]); |
| 317 delete thread_delegates[index]; | 268 delete thread_delegates[index]; |
| 318 } | 269 } |
| 319 } | 270 } |
| 320 MultipleThreadMain::CleanUp(); | 271 MultipleThreadMain::CleanUp(); |
| 321 } | 272 } |
| 322 | 273 |
| 323 // TODO(port): this test requires the MultipleLockThread class | |
| 324 // (defined above), which requires the ability to pass file | |
| 325 // descriptors between processes. We haven't done that yet in Chrome | |
| 326 // for POSIX. | |
| 327 #if defined(OS_WIN) | |
| 328 // Create a set of threads to each open a shared memory segment and write to it | |
| 329 // with the lock held. Verify that they are always reading/writing consistent | |
| 330 // data. | |
| 331 TEST(SharedMemoryTest, Lock) { | |
| 332 PlatformThreadHandle thread_handles[kNumThreads]; | |
| 333 MultipleLockThread* thread_delegates[kNumThreads]; | |
| 334 | |
| 335 // Spawn the threads. | |
| 336 for (int index = 0; index < kNumThreads; ++index) { | |
| 337 PlatformThreadHandle pth; | |
| 338 thread_delegates[index] = new MultipleLockThread(index); | |
| 339 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); | |
| 340 thread_handles[index] = pth; | |
| 341 } | |
| 342 | |
| 343 // Wait for the threads to finish. | |
| 344 for (int index = 0; index < kNumThreads; ++index) { | |
| 345 PlatformThread::Join(thread_handles[index]); | |
| 346 delete thread_delegates[index]; | |
| 347 } | |
| 348 } | |
| 349 #endif | |
| 350 | |
| 351 // Allocate private (unique) shared memory with an empty string for a | 274 // Allocate private (unique) shared memory with an empty string for a |
| 352 // name. Make sure several of them don't point to the same thing as | 275 // name. Make sure several of them don't point to the same thing as |
| 353 // we might expect if the names are equal. | 276 // we might expect if the names are equal. |
| 354 TEST(SharedMemoryTest, AnonymousPrivate) { | 277 TEST(SharedMemoryTest, AnonymousPrivate) { |
| 355 int i, j; | 278 int i, j; |
| 356 int count = 4; | 279 int count = 4; |
| 357 bool rv; | 280 bool rv; |
| 358 const uint32 kDataSize = 8192; | 281 const uint32 kDataSize = 8192; |
| 359 | 282 |
| 360 scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]); | 283 scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 430 // segment read/write. I think the test here is stronger than we actually | 353 // segment read/write. I think the test here is stronger than we actually |
| 431 // care about, but there's a remote possibility that sending a file over a | 354 // care about, but there's a remote possibility that sending a file over a |
| 432 // pipe would transform it into read/write. | 355 // pipe would transform it into read/write. |
| 433 SharedMemoryHandle handle = readonly_shmem.handle(); | 356 SharedMemoryHandle handle = readonly_shmem.handle(); |
| 434 | 357 |
| 435 #if defined(OS_ANDROID) | 358 #if defined(OS_ANDROID) |
| 436 // The "read-only" handle is still writable on Android: | 359 // The "read-only" handle is still writable on Android: |
| 437 // http://crbug.com/320865 | 360 // http://crbug.com/320865 |
| 438 (void)handle; | 361 (void)handle; |
| 439 #elif defined(OS_POSIX) | 362 #elif defined(OS_POSIX) |
| 440 EXPECT_EQ(O_RDONLY, fcntl(handle.fd, F_GETFL) & O_ACCMODE) | 363 int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle); |
| 364 EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE) |
| 441 << "The descriptor itself should be read-only."; | 365 << "The descriptor itself should be read-only."; |
| 442 | 366 |
| 443 errno = 0; | 367 errno = 0; |
| 444 void* writable = mmap( | 368 void* writable = mmap(NULL, contents.size(), PROT_READ | PROT_WRITE, |
| 445 NULL, contents.size(), PROT_READ | PROT_WRITE, MAP_SHARED, handle.fd, 0); | 369 MAP_SHARED, handle_fd, 0); |
| 446 int mmap_errno = errno; | 370 int mmap_errno = errno; |
| 447 EXPECT_EQ(MAP_FAILED, writable) | 371 EXPECT_EQ(MAP_FAILED, writable) |
| 448 << "It shouldn't be possible to re-mmap the descriptor writable."; | 372 << "It shouldn't be possible to re-mmap the descriptor writable."; |
| 449 EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno); | 373 EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno); |
| 450 if (writable != MAP_FAILED) | 374 if (writable != MAP_FAILED) |
| 451 EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size())); | 375 EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size())); |
| 452 | 376 |
| 453 #elif defined(OS_WIN) | 377 #elif defined(OS_WIN) |
| 454 EXPECT_EQ(NULL, MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, 0)) | 378 EXPECT_EQ(NULL, MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, 0)) |
| 455 << "Shouldn't be able to map memory writable."; | 379 << "Shouldn't be able to map memory writable."; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 589 const uint32 kTestSize = 1 << 8; | 513 const uint32 kTestSize = 1 << 8; |
| 590 | 514 |
| 591 SharedMemory shared_memory; | 515 SharedMemory shared_memory; |
| 592 SharedMemoryCreateOptions options; | 516 SharedMemoryCreateOptions options; |
| 593 options.size = kTestSize; | 517 options.size = kTestSize; |
| 594 // Set a file mode creation mask that gives all permissions. | 518 // Set a file mode creation mask that gives all permissions. |
| 595 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); | 519 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); |
| 596 | 520 |
| 597 EXPECT_TRUE(shared_memory.Create(options)); | 521 EXPECT_TRUE(shared_memory.Create(options)); |
| 598 | 522 |
| 599 int shm_fd = shared_memory.handle().fd; | 523 int shm_fd = |
| 524 SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); |
| 600 struct stat shm_stat; | 525 struct stat shm_stat; |
| 601 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); | 526 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); |
| 602 // Neither the group, nor others should be able to read the shared memory | 527 // Neither the group, nor others should be able to read the shared memory |
| 603 // file. | 528 // file. |
| 604 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); | 529 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); |
| 605 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); | 530 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); |
| 606 } | 531 } |
| 607 | 532 |
| 608 // Create a shared memory object, check its permissions. | 533 // Create a shared memory object, check its permissions. |
| 609 TEST(SharedMemoryTest, FilePermissionsNamed) { | 534 TEST(SharedMemoryTest, FilePermissionsNamed) { |
| 610 const uint32 kTestSize = 1 << 8; | 535 const uint32 kTestSize = 1 << 8; |
| 611 | 536 |
| 612 SharedMemory shared_memory; | 537 SharedMemory shared_memory; |
| 613 SharedMemoryCreateOptions options; | 538 SharedMemoryCreateOptions options; |
| 614 options.size = kTestSize; | 539 options.size = kTestSize; |
| 615 std::string shared_mem_name = "shared_perm_test-" + IntToString(getpid()) + | 540 std::string shared_mem_name = "shared_perm_test-" + IntToString(getpid()) + |
| 616 "-" + Uint64ToString(RandUint64()); | 541 "-" + Uint64ToString(RandUint64()); |
| 617 options.name_deprecated = &shared_mem_name; | 542 options.name_deprecated = &shared_mem_name; |
| 618 // Set a file mode creation mask that gives all permissions. | 543 // Set a file mode creation mask that gives all permissions. |
| 619 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); | 544 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); |
| 620 | 545 |
| 621 EXPECT_TRUE(shared_memory.Create(options)); | 546 EXPECT_TRUE(shared_memory.Create(options)); |
| 622 // Clean-up the backing file name immediately, we don't need it. | 547 // Clean-up the backing file name immediately, we don't need it. |
| 623 EXPECT_TRUE(shared_memory.Delete(shared_mem_name)); | 548 EXPECT_TRUE(shared_memory.Delete(shared_mem_name)); |
| 624 | 549 |
| 625 int shm_fd = shared_memory.handle().fd; | 550 int shm_fd = |
| 551 SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); |
| 626 struct stat shm_stat; | 552 struct stat shm_stat; |
| 627 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); | 553 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); |
| 628 // Neither the group, nor others should have been able to open the shared | 554 // Neither the group, nor others should have been able to open the shared |
| 629 // memory file while its name existed. | 555 // memory file while its name existed. |
| 630 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); | 556 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); |
| 631 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); | 557 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); |
| 632 } | 558 } |
| 633 #endif // !defined(OS_ANDROID) | 559 #endif // !defined(OS_ANDROID) |
| 634 | 560 |
| 635 #endif // defined(OS_POSIX) | 561 #endif // defined(OS_POSIX) |
| 636 | 562 |
| 637 // Map() will return addresses which are aligned to the platform page size, this | 563 // Map() will return addresses which are aligned to the platform page size, this |
| 638 // varies from platform to platform though. Since we'd like to advertise a | 564 // varies from platform to platform though. Since we'd like to advertise a |
| 639 // minimum alignment that callers can count on, test for it here. | 565 // minimum alignment that callers can count on, test for it here. |
| 640 TEST(SharedMemoryTest, MapMinimumAlignment) { | 566 TEST(SharedMemoryTest, MapMinimumAlignment) { |
| 641 static const int kDataSize = 8192; | 567 static const int kDataSize = 8192; |
| 642 | 568 |
| 643 SharedMemory shared_memory; | 569 SharedMemory shared_memory; |
| 644 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize)); | 570 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize)); |
| 645 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>( | 571 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>( |
| 646 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); | 572 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); |
| 647 shared_memory.Close(); | 573 shared_memory.Close(); |
| 648 } | 574 } |
| 649 | 575 |
| 650 #if !defined(OS_IOS) // iOS does not allow multiple processes. | 576 // iOS does not allow multiple processes. |
| 577 // Android ashmem doesn't support named shared memory. |
| 578 #if !defined(OS_IOS) && !defined(OS_ANDROID) |
| 651 | 579 |
| 652 // On POSIX it is especially important we test shmem across processes, | 580 // On POSIX it is especially important we test shmem across processes, |
| 653 // not just across threads. But the test is enabled on all platforms. | 581 // not just across threads. But the test is enabled on all platforms. |
| 654 class SharedMemoryProcessTest : public MultiProcessTest { | 582 class SharedMemoryProcessTest : public MultiProcessTest { |
| 655 public: | 583 public: |
| 656 | 584 |
| 657 static void CleanUp() { | 585 static void CleanUp() { |
| 658 SharedMemory memory; | 586 SharedMemory memory; |
| 659 memory.Delete(s_test_name_); | 587 memory.Delete(s_test_name_); |
| 660 } | 588 } |
| 661 | 589 |
| 662 static int TaskTestMain() { | 590 static int TaskTestMain() { |
| 663 int errors = 0; | 591 int errors = 0; |
| 664 #if defined(OS_MACOSX) | 592 #if defined(OS_MACOSX) |
| 665 mac::ScopedNSAutoreleasePool pool; | 593 mac::ScopedNSAutoreleasePool pool; |
| 666 #endif | 594 #endif |
| 667 const uint32 kDataSize = 1024; | |
| 668 SharedMemory memory; | 595 SharedMemory memory; |
| 669 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); | 596 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); |
| 670 EXPECT_TRUE(rv); | 597 EXPECT_TRUE(rv); |
| 671 if (rv != true) | 598 if (rv != true) |
| 672 errors++; | 599 errors++; |
| 673 rv = memory.Map(kDataSize); | 600 rv = memory.Map(s_data_size_); |
| 674 EXPECT_TRUE(rv); | 601 EXPECT_TRUE(rv); |
| 675 if (rv != true) | 602 if (rv != true) |
| 676 errors++; | 603 errors++; |
| 677 int *ptr = static_cast<int*>(memory.memory()); | 604 int *ptr = static_cast<int*>(memory.memory()); |
| 678 | 605 |
| 679 for (int idx = 0; idx < 20; idx++) { | 606 // This runs concurrently in multiple processes. Writes need to be atomic. |
| 680 memory.LockDeprecated(); | 607 base::subtle::Barrier_AtomicIncrement(ptr, 1); |
| 681 int i = (1 << 16) + idx; | |
| 682 *ptr = i; | |
| 683 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10)); | |
| 684 if (*ptr != i) | |
| 685 errors++; | |
| 686 memory.UnlockDeprecated(); | |
| 687 } | |
| 688 | |
| 689 memory.Close(); | 608 memory.Close(); |
| 690 return errors; | 609 return errors; |
| 691 } | 610 } |
| 692 | 611 |
| 693 private: | |
| 694 static const char* const s_test_name_; | 612 static const char* const s_test_name_; |
| 613 static const uint32 s_data_size_; |
| 695 }; | 614 }; |
| 696 | 615 |
| 697 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem"; | 616 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem"; |
| 617 const uint32 SharedMemoryProcessTest::s_data_size_ = 1024; |
| 698 | 618 |
| 699 TEST_F(SharedMemoryProcessTest, Tasks) { | 619 TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) { |
| 700 SharedMemoryProcessTest::CleanUp(); | 620 SharedMemoryProcessTest::CleanUp(); |
| 701 | 621 |
| 622 // Create a shared memory region. Set the first word to 0. |
| 623 SharedMemory memory; |
| 624 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); |
| 625 ASSERT_TRUE(rv); |
| 626 rv = memory.Map(s_data_size_); |
| 627 ASSERT_TRUE(rv); |
| 628 int* ptr = static_cast<int*>(memory.memory()); |
| 629 *ptr = 0; |
| 630 |
| 631 // Start |kNumTasks| processes, each of which atomically increments the first |
| 632 // word by 1. |
| 702 Process processes[kNumTasks]; | 633 Process processes[kNumTasks]; |
| 703 for (int index = 0; index < kNumTasks; ++index) { | 634 for (int index = 0; index < kNumTasks; ++index) { |
| 704 processes[index] = SpawnChild("SharedMemoryTestMain"); | 635 processes[index] = SpawnChild("SharedMemoryTestMain"); |
| 705 ASSERT_TRUE(processes[index].IsValid()); | 636 ASSERT_TRUE(processes[index].IsValid()); |
| 706 } | 637 } |
| 707 | 638 |
| 639 // Check that each process exited correctly. |
| 708 int exit_code = 0; | 640 int exit_code = 0; |
| 709 for (int index = 0; index < kNumTasks; ++index) { | 641 for (int index = 0; index < kNumTasks; ++index) { |
| 710 EXPECT_TRUE(processes[index].WaitForExit(&exit_code)); | 642 EXPECT_TRUE(processes[index].WaitForExit(&exit_code)); |
| 711 EXPECT_EQ(0, exit_code); | 643 EXPECT_EQ(0, exit_code); |
| 712 } | 644 } |
| 713 | 645 |
| 646 // Check that the shared memory region reflects |kNumTasks| increments. |
| 647 ASSERT_EQ(kNumTasks, *ptr); |
| 648 |
| 649 memory.Close(); |
| 714 SharedMemoryProcessTest::CleanUp(); | 650 SharedMemoryProcessTest::CleanUp(); |
| 715 } | 651 } |
| 716 | 652 |
| 717 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { | 653 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { |
| 718 return SharedMemoryProcessTest::TaskTestMain(); | 654 return SharedMemoryProcessTest::TaskTestMain(); |
| 719 } | 655 } |
| 720 | 656 |
| 721 #endif // !OS_IOS | 657 #endif // !defined(OS_IOS) && !defined(OS_ANDROID) |
| 722 | 658 |
| 723 } // namespace base | 659 } // namespace base |
| OLD | NEW |