Roll google-toolbax-for-mac a095262:17eee69 (svn 685:703).
[chromium-blink-merge.git] / base / memory / shared_memory_unittest.cc
blob6e5a4d8f7ee6cdee7c025fc0d048a44a3ba8247d
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
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/memory/shared_memory.h"
8 #include "base/process/kill.h"
9 #include "base/rand_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/sys_info.h"
12 #include "base/test/multiprocess_test.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/time/time.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "testing/multiprocess_func_list.h"
18 #if defined(OS_MACOSX)
19 #include "base/mac/scoped_nsautorelease_pool.h"
20 #endif
22 #if defined(OS_POSIX)
23 #include <errno.h>
24 #include <fcntl.h>
25 #include <sys/mman.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <unistd.h>
29 #endif
31 #if defined(OS_WIN)
32 #include "base/win/scoped_handle.h"
33 #endif
35 static const int kNumThreads = 5;
36 #if !defined(OS_IOS) // iOS does not allow multiple processes.
37 static const int kNumTasks = 5;
38 #endif
40 namespace base {
42 namespace {
44 // 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 // Verify that each thread's value in the shared memory is always correct.
47 class MultipleThreadMain : public PlatformThread::Delegate {
48 public:
49 explicit MultipleThreadMain(int16 id) : id_(id) {}
50 ~MultipleThreadMain() override {}
52 static void CleanUp() {
53 SharedMemory memory;
54 memory.Delete(s_test_name_);
57 // PlatformThread::Delegate interface.
58 void ThreadMain() override {
59 #if defined(OS_MACOSX)
60 mac::ScopedNSAutoreleasePool pool;
61 #endif
62 const uint32 kDataSize = 1024;
63 SharedMemory memory;
64 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize);
65 EXPECT_TRUE(rv);
66 rv = memory.Map(kDataSize);
67 EXPECT_TRUE(rv);
68 int *ptr = static_cast<int*>(memory.memory()) + id_;
69 EXPECT_EQ(0, *ptr);
71 for (int idx = 0; idx < 100; idx++) {
72 *ptr = idx;
73 PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
74 EXPECT_EQ(*ptr, idx);
76 // Reset back to 0 for the next test that uses the same name.
77 *ptr = 0;
79 memory.Close();
82 private:
83 int16 id_;
85 static const char* const s_test_name_;
87 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
90 const char* const MultipleThreadMain::s_test_name_ =
91 "SharedMemoryOpenThreadTest";
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 virtual ~MultipleLockThread() {}
106 // PlatformThread::Delegate interface.
107 virtual void ThreadMain() override {
108 const uint32 kDataSize = sizeof(int);
109 SharedMemoryHandle handle = NULL;
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);
120 SharedMemory memory2(handle, false);
121 EXPECT_TRUE(memory2.Map(kDataSize));
122 volatile int* const ptr = static_cast<int*>(memory2.memory());
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();
133 memory2.Close();
136 private:
137 int id_;
139 DISALLOW_COPY_AND_ASSIGN(MultipleLockThread);
141 #endif
143 } // namespace
145 // Android doesn't support SharedMemory::Open/Delete/
146 // CreateNamedDeprecated(openExisting=true)
147 #if !defined(OS_ANDROID)
148 TEST(SharedMemoryTest, OpenClose) {
149 const uint32 kDataSize = 1024;
150 std::string test_name = "SharedMemoryOpenCloseTest";
152 // Open two handles to a memory segment, confirm that they are mapped
153 // separately yet point to the same space.
154 SharedMemory memory1;
155 bool rv = memory1.Delete(test_name);
156 EXPECT_TRUE(rv);
157 rv = memory1.Delete(test_name);
158 EXPECT_TRUE(rv);
159 rv = memory1.Open(test_name, false);
160 EXPECT_FALSE(rv);
161 rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
162 EXPECT_TRUE(rv);
163 rv = memory1.Map(kDataSize);
164 EXPECT_TRUE(rv);
165 SharedMemory memory2;
166 rv = memory2.Open(test_name, false);
167 EXPECT_TRUE(rv);
168 rv = memory2.Map(kDataSize);
169 EXPECT_TRUE(rv);
170 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers.
172 // Make sure we don't segfault. (it actually happened!)
173 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
174 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));
176 // Write data to the first memory segment, verify contents of second.
177 memset(memory1.memory(), '1', kDataSize);
178 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
180 // Close the first memory segment, and verify the second has the right data.
181 memory1.Close();
182 char *start_ptr = static_cast<char *>(memory2.memory());
183 char *end_ptr = start_ptr + kDataSize;
184 for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
185 EXPECT_EQ(*ptr, '1');
187 // Close the second memory segment.
188 memory2.Close();
190 rv = memory1.Delete(test_name);
191 EXPECT_TRUE(rv);
192 rv = memory2.Delete(test_name);
193 EXPECT_TRUE(rv);
196 TEST(SharedMemoryTest, OpenExclusive) {
197 const uint32 kDataSize = 1024;
198 const uint32 kDataSize2 = 2048;
199 std::ostringstream test_name_stream;
200 test_name_stream << "SharedMemoryOpenExclusiveTest."
201 << Time::Now().ToDoubleT();
202 std::string test_name = test_name_stream.str();
204 // Open two handles to a memory segment and check that
205 // open_existing_deprecated works as expected.
206 SharedMemory memory1;
207 bool rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
208 EXPECT_TRUE(rv);
210 // Memory1 knows it's size because it created it.
211 EXPECT_EQ(memory1.requested_size(), kDataSize);
213 rv = memory1.Map(kDataSize);
214 EXPECT_TRUE(rv);
216 // The mapped memory1 must be at least the size we asked for.
217 EXPECT_GE(memory1.mapped_size(), kDataSize);
219 // The mapped memory1 shouldn't exceed rounding for allocation granularity.
220 EXPECT_LT(memory1.mapped_size(),
221 kDataSize + base::SysInfo::VMAllocationGranularity());
223 memset(memory1.memory(), 'G', kDataSize);
225 SharedMemory memory2;
226 // Should not be able to create if openExisting is false.
227 rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2);
228 EXPECT_FALSE(rv);
230 // Should be able to create with openExisting true.
231 rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2);
232 EXPECT_TRUE(rv);
234 // Memory2 shouldn't know the size because we didn't create it.
235 EXPECT_EQ(memory2.requested_size(), 0U);
237 // We should be able to map the original size.
238 rv = memory2.Map(kDataSize);
239 EXPECT_TRUE(rv);
241 // The mapped memory2 must be at least the size of the original.
242 EXPECT_GE(memory2.mapped_size(), kDataSize);
244 // The mapped memory2 shouldn't exceed rounding for allocation granularity.
245 EXPECT_LT(memory2.mapped_size(),
246 kDataSize2 + base::SysInfo::VMAllocationGranularity());
248 // Verify that opening memory2 didn't truncate or delete memory 1.
249 char *start_ptr = static_cast<char *>(memory2.memory());
250 char *end_ptr = start_ptr + kDataSize;
251 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
252 EXPECT_EQ(*ptr, 'G');
255 memory1.Close();
256 memory2.Close();
258 rv = memory1.Delete(test_name);
259 EXPECT_TRUE(rv);
261 #endif
263 // Check that memory is still mapped after its closed.
264 TEST(SharedMemoryTest, CloseNoUnmap) {
265 const size_t kDataSize = 4096;
267 SharedMemory memory;
268 ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
269 char* ptr = static_cast<char*>(memory.memory());
270 ASSERT_NE(ptr, static_cast<void*>(NULL));
271 memset(ptr, 'G', kDataSize);
273 memory.Close();
275 EXPECT_EQ(ptr, memory.memory());
276 EXPECT_EQ(SharedMemory::NULLHandle(), memory.handle());
278 for (size_t i = 0; i < kDataSize; i++) {
279 EXPECT_EQ('G', ptr[i]);
282 memory.Unmap();
283 EXPECT_EQ(nullptr, memory.memory());
286 // Create a set of N threads to each open a shared memory segment and write to
287 // it. Verify that they are always reading/writing consistent data.
288 TEST(SharedMemoryTest, MultipleThreads) {
289 MultipleThreadMain::CleanUp();
290 // On POSIX we have a problem when 2 threads try to create the shmem
291 // (a file) at exactly the same time, since create both creates the
292 // file and zerofills it. We solve the problem for this unit test
293 // (make it not flaky) by starting with 1 thread, then
294 // intentionally don't clean up its shmem before running with
295 // kNumThreads.
297 int threadcounts[] = { 1, kNumThreads };
298 for (size_t i = 0; i < arraysize(threadcounts); i++) {
299 int numthreads = threadcounts[i];
300 scoped_ptr<PlatformThreadHandle[]> thread_handles;
301 scoped_ptr<MultipleThreadMain*[]> thread_delegates;
303 thread_handles.reset(new PlatformThreadHandle[numthreads]);
304 thread_delegates.reset(new MultipleThreadMain*[numthreads]);
306 // Spawn the threads.
307 for (int16 index = 0; index < numthreads; index++) {
308 PlatformThreadHandle pth;
309 thread_delegates[index] = new MultipleThreadMain(index);
310 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
311 thread_handles[index] = pth;
314 // Wait for the threads to finish.
315 for (int index = 0; index < numthreads; index++) {
316 PlatformThread::Join(thread_handles[index]);
317 delete thread_delegates[index];
320 MultipleThreadMain::CleanUp();
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];
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;
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];
349 #endif
351 // 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
353 // we might expect if the names are equal.
354 TEST(SharedMemoryTest, AnonymousPrivate) {
355 int i, j;
356 int count = 4;
357 bool rv;
358 const uint32 kDataSize = 8192;
360 scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]);
361 scoped_ptr<int*[]> pointers(new int*[count]);
362 ASSERT_TRUE(memories.get());
363 ASSERT_TRUE(pointers.get());
365 for (i = 0; i < count; i++) {
366 rv = memories[i].CreateAndMapAnonymous(kDataSize);
367 EXPECT_TRUE(rv);
368 int *ptr = static_cast<int*>(memories[i].memory());
369 EXPECT_TRUE(ptr);
370 pointers[i] = ptr;
373 for (i = 0; i < count; i++) {
374 // zero out the first int in each except for i; for that one, make it 100.
375 for (j = 0; j < count; j++) {
376 if (i == j)
377 pointers[j][0] = 100;
378 else
379 pointers[j][0] = 0;
381 // make sure there is no bleeding of the 100 into the other pointers
382 for (j = 0; j < count; j++) {
383 if (i == j)
384 EXPECT_EQ(100, pointers[j][0]);
385 else
386 EXPECT_EQ(0, pointers[j][0]);
390 for (int i = 0; i < count; i++) {
391 memories[i].Close();
395 TEST(SharedMemoryTest, ShareReadOnly) {
396 StringPiece contents = "Hello World";
398 SharedMemory writable_shmem;
399 SharedMemoryCreateOptions options;
400 options.size = contents.size();
401 options.share_read_only = true;
402 ASSERT_TRUE(writable_shmem.Create(options));
403 ASSERT_TRUE(writable_shmem.Map(options.size));
404 memcpy(writable_shmem.memory(), contents.data(), contents.size());
405 EXPECT_TRUE(writable_shmem.Unmap());
407 SharedMemoryHandle readonly_handle;
408 ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(),
409 &readonly_handle));
410 SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true);
412 ASSERT_TRUE(readonly_shmem.Map(contents.size()));
413 EXPECT_EQ(contents,
414 StringPiece(static_cast<const char*>(readonly_shmem.memory()),
415 contents.size()));
416 EXPECT_TRUE(readonly_shmem.Unmap());
418 // Make sure the writable instance is still writable.
419 ASSERT_TRUE(writable_shmem.Map(contents.size()));
420 StringPiece new_contents = "Goodbye";
421 memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size());
422 EXPECT_EQ(new_contents,
423 StringPiece(static_cast<const char*>(writable_shmem.memory()),
424 new_contents.size()));
426 // We'd like to check that if we send the read-only segment to another
427 // process, then that other process can't reopen it read/write. (Since that
428 // would be a security hole.) Setting up multiple processes is hard in a
429 // unittest, so this test checks that the *current* process can't reopen the
430 // 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
432 // pipe would transform it into read/write.
433 SharedMemoryHandle handle = readonly_shmem.handle();
435 #if defined(OS_ANDROID)
436 // The "read-only" handle is still writable on Android:
437 // http://crbug.com/320865
438 (void)handle;
439 #elif defined(OS_POSIX)
440 EXPECT_EQ(O_RDONLY, fcntl(handle.fd, F_GETFL) & O_ACCMODE)
441 << "The descriptor itself should be read-only.";
443 errno = 0;
444 void* writable = mmap(
445 NULL, contents.size(), PROT_READ | PROT_WRITE, MAP_SHARED, handle.fd, 0);
446 int mmap_errno = errno;
447 EXPECT_EQ(MAP_FAILED, writable)
448 << "It shouldn't be possible to re-mmap the descriptor writable.";
449 EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno);
450 if (writable != MAP_FAILED)
451 EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size()));
453 #elif defined(OS_WIN)
454 EXPECT_EQ(NULL, MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, 0))
455 << "Shouldn't be able to map memory writable.";
457 HANDLE temp_handle;
458 BOOL rv = ::DuplicateHandle(GetCurrentProcess(),
459 handle,
460 GetCurrentProcess(),
461 &temp_handle,
462 FILE_MAP_ALL_ACCESS,
463 false,
465 EXPECT_EQ(FALSE, rv)
466 << "Shouldn't be able to duplicate the handle into a writable one.";
467 if (rv)
468 base::win::ScopedHandle writable_handle(temp_handle);
469 rv = ::DuplicateHandle(GetCurrentProcess(),
470 handle,
471 GetCurrentProcess(),
472 &temp_handle,
473 FILE_MAP_READ,
474 false,
476 EXPECT_EQ(TRUE, rv)
477 << "Should be able to duplicate the handle into a readable one.";
478 if (rv)
479 base::win::ScopedHandle writable_handle(temp_handle);
480 #else
481 #error Unexpected platform; write a test that tries to make 'handle' writable.
482 #endif // defined(OS_POSIX) || defined(OS_WIN)
485 TEST(SharedMemoryTest, ShareToSelf) {
486 StringPiece contents = "Hello World";
488 SharedMemory shmem;
489 ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size()));
490 memcpy(shmem.memory(), contents.data(), contents.size());
491 EXPECT_TRUE(shmem.Unmap());
493 SharedMemoryHandle shared_handle;
494 ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
495 SharedMemory shared(shared_handle, /*readonly=*/false);
497 ASSERT_TRUE(shared.Map(contents.size()));
498 EXPECT_EQ(
499 contents,
500 StringPiece(static_cast<const char*>(shared.memory()), contents.size()));
502 ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
503 SharedMemory readonly(shared_handle, /*readonly=*/true);
505 ASSERT_TRUE(readonly.Map(contents.size()));
506 EXPECT_EQ(contents,
507 StringPiece(static_cast<const char*>(readonly.memory()),
508 contents.size()));
511 TEST(SharedMemoryTest, MapAt) {
512 ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32));
513 const size_t kCount = SysInfo::VMAllocationGranularity();
514 const size_t kDataSize = kCount * sizeof(uint32);
516 SharedMemory memory;
517 ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
518 uint32* ptr = static_cast<uint32*>(memory.memory());
519 ASSERT_NE(ptr, static_cast<void*>(NULL));
521 for (size_t i = 0; i < kCount; ++i) {
522 ptr[i] = i;
525 memory.Unmap();
527 off_t offset = SysInfo::VMAllocationGranularity();
528 ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset));
529 offset /= sizeof(uint32);
530 ptr = static_cast<uint32*>(memory.memory());
531 ASSERT_NE(ptr, static_cast<void*>(NULL));
532 for (size_t i = offset; i < kCount; ++i) {
533 EXPECT_EQ(ptr[i - offset], i);
537 TEST(SharedMemoryTest, MapTwice) {
538 const uint32 kDataSize = 1024;
539 SharedMemory memory;
540 bool rv = memory.CreateAndMapAnonymous(kDataSize);
541 EXPECT_TRUE(rv);
543 void* old_address = memory.memory();
545 rv = memory.Map(kDataSize);
546 EXPECT_FALSE(rv);
547 EXPECT_EQ(old_address, memory.memory());
550 #if defined(OS_POSIX)
551 // This test is not applicable for iOS (crbug.com/399384).
552 #if !defined(OS_IOS)
553 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
554 TEST(SharedMemoryTest, AnonymousExecutable) {
555 const uint32 kTestSize = 1 << 16;
557 SharedMemory shared_memory;
558 SharedMemoryCreateOptions options;
559 options.size = kTestSize;
560 options.executable = true;
562 EXPECT_TRUE(shared_memory.Create(options));
563 EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
565 EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(),
566 PROT_READ | PROT_EXEC));
568 #endif // !defined(OS_IOS)
570 // Android supports a different permission model than POSIX for its "ashmem"
571 // shared memory implementation. So the tests about file permissions are not
572 // included on Android.
573 #if !defined(OS_ANDROID)
575 // Set a umask and restore the old mask on destruction.
576 class ScopedUmaskSetter {
577 public:
578 explicit ScopedUmaskSetter(mode_t target_mask) {
579 old_umask_ = umask(target_mask);
581 ~ScopedUmaskSetter() { umask(old_umask_); }
582 private:
583 mode_t old_umask_;
584 DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
587 // Create a shared memory object, check its permissions.
588 TEST(SharedMemoryTest, FilePermissionsAnonymous) {
589 const uint32 kTestSize = 1 << 8;
591 SharedMemory shared_memory;
592 SharedMemoryCreateOptions options;
593 options.size = kTestSize;
594 // Set a file mode creation mask that gives all permissions.
595 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
597 EXPECT_TRUE(shared_memory.Create(options));
599 int shm_fd = shared_memory.handle().fd;
600 struct stat shm_stat;
601 EXPECT_EQ(0, fstat(shm_fd, &shm_stat));
602 // Neither the group, nor others should be able to read the shared memory
603 // file.
604 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
605 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
608 // Create a shared memory object, check its permissions.
609 TEST(SharedMemoryTest, FilePermissionsNamed) {
610 const uint32 kTestSize = 1 << 8;
612 SharedMemory shared_memory;
613 SharedMemoryCreateOptions options;
614 options.size = kTestSize;
615 std::string shared_mem_name = "shared_perm_test-" + IntToString(getpid()) +
616 "-" + Uint64ToString(RandUint64());
617 options.name_deprecated = &shared_mem_name;
618 // Set a file mode creation mask that gives all permissions.
619 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
621 EXPECT_TRUE(shared_memory.Create(options));
622 // Clean-up the backing file name immediately, we don't need it.
623 EXPECT_TRUE(shared_memory.Delete(shared_mem_name));
625 int shm_fd = shared_memory.handle().fd;
626 struct stat shm_stat;
627 EXPECT_EQ(0, fstat(shm_fd, &shm_stat));
628 // Neither the group, nor others should have been able to open the shared
629 // memory file while its name existed.
630 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
631 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
633 #endif // !defined(OS_ANDROID)
635 #endif // defined(OS_POSIX)
637 // 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
639 // minimum alignment that callers can count on, test for it here.
640 TEST(SharedMemoryTest, MapMinimumAlignment) {
641 static const int kDataSize = 8192;
643 SharedMemory shared_memory;
644 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize));
645 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>(
646 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
647 shared_memory.Close();
650 #if !defined(OS_IOS) // iOS does not allow multiple processes.
652 // On POSIX it is especially important we test shmem across processes,
653 // not just across threads. But the test is enabled on all platforms.
654 class SharedMemoryProcessTest : public MultiProcessTest {
655 public:
657 static void CleanUp() {
658 SharedMemory memory;
659 memory.Delete(s_test_name_);
662 static int TaskTestMain() {
663 int errors = 0;
664 #if defined(OS_MACOSX)
665 mac::ScopedNSAutoreleasePool pool;
666 #endif
667 const uint32 kDataSize = 1024;
668 SharedMemory memory;
669 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize);
670 EXPECT_TRUE(rv);
671 if (rv != true)
672 errors++;
673 rv = memory.Map(kDataSize);
674 EXPECT_TRUE(rv);
675 if (rv != true)
676 errors++;
677 int *ptr = static_cast<int*>(memory.memory());
679 for (int idx = 0; idx < 20; idx++) {
680 memory.LockDeprecated();
681 int i = (1 << 16) + idx;
682 *ptr = i;
683 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
684 if (*ptr != i)
685 errors++;
686 memory.UnlockDeprecated();
689 memory.Close();
690 return errors;
693 private:
694 static const char* const s_test_name_;
697 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem";
699 TEST_F(SharedMemoryProcessTest, Tasks) {
700 SharedMemoryProcessTest::CleanUp();
702 Process processes[kNumTasks];
703 for (int index = 0; index < kNumTasks; ++index) {
704 processes[index] = SpawnChild("SharedMemoryTestMain");
705 ASSERT_TRUE(processes[index].IsValid());
708 int exit_code = 0;
709 for (int index = 0; index < kNumTasks; ++index) {
710 EXPECT_TRUE(processes[index].WaitForExit(&exit_code));
711 EXPECT_EQ(0, exit_code);
714 SharedMemoryProcessTest::CleanUp();
717 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
718 return SharedMemoryProcessTest::TaskTestMain();
721 #endif // !OS_IOS
723 } // namespace base