Home | History | Annotate | Download | only in memory
      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.
      4 
      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"
     17 
     18 #if defined(OS_MACOSX)
     19 #include "base/mac/scoped_nsautorelease_pool.h"
     20 #endif
     21 
     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
     30 
     31 #if defined(OS_WIN)
     32 #include "base/win/scoped_handle.h"
     33 #endif
     34 
     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
     39 
     40 namespace base {
     41 
     42 namespace {
     43 
     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   virtual ~MultipleThreadMain() {}
     51 
     52   static void CleanUp() {
     53     SharedMemory memory;
     54     memory.Delete(s_test_name_);
     55   }
     56 
     57   // PlatformThread::Delegate interface.
     58   virtual 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);
     70 
     71     for (int idx = 0; idx < 100; idx++) {
     72       *ptr = idx;
     73       PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
     74       EXPECT_EQ(*ptr, idx);
     75     }
     76     // Reset back to 0 for the next test that uses the same name.
     77     *ptr = 0;
     78 
     79     memory.Close();
     80   }
     81 
     82  private:
     83   int16 id_;
     84 
     85   static const char* const s_test_name_;
     86 
     87   DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
     88 };
     89 
     90 const char* const MultipleThreadMain::s_test_name_ =
     91     "SharedMemoryOpenThreadTest";
     92 
     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() {}
    105 
    106   // PlatformThread::Delegate interface.
    107   virtual 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
    144 
    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";
    151 
    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.
    171 
    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));
    175 
    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);
    179 
    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');
    186 
    187   // Close the second memory segment.
    188   memory2.Close();
    189 
    190   rv = memory1.Delete(test_name);
    191   EXPECT_TRUE(rv);
    192   rv = memory2.Delete(test_name);
    193   EXPECT_TRUE(rv);
    194 }
    195 
    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();
    203 
    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);
    209 
    210   // Memory1 knows it's size because it created it.
    211   EXPECT_EQ(memory1.requested_size(), kDataSize);
    212 
    213   rv = memory1.Map(kDataSize);
    214   EXPECT_TRUE(rv);
    215 
    216   // The mapped memory1 must be at least the size we asked for.
    217   EXPECT_GE(memory1.mapped_size(), kDataSize);
    218 
    219   // The mapped memory1 shouldn't exceed rounding for allocation granularity.
    220   EXPECT_LT(memory1.mapped_size(),
    221             kDataSize + base::SysInfo::VMAllocationGranularity());
    222 
    223   memset(memory1.memory(), 'G', kDataSize);
    224 
    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);
    229 
    230   // Should be able to create with openExisting true.
    231   rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2);
    232   EXPECT_TRUE(rv);
    233 
    234   // Memory2 shouldn't know the size because we didn't create it.
    235   EXPECT_EQ(memory2.requested_size(), 0U);
    236 
    237   // We should be able to map the original size.
    238   rv = memory2.Map(kDataSize);
    239   EXPECT_TRUE(rv);
    240 
    241   // The mapped memory2 must be at least the size of the original.
    242   EXPECT_GE(memory2.mapped_size(), kDataSize);
    243 
    244   // The mapped memory2 shouldn't exceed rounding for allocation granularity.
    245   EXPECT_LT(memory2.mapped_size(),
    246             kDataSize2 + base::SysInfo::VMAllocationGranularity());
    247 
    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');
    253   }
    254 
    255   memory1.Close();
    256   memory2.Close();
    257 
    258   rv = memory1.Delete(test_name);
    259   EXPECT_TRUE(rv);
    260 }
    261 #endif
    262 
    263 // Create a set of N threads to each open a shared memory segment and write to
    264 // it. Verify that they are always reading/writing consistent data.
    265 TEST(SharedMemoryTest, MultipleThreads) {
    266   MultipleThreadMain::CleanUp();
    267   // On POSIX we have a problem when 2 threads try to create the shmem
    268   // (a file) at exactly the same time, since create both creates the
    269   // file and zerofills it.  We solve the problem for this unit test
    270   // (make it not flaky) by starting with 1 thread, then
    271   // intentionally don't clean up its shmem before running with
    272   // kNumThreads.
    273 
    274   int threadcounts[] = { 1, kNumThreads };
    275   for (size_t i = 0; i < arraysize(threadcounts); i++) {
    276     int numthreads = threadcounts[i];
    277     scoped_ptr<PlatformThreadHandle[]> thread_handles;
    278     scoped_ptr<MultipleThreadMain*[]> thread_delegates;
    279 
    280     thread_handles.reset(new PlatformThreadHandle[numthreads]);
    281     thread_delegates.reset(new MultipleThreadMain*[numthreads]);
    282 
    283     // Spawn the threads.
    284     for (int16 index = 0; index < numthreads; index++) {
    285       PlatformThreadHandle pth;
    286       thread_delegates[index] = new MultipleThreadMain(index);
    287       EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
    288       thread_handles[index] = pth;
    289     }
    290 
    291     // Wait for the threads to finish.
    292     for (int index = 0; index < numthreads; index++) {
    293       PlatformThread::Join(thread_handles[index]);
    294       delete thread_delegates[index];
    295     }
    296   }
    297   MultipleThreadMain::CleanUp();
    298 }
    299 
    300 // TODO(port): this test requires the MultipleLockThread class
    301 // (defined above), which requires the ability to pass file
    302 // descriptors between processes.  We haven't done that yet in Chrome
    303 // for POSIX.
    304 #if defined(OS_WIN)
    305 // Create a set of threads to each open a shared memory segment and write to it
    306 // with the lock held. Verify that they are always reading/writing consistent
    307 // data.
    308 TEST(SharedMemoryTest, Lock) {
    309   PlatformThreadHandle thread_handles[kNumThreads];
    310   MultipleLockThread* thread_delegates[kNumThreads];
    311 
    312   // Spawn the threads.
    313   for (int index = 0; index < kNumThreads; ++index) {
    314     PlatformThreadHandle pth;
    315     thread_delegates[index] = new MultipleLockThread(index);
    316     EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
    317     thread_handles[index] = pth;
    318   }
    319 
    320   // Wait for the threads to finish.
    321   for (int index = 0; index < kNumThreads; ++index) {
    322     PlatformThread::Join(thread_handles[index]);
    323     delete thread_delegates[index];
    324   }
    325 }
    326 #endif
    327 
    328 // Allocate private (unique) shared memory with an empty string for a
    329 // name.  Make sure several of them don't point to the same thing as
    330 // we might expect if the names are equal.
    331 TEST(SharedMemoryTest, AnonymousPrivate) {
    332   int i, j;
    333   int count = 4;
    334   bool rv;
    335   const uint32 kDataSize = 8192;
    336 
    337   scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]);
    338   scoped_ptr<int*[]> pointers(new int*[count]);
    339   ASSERT_TRUE(memories.get());
    340   ASSERT_TRUE(pointers.get());
    341 
    342   for (i = 0; i < count; i++) {
    343     rv = memories[i].CreateAndMapAnonymous(kDataSize);
    344     EXPECT_TRUE(rv);
    345     int *ptr = static_cast<int*>(memories[i].memory());
    346     EXPECT_TRUE(ptr);
    347     pointers[i] = ptr;
    348   }
    349 
    350   for (i = 0; i < count; i++) {
    351     // zero out the first int in each except for i; for that one, make it 100.
    352     for (j = 0; j < count; j++) {
    353       if (i == j)
    354         pointers[j][0] = 100;
    355       else
    356         pointers[j][0] = 0;
    357     }
    358     // make sure there is no bleeding of the 100 into the other pointers
    359     for (j = 0; j < count; j++) {
    360       if (i == j)
    361         EXPECT_EQ(100, pointers[j][0]);
    362       else
    363         EXPECT_EQ(0, pointers[j][0]);
    364     }
    365   }
    366 
    367   for (int i = 0; i < count; i++) {
    368     memories[i].Close();
    369   }
    370 }
    371 
    372 TEST(SharedMemoryTest, ShareReadOnly) {
    373   StringPiece contents = "Hello World";
    374 
    375   SharedMemory writable_shmem;
    376   SharedMemoryCreateOptions options;
    377   options.size = contents.size();
    378   options.share_read_only = true;
    379   ASSERT_TRUE(writable_shmem.Create(options));
    380   ASSERT_TRUE(writable_shmem.Map(options.size));
    381   memcpy(writable_shmem.memory(), contents.data(), contents.size());
    382   EXPECT_TRUE(writable_shmem.Unmap());
    383 
    384   SharedMemoryHandle readonly_handle;
    385   ASSERT_TRUE(writable_shmem.ShareReadOnlyToProcess(GetCurrentProcessHandle(),
    386                                                     &readonly_handle));
    387   SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true);
    388 
    389   ASSERT_TRUE(readonly_shmem.Map(contents.size()));
    390   EXPECT_EQ(contents,
    391             StringPiece(static_cast<const char*>(readonly_shmem.memory()),
    392                         contents.size()));
    393   EXPECT_TRUE(readonly_shmem.Unmap());
    394 
    395   // Make sure the writable instance is still writable.
    396   ASSERT_TRUE(writable_shmem.Map(contents.size()));
    397   StringPiece new_contents = "Goodbye";
    398   memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size());
    399   EXPECT_EQ(new_contents,
    400             StringPiece(static_cast<const char*>(writable_shmem.memory()),
    401                         new_contents.size()));
    402 
    403   // We'd like to check that if we send the read-only segment to another
    404   // process, then that other process can't reopen it read/write.  (Since that
    405   // would be a security hole.)  Setting up multiple processes is hard in a
    406   // unittest, so this test checks that the *current* process can't reopen the
    407   // segment read/write.  I think the test here is stronger than we actually
    408   // care about, but there's a remote possibility that sending a file over a
    409   // pipe would transform it into read/write.
    410   SharedMemoryHandle handle = readonly_shmem.handle();
    411 
    412 #if defined(OS_ANDROID)
    413   // The "read-only" handle is still writable on Android:
    414   // http://crbug.com/320865
    415   (void)handle;
    416 #elif defined(OS_POSIX)
    417   EXPECT_EQ(O_RDONLY, fcntl(handle.fd, F_GETFL) & O_ACCMODE)
    418       << "The descriptor itself should be read-only.";
    419 
    420   errno = 0;
    421   void* writable = mmap(
    422       NULL, contents.size(), PROT_READ | PROT_WRITE, MAP_SHARED, handle.fd, 0);
    423   int mmap_errno = errno;
    424   EXPECT_EQ(MAP_FAILED, writable)
    425       << "It shouldn't be possible to re-mmap the descriptor writable.";
    426   EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno);
    427   if (writable != MAP_FAILED)
    428     EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size()));
    429 
    430 #elif defined(OS_WIN)
    431   EXPECT_EQ(NULL, MapViewOfFile(handle, FILE_MAP_WRITE, 0, 0, 0))
    432       << "Shouldn't be able to map memory writable.";
    433 
    434   HANDLE temp_handle;
    435   BOOL rv = ::DuplicateHandle(GetCurrentProcess(),
    436                               handle,
    437                               GetCurrentProcess(),
    438                               &temp_handle,
    439                               FILE_MAP_ALL_ACCESS,
    440                               false,
    441                               0);
    442   EXPECT_EQ(FALSE, rv)
    443       << "Shouldn't be able to duplicate the handle into a writable one.";
    444   if (rv)
    445     base::win::ScopedHandle writable_handle(temp_handle);
    446   rv = ::DuplicateHandle(GetCurrentProcess(),
    447                          handle,
    448                          GetCurrentProcess(),
    449                          &temp_handle,
    450                          FILE_MAP_READ,
    451                          false,
    452                          0);
    453   EXPECT_EQ(TRUE, rv)
    454       << "Should be able to duplicate the handle into a readable one.";
    455   if (rv)
    456     base::win::ScopedHandle writable_handle(temp_handle);
    457 #else
    458 #error Unexpected platform; write a test that tries to make 'handle' writable.
    459 #endif  // defined(OS_POSIX) || defined(OS_WIN)
    460 }
    461 
    462 TEST(SharedMemoryTest, ShareToSelf) {
    463   StringPiece contents = "Hello World";
    464 
    465   SharedMemory shmem;
    466   ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size()));
    467   memcpy(shmem.memory(), contents.data(), contents.size());
    468   EXPECT_TRUE(shmem.Unmap());
    469 
    470   SharedMemoryHandle shared_handle;
    471   ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
    472   SharedMemory shared(shared_handle, /*readonly=*/false);
    473 
    474   ASSERT_TRUE(shared.Map(contents.size()));
    475   EXPECT_EQ(
    476       contents,
    477       StringPiece(static_cast<const char*>(shared.memory()), contents.size()));
    478 
    479   ASSERT_TRUE(shmem.ShareToProcess(GetCurrentProcessHandle(), &shared_handle));
    480   SharedMemory readonly(shared_handle, /*readonly=*/true);
    481 
    482   ASSERT_TRUE(readonly.Map(contents.size()));
    483   EXPECT_EQ(contents,
    484             StringPiece(static_cast<const char*>(readonly.memory()),
    485                         contents.size()));
    486 }
    487 
    488 TEST(SharedMemoryTest, MapAt) {
    489   ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32));
    490   const size_t kCount = SysInfo::VMAllocationGranularity();
    491   const size_t kDataSize = kCount * sizeof(uint32);
    492 
    493   SharedMemory memory;
    494   ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
    495   uint32* ptr = static_cast<uint32*>(memory.memory());
    496   ASSERT_NE(ptr, static_cast<void*>(NULL));
    497 
    498   for (size_t i = 0; i < kCount; ++i) {
    499     ptr[i] = i;
    500   }
    501 
    502   memory.Unmap();
    503 
    504   off_t offset = SysInfo::VMAllocationGranularity();
    505   ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset));
    506   offset /= sizeof(uint32);
    507   ptr = static_cast<uint32*>(memory.memory());
    508   ASSERT_NE(ptr, static_cast<void*>(NULL));
    509   for (size_t i = offset; i < kCount; ++i) {
    510     EXPECT_EQ(ptr[i - offset], i);
    511   }
    512 }
    513 
    514 TEST(SharedMemoryTest, MapTwice) {
    515   const uint32 kDataSize = 1024;
    516   SharedMemory memory;
    517   bool rv = memory.CreateAndMapAnonymous(kDataSize);
    518   EXPECT_TRUE(rv);
    519 
    520   void* old_address = memory.memory();
    521 
    522   rv = memory.Map(kDataSize);
    523   EXPECT_FALSE(rv);
    524   EXPECT_EQ(old_address, memory.memory());
    525 }
    526 
    527 #if defined(OS_POSIX)
    528 // This test is not applicable for iOS (crbug.com/399384).
    529 #if !defined(OS_IOS)
    530 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
    531 TEST(SharedMemoryTest, AnonymousExecutable) {
    532   const uint32 kTestSize = 1 << 16;
    533 
    534   SharedMemory shared_memory;
    535   SharedMemoryCreateOptions options;
    536   options.size = kTestSize;
    537   options.executable = true;
    538 
    539   EXPECT_TRUE(shared_memory.Create(options));
    540   EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
    541 
    542   EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(),
    543                         PROT_READ | PROT_EXEC));
    544 }
    545 #endif  // !defined(OS_IOS)
    546 
    547 // Android supports a different permission model than POSIX for its "ashmem"
    548 // shared memory implementation. So the tests about file permissions are not
    549 // included on Android.
    550 #if !defined(OS_ANDROID)
    551 
    552 // Set a umask and restore the old mask on destruction.
    553 class ScopedUmaskSetter {
    554  public:
    555   explicit ScopedUmaskSetter(mode_t target_mask) {
    556     old_umask_ = umask(target_mask);
    557   }
    558   ~ScopedUmaskSetter() { umask(old_umask_); }
    559  private:
    560   mode_t old_umask_;
    561   DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
    562 };
    563 
    564 // Create a shared memory object, check its permissions.
    565 TEST(SharedMemoryTest, FilePermissionsAnonymous) {
    566   const uint32 kTestSize = 1 << 8;
    567 
    568   SharedMemory shared_memory;
    569   SharedMemoryCreateOptions options;
    570   options.size = kTestSize;
    571   // Set a file mode creation mask that gives all permissions.
    572   ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
    573 
    574   EXPECT_TRUE(shared_memory.Create(options));
    575 
    576   int shm_fd = shared_memory.handle().fd;
    577   struct stat shm_stat;
    578   EXPECT_EQ(0, fstat(shm_fd, &shm_stat));
    579   // Neither the group, nor others should be able to read the shared memory
    580   // file.
    581   EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
    582   EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
    583 }
    584 
    585 // Create a shared memory object, check its permissions.
    586 TEST(SharedMemoryTest, FilePermissionsNamed) {
    587   const uint32 kTestSize = 1 << 8;
    588 
    589   SharedMemory shared_memory;
    590   SharedMemoryCreateOptions options;
    591   options.size = kTestSize;
    592   std::string shared_mem_name = "shared_perm_test-" + IntToString(getpid()) +
    593       "-" + Uint64ToString(RandUint64());
    594   options.name_deprecated = &shared_mem_name;
    595   // Set a file mode creation mask that gives all permissions.
    596   ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
    597 
    598   EXPECT_TRUE(shared_memory.Create(options));
    599   // Clean-up the backing file name immediately, we don't need it.
    600   EXPECT_TRUE(shared_memory.Delete(shared_mem_name));
    601 
    602   int shm_fd = shared_memory.handle().fd;
    603   struct stat shm_stat;
    604   EXPECT_EQ(0, fstat(shm_fd, &shm_stat));
    605   // Neither the group, nor others should have been able to open the shared
    606   // memory file while its name existed.
    607   EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
    608   EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
    609 }
    610 #endif  // !defined(OS_ANDROID)
    611 
    612 #endif  // defined(OS_POSIX)
    613 
    614 // Map() will return addresses which are aligned to the platform page size, this
    615 // varies from platform to platform though.  Since we'd like to advertise a
    616 // minimum alignment that callers can count on, test for it here.
    617 TEST(SharedMemoryTest, MapMinimumAlignment) {
    618   static const int kDataSize = 8192;
    619 
    620   SharedMemory shared_memory;
    621   ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize));
    622   EXPECT_EQ(0U, reinterpret_cast<uintptr_t>(
    623       shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
    624   shared_memory.Close();
    625 }
    626 
    627 #if !defined(OS_IOS)  // iOS does not allow multiple processes.
    628 
    629 // On POSIX it is especially important we test shmem across processes,
    630 // not just across threads.  But the test is enabled on all platforms.
    631 class SharedMemoryProcessTest : public MultiProcessTest {
    632  public:
    633 
    634   static void CleanUp() {
    635     SharedMemory memory;
    636     memory.Delete(s_test_name_);
    637   }
    638 
    639   static int TaskTestMain() {
    640     int errors = 0;
    641 #if defined(OS_MACOSX)
    642     mac::ScopedNSAutoreleasePool pool;
    643 #endif
    644     const uint32 kDataSize = 1024;
    645     SharedMemory memory;
    646     bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize);
    647     EXPECT_TRUE(rv);
    648     if (rv != true)
    649       errors++;
    650     rv = memory.Map(kDataSize);
    651     EXPECT_TRUE(rv);
    652     if (rv != true)
    653       errors++;
    654     int *ptr = static_cast<int*>(memory.memory());
    655 
    656     for (int idx = 0; idx < 20; idx++) {
    657       memory.LockDeprecated();
    658       int i = (1 << 16) + idx;
    659       *ptr = i;
    660       PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
    661       if (*ptr != i)
    662         errors++;
    663       memory.UnlockDeprecated();
    664     }
    665 
    666     memory.Close();
    667     return errors;
    668   }
    669 
    670  private:
    671   static const char* const s_test_name_;
    672 };
    673 
    674 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem";
    675 
    676 TEST_F(SharedMemoryProcessTest, Tasks) {
    677   SharedMemoryProcessTest::CleanUp();
    678 
    679   ProcessHandle handles[kNumTasks];
    680   for (int index = 0; index < kNumTasks; ++index) {
    681     handles[index] = SpawnChild("SharedMemoryTestMain");
    682     ASSERT_TRUE(handles[index]);
    683   }
    684 
    685   int exit_code = 0;
    686   for (int index = 0; index < kNumTasks; ++index) {
    687     EXPECT_TRUE(WaitForExitCode(handles[index], &exit_code));
    688     EXPECT_EQ(0, exit_code);
    689   }
    690 
    691   SharedMemoryProcessTest::CleanUp();
    692 }
    693 
    694 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
    695   return SharedMemoryProcessTest::TaskTestMain();
    696 }
    697 
    698 #endif  // !OS_IOS
    699 
    700 }  // namespace base
    701