Move media/base/simd/x86inc.asm to third_party/x86inc
[chromium-blink-merge.git] / base / shared_memory_unittest.cc
blob3f832486c1fb0c81f44a4b4d704a6908265638a8
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/sys_info.h"
12 #include "base/test/multiprocess_test.h"
13 #include "base/threading/platform_thread.h"
14 #include "base/time.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "testing/multiprocess_func_list.h"
18 #if defined(OS_MACOSX)
19 #include "base/mac/scoped_nsautorelease_pool.h"
20 #endif
22 #if defined(OS_POSIX)
23 #include <sys/mman.h>
24 #endif
26 static const int kNumThreads = 5;
27 static const int kNumTasks = 5;
29 namespace base {
31 namespace {
33 // Each thread will open the shared memory. Each thread will take a different 4
34 // byte int pointer, and keep changing it, with some small pauses in between.
35 // Verify that each thread's value in the shared memory is always correct.
36 class MultipleThreadMain : public PlatformThread::Delegate {
37 public:
38 explicit MultipleThreadMain(int16 id) : id_(id) {}
39 virtual ~MultipleThreadMain() {}
41 static void CleanUp() {
42 SharedMemory memory;
43 memory.Delete(s_test_name_);
46 // PlatformThread::Delegate interface.
47 virtual void ThreadMain() OVERRIDE {
48 #if defined(OS_MACOSX)
49 mac::ScopedNSAutoreleasePool pool;
50 #endif
51 const uint32 kDataSize = 1024;
52 SharedMemory memory;
53 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
54 EXPECT_TRUE(rv);
55 rv = memory.Map(kDataSize);
56 EXPECT_TRUE(rv);
57 int *ptr = static_cast<int*>(memory.memory()) + id_;
58 EXPECT_EQ(0, *ptr);
60 for (int idx = 0; idx < 100; idx++) {
61 *ptr = idx;
62 PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
63 EXPECT_EQ(*ptr, idx);
65 // Reset back to 0 for the next test that uses the same name.
66 *ptr = 0;
68 memory.Close();
71 private:
72 int16 id_;
74 static const char* const s_test_name_;
76 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
79 const char* const MultipleThreadMain::s_test_name_ =
80 "SharedMemoryOpenThreadTest";
82 // TODO(port):
83 // This test requires the ability to pass file descriptors between processes.
84 // We haven't done that yet in Chrome for POSIX.
85 #if defined(OS_WIN)
86 // Each thread will open the shared memory. Each thread will take the memory,
87 // and keep changing it while trying to lock it, with some small pauses in
88 // between. Verify that each thread's value in the shared memory is always
89 // correct.
90 class MultipleLockThread : public PlatformThread::Delegate {
91 public:
92 explicit MultipleLockThread(int id) : id_(id) {}
93 virtual ~MultipleLockThread() {}
95 // PlatformThread::Delegate interface.
96 virtual void ThreadMain() OVERRIDE {
97 const uint32 kDataSize = sizeof(int);
98 SharedMemoryHandle handle = NULL;
100 SharedMemory memory1;
101 EXPECT_TRUE(memory1.CreateNamed("SharedMemoryMultipleLockThreadTest",
102 true, kDataSize));
103 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle));
104 // TODO(paulg): Implement this once we have a posix version of
105 // SharedMemory::ShareToProcess.
106 EXPECT_TRUE(true);
109 SharedMemory memory2(handle, false);
110 EXPECT_TRUE(memory2.Map(kDataSize));
111 volatile int* const ptr = static_cast<int*>(memory2.memory());
113 for (int idx = 0; idx < 20; idx++) {
114 memory2.Lock();
115 int i = (id_ << 16) + idx;
116 *ptr = i;
117 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
118 EXPECT_EQ(*ptr, i);
119 memory2.Unlock();
122 memory2.Close();
125 private:
126 int id_;
128 DISALLOW_COPY_AND_ASSIGN(MultipleLockThread);
130 #endif
132 } // namespace
134 // Android doesn't support SharedMemory::Open/Delete/
135 // CreateNamed(openExisting=true)
136 #if !defined(OS_ANDROID)
137 TEST(SharedMemoryTest, OpenClose) {
138 const uint32 kDataSize = 1024;
139 std::string test_name = "SharedMemoryOpenCloseTest";
141 // Open two handles to a memory segment, confirm that they are mapped
142 // separately yet point to the same space.
143 SharedMemory memory1;
144 bool rv = memory1.Delete(test_name);
145 EXPECT_TRUE(rv);
146 rv = memory1.Delete(test_name);
147 EXPECT_TRUE(rv);
148 rv = memory1.Open(test_name, false);
149 EXPECT_FALSE(rv);
150 rv = memory1.CreateNamed(test_name, false, kDataSize);
151 EXPECT_TRUE(rv);
152 rv = memory1.Map(kDataSize);
153 EXPECT_TRUE(rv);
154 SharedMemory memory2;
155 rv = memory2.Open(test_name, false);
156 EXPECT_TRUE(rv);
157 rv = memory2.Map(kDataSize);
158 EXPECT_TRUE(rv);
159 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers.
161 // Make sure we don't segfault. (it actually happened!)
162 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
163 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));
165 // Write data to the first memory segment, verify contents of second.
166 memset(memory1.memory(), '1', kDataSize);
167 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
169 // Close the first memory segment, and verify the second has the right data.
170 memory1.Close();
171 char *start_ptr = static_cast<char *>(memory2.memory());
172 char *end_ptr = start_ptr + kDataSize;
173 for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
174 EXPECT_EQ(*ptr, '1');
176 // Close the second memory segment.
177 memory2.Close();
179 rv = memory1.Delete(test_name);
180 EXPECT_TRUE(rv);
181 rv = memory2.Delete(test_name);
182 EXPECT_TRUE(rv);
185 TEST(SharedMemoryTest, OpenExclusive) {
186 const uint32 kDataSize = 1024;
187 const uint32 kDataSize2 = 2048;
188 std::ostringstream test_name_stream;
189 test_name_stream << "SharedMemoryOpenExclusiveTest."
190 << Time::Now().ToDoubleT();
191 std::string test_name = test_name_stream.str();
193 // Open two handles to a memory segment and check that open_existing works
194 // as expected.
195 SharedMemory memory1;
196 bool rv = memory1.CreateNamed(test_name, false, kDataSize);
197 EXPECT_TRUE(rv);
199 // Memory1 knows it's size because it created it.
200 EXPECT_EQ(memory1.created_size(), kDataSize);
202 rv = memory1.Map(kDataSize);
203 EXPECT_TRUE(rv);
205 memset(memory1.memory(), 'G', kDataSize);
207 SharedMemory memory2;
208 // Should not be able to create if openExisting is false.
209 rv = memory2.CreateNamed(test_name, false, kDataSize2);
210 EXPECT_FALSE(rv);
212 // Should be able to create with openExisting true.
213 rv = memory2.CreateNamed(test_name, true, kDataSize2);
214 EXPECT_TRUE(rv);
216 // Memory2 shouldn't know the size because we didn't create it.
217 EXPECT_EQ(memory2.created_size(), 0U);
219 // We should be able to map the original size.
220 rv = memory2.Map(kDataSize);
221 EXPECT_TRUE(rv);
223 // Verify that opening memory2 didn't truncate or delete memory 1.
224 char *start_ptr = static_cast<char *>(memory2.memory());
225 char *end_ptr = start_ptr + kDataSize;
226 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
227 EXPECT_EQ(*ptr, 'G');
230 memory1.Close();
231 memory2.Close();
233 rv = memory1.Delete(test_name);
234 EXPECT_TRUE(rv);
236 #endif
238 // Create a set of N threads to each open a shared memory segment and write to
239 // it. Verify that they are always reading/writing consistent data.
240 TEST(SharedMemoryTest, MultipleThreads) {
241 MultipleThreadMain::CleanUp();
242 // On POSIX we have a problem when 2 threads try to create the shmem
243 // (a file) at exactly the same time, since create both creates the
244 // file and zerofills it. We solve the problem for this unit test
245 // (make it not flaky) by starting with 1 thread, then
246 // intentionally don't clean up its shmem before running with
247 // kNumThreads.
249 int threadcounts[] = { 1, kNumThreads };
250 for (size_t i = 0; i < arraysize(threadcounts); i++) {
251 int numthreads = threadcounts[i];
252 scoped_ptr<PlatformThreadHandle[]> thread_handles;
253 scoped_ptr<MultipleThreadMain*[]> thread_delegates;
255 thread_handles.reset(new PlatformThreadHandle[numthreads]);
256 thread_delegates.reset(new MultipleThreadMain*[numthreads]);
258 // Spawn the threads.
259 for (int16 index = 0; index < numthreads; index++) {
260 PlatformThreadHandle pth;
261 thread_delegates[index] = new MultipleThreadMain(index);
262 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
263 thread_handles[index] = pth;
266 // Wait for the threads to finish.
267 for (int index = 0; index < numthreads; index++) {
268 PlatformThread::Join(thread_handles[index]);
269 delete thread_delegates[index];
272 MultipleThreadMain::CleanUp();
275 // TODO(port): this test requires the MultipleLockThread class
276 // (defined above), which requires the ability to pass file
277 // descriptors between processes. We haven't done that yet in Chrome
278 // for POSIX.
279 #if defined(OS_WIN)
280 // Create a set of threads to each open a shared memory segment and write to it
281 // with the lock held. Verify that they are always reading/writing consistent
282 // data.
283 TEST(SharedMemoryTest, Lock) {
284 PlatformThreadHandle thread_handles[kNumThreads];
285 MultipleLockThread* thread_delegates[kNumThreads];
287 // Spawn the threads.
288 for (int index = 0; index < kNumThreads; ++index) {
289 PlatformThreadHandle pth;
290 thread_delegates[index] = new MultipleLockThread(index);
291 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
292 thread_handles[index] = pth;
295 // Wait for the threads to finish.
296 for (int index = 0; index < kNumThreads; ++index) {
297 PlatformThread::Join(thread_handles[index]);
298 delete thread_delegates[index];
301 #endif
303 // Allocate private (unique) shared memory with an empty string for a
304 // name. Make sure several of them don't point to the same thing as
305 // we might expect if the names are equal.
306 TEST(SharedMemoryTest, AnonymousPrivate) {
307 int i, j;
308 int count = 4;
309 bool rv;
310 const uint32 kDataSize = 8192;
312 scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]);
313 scoped_ptr<int*[]> pointers(new int*[count]);
314 ASSERT_TRUE(memories.get());
315 ASSERT_TRUE(pointers.get());
317 for (i = 0; i < count; i++) {
318 rv = memories[i].CreateAndMapAnonymous(kDataSize);
319 EXPECT_TRUE(rv);
320 int *ptr = static_cast<int*>(memories[i].memory());
321 EXPECT_TRUE(ptr);
322 pointers[i] = ptr;
325 for (i = 0; i < count; i++) {
326 // zero out the first int in each except for i; for that one, make it 100.
327 for (j = 0; j < count; j++) {
328 if (i == j)
329 pointers[j][0] = 100;
330 else
331 pointers[j][0] = 0;
333 // make sure there is no bleeding of the 100 into the other pointers
334 for (j = 0; j < count; j++) {
335 if (i == j)
336 EXPECT_EQ(100, pointers[j][0]);
337 else
338 EXPECT_EQ(0, pointers[j][0]);
342 for (int i = 0; i < count; i++) {
343 memories[i].Close();
347 TEST(SharedMemoryTest, MapAt) {
348 ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32));
349 const size_t kCount = SysInfo::VMAllocationGranularity();
350 const size_t kDataSize = kCount * sizeof(uint32);
352 SharedMemory memory;
353 ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
354 ASSERT_TRUE(memory.Map(kDataSize));
355 uint32* ptr = static_cast<uint32*>(memory.memory());
356 ASSERT_NE(ptr, static_cast<void*>(NULL));
358 for (size_t i = 0; i < kCount; ++i) {
359 ptr[i] = i;
362 memory.Unmap();
364 off_t offset = SysInfo::VMAllocationGranularity();
365 ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset));
366 offset /= sizeof(uint32);
367 ptr = static_cast<uint32*>(memory.memory());
368 ASSERT_NE(ptr, static_cast<void*>(NULL));
369 for (size_t i = offset; i < kCount; ++i) {
370 EXPECT_EQ(ptr[i - offset], i);
374 #if defined(OS_POSIX)
375 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
376 TEST(SharedMemoryTest, AnonymousExecutable) {
377 const uint32 kTestSize = 1 << 16;
379 SharedMemory shared_memory;
380 SharedMemoryCreateOptions options;
381 options.size = kTestSize;
382 options.executable = true;
384 EXPECT_TRUE(shared_memory.Create(options));
385 EXPECT_TRUE(shared_memory.Map(shared_memory.created_size()));
387 EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.created_size(),
388 PROT_READ | PROT_EXEC));
390 #endif
392 // Map() will return addresses which are aligned to the platform page size, this
393 // varies from platform to platform though. Since we'd like to advertise a
394 // minimum alignment that callers can count on, test for it here.
395 TEST(SharedMemoryTest, MapMinimumAlignment) {
396 static const int kDataSize = 8192;
398 SharedMemory shared_memory;
399 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize));
400 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>(
401 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
402 shared_memory.Close();
405 #if !defined(OS_IOS) // iOS does not allow multiple processes.
407 // On POSIX it is especially important we test shmem across processes,
408 // not just across threads. But the test is enabled on all platforms.
409 class SharedMemoryProcessTest : public MultiProcessTest {
410 public:
412 static void CleanUp() {
413 SharedMemory memory;
414 memory.Delete(s_test_name_);
417 static int TaskTestMain() {
418 int errors = 0;
419 #if defined(OS_MACOSX)
420 mac::ScopedNSAutoreleasePool pool;
421 #endif
422 const uint32 kDataSize = 1024;
423 SharedMemory memory;
424 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
425 EXPECT_TRUE(rv);
426 if (rv != true)
427 errors++;
428 rv = memory.Map(kDataSize);
429 EXPECT_TRUE(rv);
430 if (rv != true)
431 errors++;
432 int *ptr = static_cast<int*>(memory.memory());
434 for (int idx = 0; idx < 20; idx++) {
435 memory.Lock();
436 int i = (1 << 16) + idx;
437 *ptr = i;
438 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
439 if (*ptr != i)
440 errors++;
441 memory.Unlock();
444 memory.Close();
445 return errors;
448 private:
449 static const char* const s_test_name_;
452 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem";
454 TEST_F(SharedMemoryProcessTest, Tasks) {
455 SharedMemoryProcessTest::CleanUp();
457 ProcessHandle handles[kNumTasks];
458 for (int index = 0; index < kNumTasks; ++index) {
459 handles[index] = SpawnChild("SharedMemoryTestMain", false);
460 ASSERT_TRUE(handles[index]);
463 int exit_code = 0;
464 for (int index = 0; index < kNumTasks; ++index) {
465 EXPECT_TRUE(WaitForExitCode(handles[index], &exit_code));
466 EXPECT_EQ(0, exit_code);
469 SharedMemoryProcessTest::CleanUp();
472 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
473 return SharedMemoryProcessTest::TaskTestMain();
476 #endif // !OS_IOS
478 } // namespace base