1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h"
6731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/mac/scoped_nsautorelease_pool.h"
7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h"
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/shared_memory.h"
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/test/multiprocess_test.h"
103f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/platform_thread.h"
11513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#include "base/time.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "testing/gtest/include/gtest/gtest.h"
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "testing/multiprocess_func_list.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kNumThreads = 5;
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kNumTasks = 5;
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base {
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace {
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Each thread will open the shared memory.  Each thread will take a different 4
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// byte int pointer, and keep changing it, with some small pauses in between.
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Verify that each thread's value in the shared memory is always correct.
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MultipleThreadMain : public PlatformThread::Delegate {
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit MultipleThreadMain(int16 id) : id_(id) {}
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~MultipleThreadMain() {}
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void CleanUp() {
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SharedMemory memory;
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memory.Delete(s_test_name_);
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // PlatformThread::Delegate interface.
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void ThreadMain() {
37731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    mac::ScopedNSAutoreleasePool pool;  // noop if not OSX
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const uint32 kDataSize = 1024;
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SharedMemory memory;
40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(rv);
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = memory.Map(kDataSize);
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(rv);
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int *ptr = static_cast<int*>(memory.memory()) + id_;
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(*ptr, 0);
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int idx = 0; idx < 100; idx++) {
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *ptr = idx;
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PlatformThread::Sleep(1);  // Short wait.
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(*ptr, idx);
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memory.Close();
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int16 id_;
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char* const s_test_name_;
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char* const MultipleThreadMain::s_test_name_ =
653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    "SharedMemoryOpenThreadTest";
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(port):
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This test requires the ability to pass file descriptors between processes.
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We haven't done that yet in Chrome for POSIX.
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Each thread will open the shared memory.  Each thread will take the memory,
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and keep changing it while trying to lock it, with some small pauses in
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// between. Verify that each thread's value in the shared memory is always
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// correct.
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass MultipleLockThread : public PlatformThread::Delegate {
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  explicit MultipleLockThread(int id) : id_(id) {}
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ~MultipleLockThread() {}
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // PlatformThread::Delegate interface.
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void ThreadMain() {
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const uint32 kDataSize = sizeof(int);
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SharedMemoryHandle handle = NULL;
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    {
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      SharedMemory memory1;
86513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch      EXPECT_TRUE(memory1.CreateNamed("SharedMemoryMultipleLockThreadTest",
87513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 true, kDataSize));
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle));
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // TODO(paulg): Implement this once we have a posix version of
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // SharedMemory::ShareToProcess.
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(true);
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SharedMemory memory2(handle, false);
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(memory2.Map(kDataSize));
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    volatile int* const ptr = static_cast<int*>(memory2.memory());
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int idx = 0; idx < 20; idx++) {
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      memory2.Lock();
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int i = (id_ << 16) + idx;
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *ptr = i;
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PlatformThread::Sleep(1);  // Short wait.
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_EQ(*ptr, i);
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      memory2.Unlock();
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memory2.Close();
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int id_;
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DISALLOW_COPY_AND_ASSIGN(MultipleLockThread);
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(SharedMemoryTest, OpenClose) {
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const uint32 kDataSize = 1024;
1213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string test_name = "SharedMemoryOpenCloseTest";
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Open two handles to a memory segment, confirm that they are mapped
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // separately yet point to the same space.
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SharedMemory memory1;
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool rv = memory1.Delete(test_name);
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv);
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = memory1.Delete(test_name);
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv);
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = memory1.Open(test_name, false);
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_FALSE(rv);
132513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  rv = memory1.CreateNamed(test_name, false, kDataSize);
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv);
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = memory1.Map(kDataSize);
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv);
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SharedMemory memory2;
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = memory2.Open(test_name, false);
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv);
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = memory2.Map(kDataSize);
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv);
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_NE(memory1.memory(), memory2.memory());  // Compare the pointers.
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Make sure we don't segfault. (it actually happened!)
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Write data to the first memory segment, verify contents of second.
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memset(memory1.memory(), '1', kDataSize);
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Close the first memory segment, and verify the second has the right data.
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memory1.Close();
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char *start_ptr = static_cast<char *>(memory2.memory());
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char *end_ptr = start_ptr + kDataSize;
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_EQ(*ptr, '1');
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Close the second memory segment.
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memory2.Close();
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = memory1.Delete(test_name);
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv);
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  rv = memory2.Delete(test_name);
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  EXPECT_TRUE(rv);
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
167513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTEST(SharedMemoryTest, OpenExclusive) {
168513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const uint32 kDataSize = 1024;
169513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const uint32 kDataSize2 = 2048;
170513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::ostringstream test_name_stream;
171513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  test_name_stream << "SharedMemoryOpenExclusiveTest."
172513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                   << Time::Now().ToDoubleT();
173513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  std::string test_name = test_name_stream.str();
174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Open two handles to a memory segment and check that open_existing works
176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // as expected.
177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  SharedMemory memory1;
178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  bool rv = memory1.CreateNamed(test_name, false, kDataSize);
179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_TRUE(rv);
180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Memory1 knows it's size because it created it.
182513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(memory1.created_size(), kDataSize);
183513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
184513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  rv = memory1.Map(kDataSize);
185513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_TRUE(rv);
186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  memset(memory1.memory(), 'G', kDataSize);
188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
189513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  SharedMemory memory2;
190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Should not be able to create if openExisting is false.
191513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  rv = memory2.CreateNamed(test_name, false, kDataSize2);
192513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_FALSE(rv);
193513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
194513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Should be able to create with openExisting true.
195513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  rv = memory2.CreateNamed(test_name, true, kDataSize2);
196513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_TRUE(rv);
197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Memory2 shouldn't know the size because we didn't create it.
199513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_EQ(memory2.created_size(), 0U);
200513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
201513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // We should be able to map the original size.
202513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  rv = memory2.Map(kDataSize);
203513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_TRUE(rv);
204513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
205513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Verify that opening memory2 didn't truncate or delete memory 1.
206513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  char *start_ptr = static_cast<char *>(memory2.memory());
207513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  char *end_ptr = start_ptr + kDataSize;
208513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
209513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    EXPECT_EQ(*ptr, 'G');
210513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
211513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
212513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  memory1.Close();
213513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  memory2.Close();
214513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
215513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  rv = memory1.Delete(test_name);
216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  EXPECT_TRUE(rv);
217513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Create a set of N threads to each open a shared memory segment and write to
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// it. Verify that they are always reading/writing consistent data.
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(SharedMemoryTest, MultipleThreads) {
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MultipleThreadMain::CleanUp();
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // On POSIX we have a problem when 2 threads try to create the shmem
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // (a file) at exactly the same time, since create both creates the
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // file and zerofills it.  We solve the problem for this unit test
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // (make it not flaky) by starting with 1 thread, then
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // intentionally don't clean up its shmem before running with
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // kNumThreads.
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int threadcounts[] = { 1, kNumThreads };
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < sizeof(threadcounts) / sizeof(threadcounts); i++) {
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int numthreads = threadcounts[i];
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    scoped_array<PlatformThreadHandle> thread_handles;
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    scoped_array<MultipleThreadMain*> thread_delegates;
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    thread_handles.reset(new PlatformThreadHandle[numthreads]);
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    thread_delegates.reset(new MultipleThreadMain*[numthreads]);
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Spawn the threads.
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int16 index = 0; index < numthreads; index++) {
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PlatformThreadHandle pth;
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      thread_delegates[index] = new MultipleThreadMain(index);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      thread_handles[index] = pth;
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Wait for the threads to finish.
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int index = 0; index < numthreads; index++) {
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PlatformThread::Join(thread_handles[index]);
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      delete thread_delegates[index];
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MultipleThreadMain::CleanUp();
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(port): this test requires the MultipleLockThread class
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// (defined above), which requires the ability to pass file
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// descriptors between processes.  We haven't done that yet in Chrome
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// for POSIX.
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Create a set of threads to each open a shared memory segment and write to it
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// with the lock held. Verify that they are always reading/writing consistent
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// data.
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(SharedMemoryTest, Lock) {
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  PlatformThreadHandle thread_handles[kNumThreads];
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MultipleLockThread* thread_delegates[kNumThreads];
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Spawn the threads.
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int index = 0; index < kNumThreads; ++index) {
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PlatformThreadHandle pth;
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    thread_delegates[index] = new MultipleLockThread(index);
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    thread_handles[index] = pth;
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Wait for the threads to finish.
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int index = 0; index < kNumThreads; ++index) {
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    PlatformThread::Join(thread_handles[index]);
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete thread_delegates[index];
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Allocate private (unique) shared memory with an empty string for a
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// name.  Make sure several of them don't point to the same thing as
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// we might expect if the names are equal.
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTEST(SharedMemoryTest, AnonymousPrivate) {
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int i, j;
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int count = 4;
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool rv;
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const uint32 kDataSize = 8192;
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_array<SharedMemory> memories(new SharedMemory[count]);
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_array<int*> pointers(new int*[count]);
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(memories.get());
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ASSERT_TRUE(pointers.get());
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (i = 0; i < count; i++) {
299513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    rv = memories[i].CreateAndMapAnonymous(kDataSize);
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(rv);
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int *ptr = static_cast<int*>(memories[i].memory());
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(ptr);
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    pointers[i] = ptr;
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (i = 0; i < count; i++) {
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // zero out the first int in each except for i; for that one, make it 100.
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (j = 0; j < count; j++) {
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (i == j)
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pointers[j][0] = 100;
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      else
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        pointers[j][0] = 0;
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // make sure there is no bleeding of the 100 into the other pointers
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (j = 0; j < count; j++) {
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (i == j)
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        EXPECT_EQ(100, pointers[j][0]);
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      else
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        EXPECT_EQ(0, pointers[j][0]);
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < count; i++) {
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memories[i].Close();
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// On POSIX it is especially important we test shmem across processes,
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// not just across threads.  But the test is enabled on all platforms.
3303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenclass SharedMemoryProcessTest : public MultiProcessTest {
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void CleanUp() {
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SharedMemory memory;
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memory.Delete(s_test_name_);
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static int TaskTestMain() {
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int errors = 0;
340731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    mac::ScopedNSAutoreleasePool pool;  // noop if not OSX
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const uint32 kDataSize = 1024;
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SharedMemory memory;
343513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(rv);
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv != true)
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      errors++;
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = memory.Map(kDataSize);
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(rv);
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv != true)
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      errors++;
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    int *ptr = static_cast<int*>(memory.memory());
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    for (int idx = 0; idx < 20; idx++) {
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      memory.Lock();
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      int i = (1 << 16) + idx;
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      *ptr = i;
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      PlatformThread::Sleep(10);  // Short wait.
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (*ptr != i)
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        errors++;
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      memory.Unlock();
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    memory.Close();
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return errors;
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
3683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static const char* const s_test_name_;
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst char* const SharedMemoryProcessTest::s_test_name_ = "MPMem";
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
374513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(OS_MACOSX)
375513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#define MAYBE_Tasks FLAKY_Tasks
376513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#else
377513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#define MAYBE_Tasks Tasks
378513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif
379513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
380513209b27ff55e2841eac0e4120199c23acce758Ben MurdochTEST_F(SharedMemoryProcessTest, MAYBE_Tasks) {
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SharedMemoryProcessTest::CleanUp();
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3833f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  ProcessHandle handles[kNumTasks];
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int index = 0; index < kNumTasks; ++index) {
3853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    handles[index] = SpawnChild("SharedMemoryTestMain", false);
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int exit_code = 0;
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int index = 0; index < kNumTasks; ++index) {
3903f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen    EXPECT_TRUE(WaitForExitCode(handles[index], &exit_code));
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    EXPECT_TRUE(exit_code == 0);
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SharedMemoryProcessTest::CleanUp();
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return SharedMemoryProcessTest::TaskTestMain();
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace base
402