[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / base / shared_memory_unittest.cc
blobbd537692f4880febe1ce12dc9a18e91991296ca4
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
6 #if defined(OS_MACOSX)
7 #include "base/mac/scoped_nsautorelease_pool.h"
8 #endif
9 #include "base/memory/scoped_ptr.h"
10 #include "base/shared_memory.h"
11 #include "base/test/multiprocess_test.h"
12 #include "base/threading/platform_thread.h"
13 #include "base/time.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "testing/multiprocess_func_list.h"
17 #if defined(OS_MACOSX)
18 #include "base/mac/scoped_nsautorelease_pool.h"
19 #endif
21 #if defined(OS_POSIX)
22 #include <sys/mman.h>
23 #endif
25 static const int kNumThreads = 5;
26 static const int kNumTasks = 5;
28 namespace base {
30 namespace {
32 // Each thread will open the shared memory. Each thread will take a different 4
33 // byte int pointer, and keep changing it, with some small pauses in between.
34 // Verify that each thread's value in the shared memory is always correct.
35 class MultipleThreadMain : public PlatformThread::Delegate {
36 public:
37 explicit MultipleThreadMain(int16 id) : id_(id) {}
38 virtual ~MultipleThreadMain() {}
40 static void CleanUp() {
41 SharedMemory memory;
42 memory.Delete(s_test_name_);
45 // PlatformThread::Delegate interface.
46 virtual void ThreadMain() OVERRIDE {
47 #if defined(OS_MACOSX)
48 mac::ScopedNSAutoreleasePool pool;
49 #endif
50 const uint32 kDataSize = 1024;
51 SharedMemory memory;
52 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
53 EXPECT_TRUE(rv);
54 rv = memory.Map(kDataSize);
55 EXPECT_TRUE(rv);
56 int *ptr = static_cast<int*>(memory.memory()) + id_;
57 EXPECT_EQ(0, *ptr);
59 for (int idx = 0; idx < 100; idx++) {
60 *ptr = idx;
61 PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
62 EXPECT_EQ(*ptr, idx);
64 // Reset back to 0 for the next test that uses the same name.
65 *ptr = 0;
67 memory.Close();
70 private:
71 int16 id_;
73 static const char* const s_test_name_;
75 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
78 const char* const MultipleThreadMain::s_test_name_ =
79 "SharedMemoryOpenThreadTest";
81 // TODO(port):
82 // This test requires the ability to pass file descriptors between processes.
83 // We haven't done that yet in Chrome for POSIX.
84 #if defined(OS_WIN)
85 // Each thread will open the shared memory. Each thread will take the memory,
86 // and keep changing it while trying to lock it, with some small pauses in
87 // between. Verify that each thread's value in the shared memory is always
88 // correct.
89 class MultipleLockThread : public PlatformThread::Delegate {
90 public:
91 explicit MultipleLockThread(int id) : id_(id) {}
92 virtual ~MultipleLockThread() {}
94 // PlatformThread::Delegate interface.
95 virtual void ThreadMain() OVERRIDE {
96 const uint32 kDataSize = sizeof(int);
97 SharedMemoryHandle handle = NULL;
99 SharedMemory memory1;
100 EXPECT_TRUE(memory1.CreateNamed("SharedMemoryMultipleLockThreadTest",
101 true, kDataSize));
102 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle));
103 // TODO(paulg): Implement this once we have a posix version of
104 // SharedMemory::ShareToProcess.
105 EXPECT_TRUE(true);
108 SharedMemory memory2(handle, false);
109 EXPECT_TRUE(memory2.Map(kDataSize));
110 volatile int* const ptr = static_cast<int*>(memory2.memory());
112 for (int idx = 0; idx < 20; idx++) {
113 memory2.Lock();
114 int i = (id_ << 16) + idx;
115 *ptr = i;
116 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
117 EXPECT_EQ(*ptr, i);
118 memory2.Unlock();
121 memory2.Close();
124 private:
125 int id_;
127 DISALLOW_COPY_AND_ASSIGN(MultipleLockThread);
129 #endif
131 } // namespace
133 // Android doesn't support SharedMemory::Open/Delete/
134 // CreateNamed(openExisting=true)
135 #if !defined(OS_ANDROID)
136 TEST(SharedMemoryTest, OpenClose) {
137 const uint32 kDataSize = 1024;
138 std::string test_name = "SharedMemoryOpenCloseTest";
140 // Open two handles to a memory segment, confirm that they are mapped
141 // separately yet point to the same space.
142 SharedMemory memory1;
143 bool rv = memory1.Delete(test_name);
144 EXPECT_TRUE(rv);
145 rv = memory1.Delete(test_name);
146 EXPECT_TRUE(rv);
147 rv = memory1.Open(test_name, false);
148 EXPECT_FALSE(rv);
149 rv = memory1.CreateNamed(test_name, false, kDataSize);
150 EXPECT_TRUE(rv);
151 rv = memory1.Map(kDataSize);
152 EXPECT_TRUE(rv);
153 SharedMemory memory2;
154 rv = memory2.Open(test_name, false);
155 EXPECT_TRUE(rv);
156 rv = memory2.Map(kDataSize);
157 EXPECT_TRUE(rv);
158 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers.
160 // Make sure we don't segfault. (it actually happened!)
161 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
162 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));
164 // Write data to the first memory segment, verify contents of second.
165 memset(memory1.memory(), '1', kDataSize);
166 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
168 // Close the first memory segment, and verify the second has the right data.
169 memory1.Close();
170 char *start_ptr = static_cast<char *>(memory2.memory());
171 char *end_ptr = start_ptr + kDataSize;
172 for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
173 EXPECT_EQ(*ptr, '1');
175 // Close the second memory segment.
176 memory2.Close();
178 rv = memory1.Delete(test_name);
179 EXPECT_TRUE(rv);
180 rv = memory2.Delete(test_name);
181 EXPECT_TRUE(rv);
184 TEST(SharedMemoryTest, OpenExclusive) {
185 const uint32 kDataSize = 1024;
186 const uint32 kDataSize2 = 2048;
187 std::ostringstream test_name_stream;
188 test_name_stream << "SharedMemoryOpenExclusiveTest."
189 << Time::Now().ToDoubleT();
190 std::string test_name = test_name_stream.str();
192 // Open two handles to a memory segment and check that open_existing works
193 // as expected.
194 SharedMemory memory1;
195 bool rv = memory1.CreateNamed(test_name, false, kDataSize);
196 EXPECT_TRUE(rv);
198 // Memory1 knows it's size because it created it.
199 EXPECT_EQ(memory1.created_size(), kDataSize);
201 rv = memory1.Map(kDataSize);
202 EXPECT_TRUE(rv);
204 memset(memory1.memory(), 'G', kDataSize);
206 SharedMemory memory2;
207 // Should not be able to create if openExisting is false.
208 rv = memory2.CreateNamed(test_name, false, kDataSize2);
209 EXPECT_FALSE(rv);
211 // Should be able to create with openExisting true.
212 rv = memory2.CreateNamed(test_name, true, kDataSize2);
213 EXPECT_TRUE(rv);
215 // Memory2 shouldn't know the size because we didn't create it.
216 EXPECT_EQ(memory2.created_size(), 0U);
218 // We should be able to map the original size.
219 rv = memory2.Map(kDataSize);
220 EXPECT_TRUE(rv);
222 // Verify that opening memory2 didn't truncate or delete memory 1.
223 char *start_ptr = static_cast<char *>(memory2.memory());
224 char *end_ptr = start_ptr + kDataSize;
225 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
226 EXPECT_EQ(*ptr, 'G');
229 memory1.Close();
230 memory2.Close();
232 rv = memory1.Delete(test_name);
233 EXPECT_TRUE(rv);
235 #endif
237 // Create a set of N threads to each open a shared memory segment and write to
238 // it. Verify that they are always reading/writing consistent data.
239 TEST(SharedMemoryTest, MultipleThreads) {
240 MultipleThreadMain::CleanUp();
241 // On POSIX we have a problem when 2 threads try to create the shmem
242 // (a file) at exactly the same time, since create both creates the
243 // file and zerofills it. We solve the problem for this unit test
244 // (make it not flaky) by starting with 1 thread, then
245 // intentionally don't clean up its shmem before running with
246 // kNumThreads.
248 int threadcounts[] = { 1, kNumThreads };
249 for (size_t i = 0; i < arraysize(threadcounts); i++) {
250 int numthreads = threadcounts[i];
251 scoped_array<PlatformThreadHandle> thread_handles;
252 scoped_array<MultipleThreadMain*> thread_delegates;
254 thread_handles.reset(new PlatformThreadHandle[numthreads]);
255 thread_delegates.reset(new MultipleThreadMain*[numthreads]);
257 // Spawn the threads.
258 for (int16 index = 0; index < numthreads; index++) {
259 PlatformThreadHandle pth;
260 thread_delegates[index] = new MultipleThreadMain(index);
261 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
262 thread_handles[index] = pth;
265 // Wait for the threads to finish.
266 for (int index = 0; index < numthreads; index++) {
267 PlatformThread::Join(thread_handles[index]);
268 delete thread_delegates[index];
271 MultipleThreadMain::CleanUp();
274 // TODO(port): this test requires the MultipleLockThread class
275 // (defined above), which requires the ability to pass file
276 // descriptors between processes. We haven't done that yet in Chrome
277 // for POSIX.
278 #if defined(OS_WIN)
279 // Create a set of threads to each open a shared memory segment and write to it
280 // with the lock held. Verify that they are always reading/writing consistent
281 // data.
282 TEST(SharedMemoryTest, Lock) {
283 PlatformThreadHandle thread_handles[kNumThreads];
284 MultipleLockThread* thread_delegates[kNumThreads];
286 // Spawn the threads.
287 for (int index = 0; index < kNumThreads; ++index) {
288 PlatformThreadHandle pth;
289 thread_delegates[index] = new MultipleLockThread(index);
290 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
291 thread_handles[index] = pth;
294 // Wait for the threads to finish.
295 for (int index = 0; index < kNumThreads; ++index) {
296 PlatformThread::Join(thread_handles[index]);
297 delete thread_delegates[index];
300 #endif
302 // Allocate private (unique) shared memory with an empty string for a
303 // name. Make sure several of them don't point to the same thing as
304 // we might expect if the names are equal.
305 TEST(SharedMemoryTest, AnonymousPrivate) {
306 int i, j;
307 int count = 4;
308 bool rv;
309 const uint32 kDataSize = 8192;
311 scoped_array<SharedMemory> memories(new SharedMemory[count]);
312 scoped_array<int*> pointers(new int*[count]);
313 ASSERT_TRUE(memories.get());
314 ASSERT_TRUE(pointers.get());
316 for (i = 0; i < count; i++) {
317 rv = memories[i].CreateAndMapAnonymous(kDataSize);
318 EXPECT_TRUE(rv);
319 int *ptr = static_cast<int*>(memories[i].memory());
320 EXPECT_TRUE(ptr);
321 pointers[i] = ptr;
324 for (i = 0; i < count; i++) {
325 // zero out the first int in each except for i; for that one, make it 100.
326 for (j = 0; j < count; j++) {
327 if (i == j)
328 pointers[j][0] = 100;
329 else
330 pointers[j][0] = 0;
332 // make sure there is no bleeding of the 100 into the other pointers
333 for (j = 0; j < count; j++) {
334 if (i == j)
335 EXPECT_EQ(100, pointers[j][0]);
336 else
337 EXPECT_EQ(0, pointers[j][0]);
341 for (int i = 0; i < count; i++) {
342 memories[i].Close();
346 #if defined(OS_POSIX)
347 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
348 TEST(SharedMemoryTest, AnonymousExecutable) {
349 const uint32 kTestSize = 1 << 16;
351 SharedMemory shared_memory;
352 SharedMemoryCreateOptions options;
353 options.size = kTestSize;
354 options.executable = true;
356 EXPECT_TRUE(shared_memory.Create(options));
357 EXPECT_TRUE(shared_memory.Map(shared_memory.created_size()));
359 EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.created_size(),
360 PROT_READ | PROT_EXEC));
362 #endif
364 // Map() will return addresses which are aligned to the platform page size, this
365 // varies from platform to platform though. Since we'd like to advertise a
366 // minimum alignment that callers can count on, test for it here.
367 TEST(SharedMemoryTest, MapMinimumAlignment) {
368 static const int kDataSize = 8192;
370 SharedMemory shared_memory;
371 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize));
372 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>(
373 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
374 shared_memory.Close();
377 #if !defined(OS_IOS) // iOS does not allow multiple processes.
379 // On POSIX it is especially important we test shmem across processes,
380 // not just across threads. But the test is enabled on all platforms.
381 class SharedMemoryProcessTest : public MultiProcessTest {
382 public:
384 static void CleanUp() {
385 SharedMemory memory;
386 memory.Delete(s_test_name_);
389 static int TaskTestMain() {
390 int errors = 0;
391 #if defined(OS_MACOSX)
392 mac::ScopedNSAutoreleasePool pool;
393 #endif
394 const uint32 kDataSize = 1024;
395 SharedMemory memory;
396 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
397 EXPECT_TRUE(rv);
398 if (rv != true)
399 errors++;
400 rv = memory.Map(kDataSize);
401 EXPECT_TRUE(rv);
402 if (rv != true)
403 errors++;
404 int *ptr = static_cast<int*>(memory.memory());
406 for (int idx = 0; idx < 20; idx++) {
407 memory.Lock();
408 int i = (1 << 16) + idx;
409 *ptr = i;
410 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
411 if (*ptr != i)
412 errors++;
413 memory.Unlock();
416 memory.Close();
417 return errors;
420 private:
421 static const char* const s_test_name_;
424 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem";
426 TEST_F(SharedMemoryProcessTest, Tasks) {
427 SharedMemoryProcessTest::CleanUp();
429 ProcessHandle handles[kNumTasks];
430 for (int index = 0; index < kNumTasks; ++index) {
431 handles[index] = SpawnChild("SharedMemoryTestMain", false);
432 ASSERT_TRUE(handles[index]);
435 int exit_code = 0;
436 for (int index = 0; index < kNumTasks; ++index) {
437 EXPECT_TRUE(WaitForExitCode(handles[index], &exit_code));
438 EXPECT_EQ(0, exit_code);
441 SharedMemoryProcessTest::CleanUp();
444 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
445 return SharedMemoryProcessTest::TaskTestMain();
448 #endif // !OS_IOS
450 } // namespace base