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
35static const int kNumThreads = 5;
36#if !defined(OS_IOS)  // iOS does not allow multiple processes.
37static const int kNumTasks = 5;
38#endif
39
40namespace base {
41
42namespace {
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.
47class 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
90const 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.
101class 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)
148TEST(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
196TEST(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.
265TEST(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.
308TEST(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.
331TEST(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
372TEST(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
462TEST(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
488TEST(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
514TEST(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.
531TEST(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.
553class 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.
565TEST(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.
586TEST(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.
617TEST(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.
631class 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
674const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem";
675
676TEST_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
694MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
695  return SharedMemoryProcessTest::TaskTestMain();
696}
697
698#endif  // !OS_IOS
699
700}  // namespace base
701