Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(132)

Side by Side Diff: base/memory/shared_memory_unittest.cc

Issue 1641513004: Update //base to chromium 9659b08ea5a34f889dc4166217f438095ddc10d2 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/memory/shared_memory_posix.cc ('k') | base/memory/shared_memory_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « base/memory/shared_memory_posix.cc ('k') | base/memory/shared_memory_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698