[cros] Don't succeed if user has default profile picturewq
[chromium-blink-merge.git] / base / shared_memory_unittest.cc
blob330add4850779b28b6ec0b805c2bef6e2d2af309
1 // Copyright (c) 2011 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/mac/scoped_nsautorelease_pool.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/shared_memory.h"
9 #include "base/test/multiprocess_test.h"
10 #include "base/threading/platform_thread.h"
11 #include "base/time.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "testing/multiprocess_func_list.h"
15 static const int kNumThreads = 5;
16 static const int kNumTasks = 5;
18 namespace base {
20 namespace {
22 // Each thread will open the shared memory. Each thread will take a different 4
23 // byte int pointer, and keep changing it, with some small pauses in between.
24 // Verify that each thread's value in the shared memory is always correct.
25 class MultipleThreadMain : public PlatformThread::Delegate {
26 public:
27 explicit MultipleThreadMain(int16 id) : id_(id) {}
28 ~MultipleThreadMain() {}
30 static void CleanUp() {
31 SharedMemory memory;
32 memory.Delete(s_test_name_);
35 // PlatformThread::Delegate interface.
36 void ThreadMain() {
37 mac::ScopedNSAutoreleasePool pool; // noop if not OSX
38 const uint32 kDataSize = 1024;
39 SharedMemory memory;
40 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
41 EXPECT_TRUE(rv);
42 rv = memory.Map(kDataSize);
43 EXPECT_TRUE(rv);
44 int *ptr = static_cast<int*>(memory.memory()) + id_;
45 EXPECT_EQ(0, *ptr);
47 for (int idx = 0; idx < 100; idx++) {
48 *ptr = idx;
49 PlatformThread::Sleep(1); // Short wait.
50 EXPECT_EQ(*ptr, idx);
52 // Reset back to 0 for the next test that uses the same name.
53 *ptr = 0;
55 memory.Close();
58 private:
59 int16 id_;
61 static const char* const s_test_name_;
63 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
66 const char* const MultipleThreadMain::s_test_name_ =
67 "SharedMemoryOpenThreadTest";
69 // TODO(port):
70 // This test requires the ability to pass file descriptors between processes.
71 // We haven't done that yet in Chrome for POSIX.
72 #if defined(OS_WIN)
73 // Each thread will open the shared memory. Each thread will take the memory,
74 // and keep changing it while trying to lock it, with some small pauses in
75 // between. Verify that each thread's value in the shared memory is always
76 // correct.
77 class MultipleLockThread : public PlatformThread::Delegate {
78 public:
79 explicit MultipleLockThread(int id) : id_(id) {}
80 ~MultipleLockThread() {}
82 // PlatformThread::Delegate interface.
83 void ThreadMain() {
84 const uint32 kDataSize = sizeof(int);
85 SharedMemoryHandle handle = NULL;
87 SharedMemory memory1;
88 EXPECT_TRUE(memory1.CreateNamed("SharedMemoryMultipleLockThreadTest",
89 true, kDataSize));
90 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle));
91 // TODO(paulg): Implement this once we have a posix version of
92 // SharedMemory::ShareToProcess.
93 EXPECT_TRUE(true);
96 SharedMemory memory2(handle, false);
97 EXPECT_TRUE(memory2.Map(kDataSize));
98 volatile int* const ptr = static_cast<int*>(memory2.memory());
100 for (int idx = 0; idx < 20; idx++) {
101 memory2.Lock();
102 int i = (id_ << 16) + idx;
103 *ptr = i;
104 PlatformThread::Sleep(1); // Short wait.
105 EXPECT_EQ(*ptr, i);
106 memory2.Unlock();
109 memory2.Close();
112 private:
113 int id_;
115 DISALLOW_COPY_AND_ASSIGN(MultipleLockThread);
117 #endif
119 } // namespace
121 TEST(SharedMemoryTest, OpenClose) {
122 const uint32 kDataSize = 1024;
123 std::string test_name = "SharedMemoryOpenCloseTest";
125 // Open two handles to a memory segment, confirm that they are mapped
126 // separately yet point to the same space.
127 SharedMemory memory1;
128 bool rv = memory1.Delete(test_name);
129 EXPECT_TRUE(rv);
130 rv = memory1.Delete(test_name);
131 EXPECT_TRUE(rv);
132 rv = memory1.Open(test_name, false);
133 EXPECT_FALSE(rv);
134 rv = memory1.CreateNamed(test_name, false, kDataSize);
135 EXPECT_TRUE(rv);
136 rv = memory1.Map(kDataSize);
137 EXPECT_TRUE(rv);
138 SharedMemory memory2;
139 rv = memory2.Open(test_name, false);
140 EXPECT_TRUE(rv);
141 rv = memory2.Map(kDataSize);
142 EXPECT_TRUE(rv);
143 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers.
145 // Make sure we don't segfault. (it actually happened!)
146 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
147 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));
149 // Write data to the first memory segment, verify contents of second.
150 memset(memory1.memory(), '1', kDataSize);
151 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
153 // Close the first memory segment, and verify the second has the right data.
154 memory1.Close();
155 char *start_ptr = static_cast<char *>(memory2.memory());
156 char *end_ptr = start_ptr + kDataSize;
157 for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
158 EXPECT_EQ(*ptr, '1');
160 // Close the second memory segment.
161 memory2.Close();
163 rv = memory1.Delete(test_name);
164 EXPECT_TRUE(rv);
165 rv = memory2.Delete(test_name);
166 EXPECT_TRUE(rv);
169 TEST(SharedMemoryTest, OpenExclusive) {
170 const uint32 kDataSize = 1024;
171 const uint32 kDataSize2 = 2048;
172 std::ostringstream test_name_stream;
173 test_name_stream << "SharedMemoryOpenExclusiveTest."
174 << Time::Now().ToDoubleT();
175 std::string test_name = test_name_stream.str();
177 // Open two handles to a memory segment and check that open_existing works
178 // as expected.
179 SharedMemory memory1;
180 bool rv = memory1.CreateNamed(test_name, false, kDataSize);
181 EXPECT_TRUE(rv);
183 // Memory1 knows it's size because it created it.
184 EXPECT_EQ(memory1.created_size(), kDataSize);
186 rv = memory1.Map(kDataSize);
187 EXPECT_TRUE(rv);
189 memset(memory1.memory(), 'G', kDataSize);
191 SharedMemory memory2;
192 // Should not be able to create if openExisting is false.
193 rv = memory2.CreateNamed(test_name, false, kDataSize2);
194 EXPECT_FALSE(rv);
196 // Should be able to create with openExisting true.
197 rv = memory2.CreateNamed(test_name, true, kDataSize2);
198 EXPECT_TRUE(rv);
200 // Memory2 shouldn't know the size because we didn't create it.
201 EXPECT_EQ(memory2.created_size(), 0U);
203 // We should be able to map the original size.
204 rv = memory2.Map(kDataSize);
205 EXPECT_TRUE(rv);
207 // Verify that opening memory2 didn't truncate or delete memory 1.
208 char *start_ptr = static_cast<char *>(memory2.memory());
209 char *end_ptr = start_ptr + kDataSize;
210 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
211 EXPECT_EQ(*ptr, 'G');
214 memory1.Close();
215 memory2.Close();
217 rv = memory1.Delete(test_name);
218 EXPECT_TRUE(rv);
221 // Create a set of N threads to each open a shared memory segment and write to
222 // it. Verify that they are always reading/writing consistent data.
223 TEST(SharedMemoryTest, MultipleThreads) {
224 MultipleThreadMain::CleanUp();
225 // On POSIX we have a problem when 2 threads try to create the shmem
226 // (a file) at exactly the same time, since create both creates the
227 // file and zerofills it. We solve the problem for this unit test
228 // (make it not flaky) by starting with 1 thread, then
229 // intentionally don't clean up its shmem before running with
230 // kNumThreads.
232 int threadcounts[] = { 1, kNumThreads };
233 for (size_t i = 0; i < arraysize(threadcounts); i++) {
234 int numthreads = threadcounts[i];
235 scoped_array<PlatformThreadHandle> thread_handles;
236 scoped_array<MultipleThreadMain*> thread_delegates;
238 thread_handles.reset(new PlatformThreadHandle[numthreads]);
239 thread_delegates.reset(new MultipleThreadMain*[numthreads]);
241 // Spawn the threads.
242 for (int16 index = 0; index < numthreads; index++) {
243 PlatformThreadHandle pth;
244 thread_delegates[index] = new MultipleThreadMain(index);
245 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
246 thread_handles[index] = pth;
249 // Wait for the threads to finish.
250 for (int index = 0; index < numthreads; index++) {
251 PlatformThread::Join(thread_handles[index]);
252 delete thread_delegates[index];
255 MultipleThreadMain::CleanUp();
258 // TODO(port): this test requires the MultipleLockThread class
259 // (defined above), which requires the ability to pass file
260 // descriptors between processes. We haven't done that yet in Chrome
261 // for POSIX.
262 #if defined(OS_WIN)
263 // Create a set of threads to each open a shared memory segment and write to it
264 // with the lock held. Verify that they are always reading/writing consistent
265 // data.
266 TEST(SharedMemoryTest, Lock) {
267 PlatformThreadHandle thread_handles[kNumThreads];
268 MultipleLockThread* thread_delegates[kNumThreads];
270 // Spawn the threads.
271 for (int index = 0; index < kNumThreads; ++index) {
272 PlatformThreadHandle pth;
273 thread_delegates[index] = new MultipleLockThread(index);
274 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
275 thread_handles[index] = pth;
278 // Wait for the threads to finish.
279 for (int index = 0; index < kNumThreads; ++index) {
280 PlatformThread::Join(thread_handles[index]);
281 delete thread_delegates[index];
284 #endif
286 // Allocate private (unique) shared memory with an empty string for a
287 // name. Make sure several of them don't point to the same thing as
288 // we might expect if the names are equal.
289 TEST(SharedMemoryTest, AnonymousPrivate) {
290 int i, j;
291 int count = 4;
292 bool rv;
293 const uint32 kDataSize = 8192;
295 scoped_array<SharedMemory> memories(new SharedMemory[count]);
296 scoped_array<int*> pointers(new int*[count]);
297 ASSERT_TRUE(memories.get());
298 ASSERT_TRUE(pointers.get());
300 for (i = 0; i < count; i++) {
301 rv = memories[i].CreateAndMapAnonymous(kDataSize);
302 EXPECT_TRUE(rv);
303 int *ptr = static_cast<int*>(memories[i].memory());
304 EXPECT_TRUE(ptr);
305 pointers[i] = ptr;
308 for (i = 0; i < count; i++) {
309 // zero out the first int in each except for i; for that one, make it 100.
310 for (j = 0; j < count; j++) {
311 if (i == j)
312 pointers[j][0] = 100;
313 else
314 pointers[j][0] = 0;
316 // make sure there is no bleeding of the 100 into the other pointers
317 for (j = 0; j < count; j++) {
318 if (i == j)
319 EXPECT_EQ(100, pointers[j][0]);
320 else
321 EXPECT_EQ(0, pointers[j][0]);
325 for (int i = 0; i < count; i++) {
326 memories[i].Close();
330 // On POSIX it is especially important we test shmem across processes,
331 // not just across threads. But the test is enabled on all platforms.
332 class SharedMemoryProcessTest : public MultiProcessTest {
333 public:
335 static void CleanUp() {
336 SharedMemory memory;
337 memory.Delete(s_test_name_);
340 static int TaskTestMain() {
341 int errors = 0;
342 mac::ScopedNSAutoreleasePool pool; // noop if not OSX
343 const uint32 kDataSize = 1024;
344 SharedMemory memory;
345 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
346 EXPECT_TRUE(rv);
347 if (rv != true)
348 errors++;
349 rv = memory.Map(kDataSize);
350 EXPECT_TRUE(rv);
351 if (rv != true)
352 errors++;
353 int *ptr = static_cast<int*>(memory.memory());
355 for (int idx = 0; idx < 20; idx++) {
356 memory.Lock();
357 int i = (1 << 16) + idx;
358 *ptr = i;
359 PlatformThread::Sleep(10); // Short wait.
360 if (*ptr != i)
361 errors++;
362 memory.Unlock();
365 memory.Close();
366 return errors;
369 private:
370 static const char* const s_test_name_;
373 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem";
376 #if defined(OS_MACOSX)
377 #define MAYBE_Tasks FLAKY_Tasks
378 #else
379 #define MAYBE_Tasks Tasks
380 #endif
382 TEST_F(SharedMemoryProcessTest, MAYBE_Tasks) {
383 SharedMemoryProcessTest::CleanUp();
385 ProcessHandle handles[kNumTasks];
386 for (int index = 0; index < kNumTasks; ++index) {
387 handles[index] = SpawnChild("SharedMemoryTestMain", false);
388 ASSERT_TRUE(handles[index]);
391 int exit_code = 0;
392 for (int index = 0; index < kNumTasks; ++index) {
393 EXPECT_TRUE(WaitForExitCode(handles[index], &exit_code));
394 EXPECT_TRUE(exit_code == 0);
397 SharedMemoryProcessTest::CleanUp();
400 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
401 return SharedMemoryProcessTest::TaskTestMain();
404 } // namespace base