OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
6 #include "base/memory/scoped_ptr.h" | 6 #include "base/memory/scoped_ptr.h" |
7 #include "base/shared_memory.h" | 7 #include "base/shared_memory.h" |
8 #include "base/test/multiprocess_test.h" | 8 #include "base/test/multiprocess_test.h" |
9 #include "base/threading/platform_thread.h" | 9 #include "base/threading/platform_thread.h" |
10 #include "base/time.h" | 10 #include "base/time.h" |
11 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
12 #include "testing/multiprocess_func_list.h" | 12 #include "testing/multiprocess_func_list.h" |
13 | 13 |
14 #if defined(OS_MACOSX) | 14 #if defined(OS_MACOSX) |
15 #include "base/mac/scoped_nsautorelease_pool.h" | 15 #include "base/mac/scoped_nsautorelease_pool.h" |
16 #endif | 16 #endif |
17 | 17 |
| 18 #if defined(OS_POSIX) |
| 19 #include <sys/mman.h> |
| 20 #endif |
| 21 |
18 static const int kNumThreads = 5; | 22 static const int kNumThreads = 5; |
19 static const int kNumTasks = 5; | 23 static const int kNumTasks = 5; |
20 | 24 |
21 namespace base { | 25 namespace base { |
22 | 26 |
23 namespace { | 27 namespace { |
24 | 28 |
25 // Each thread will open the shared memory. Each thread will take a different 4 | 29 // Each thread will open the shared memory. Each thread will take a different 4 |
26 // byte int pointer, and keep changing it, with some small pauses in between. | 30 // byte int pointer, and keep changing it, with some small pauses in between. |
27 // Verify that each thread's value in the shared memory is always correct. | 31 // Verify that each thread's value in the shared memory is always correct. |
28 class MultipleThreadMain : public PlatformThread::Delegate { | 32 class MultipleThreadMain : public PlatformThread::Delegate { |
29 public: | 33 public: |
30 explicit MultipleThreadMain(int16 id) : id_(id) {} | 34 explicit MultipleThreadMain(int16 id) : id_(id) {} |
31 ~MultipleThreadMain() {} | 35 ~MultipleThreadMain() {} |
32 | 36 |
33 static void CleanUp() { | 37 static void CleanUp() { |
34 SharedMemory memory; | 38 SharedMemory memory; |
35 memory.Delete(s_test_name_); | 39 memory.Delete(s_test_name_); |
36 } | 40 } |
37 | 41 |
38 // PlatformThread::Delegate interface. | 42 // PlatformThread::Delegate interface. |
39 void ThreadMain() { | 43 void ThreadMain() { |
40 #if defined(OS_MACOSX) | 44 #if defined(OS_MACOSX) |
41 mac::ScopedNSAutoreleasePool pool; | 45 mac::ScopedNSAutoreleasePool pool; |
42 #endif | 46 #endif |
43 const uint32 kDataSize = 1024; | 47 const uint32 kDataSize = 1024; |
44 SharedMemory memory; | 48 SharedMemory memory; |
45 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize); | 49 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize, false); |
46 EXPECT_TRUE(rv); | 50 EXPECT_TRUE(rv); |
47 rv = memory.Map(kDataSize); | 51 rv = memory.Map(kDataSize); |
48 EXPECT_TRUE(rv); | 52 EXPECT_TRUE(rv); |
49 int *ptr = static_cast<int*>(memory.memory()) + id_; | 53 int *ptr = static_cast<int*>(memory.memory()) + id_; |
50 EXPECT_EQ(0, *ptr); | 54 EXPECT_EQ(0, *ptr); |
51 | 55 |
52 for (int idx = 0; idx < 100; idx++) { | 56 for (int idx = 0; idx < 100; idx++) { |
53 *ptr = idx; | 57 *ptr = idx; |
54 PlatformThread::Sleep(1); // Short wait. | 58 PlatformThread::Sleep(1); // Short wait. |
55 EXPECT_EQ(*ptr, idx); | 59 EXPECT_EQ(*ptr, idx); |
(...skipping 28 matching lines...) Expand all Loading... |
84 explicit MultipleLockThread(int id) : id_(id) {} | 88 explicit MultipleLockThread(int id) : id_(id) {} |
85 ~MultipleLockThread() {} | 89 ~MultipleLockThread() {} |
86 | 90 |
87 // PlatformThread::Delegate interface. | 91 // PlatformThread::Delegate interface. |
88 void ThreadMain() { | 92 void ThreadMain() { |
89 const uint32 kDataSize = sizeof(int); | 93 const uint32 kDataSize = sizeof(int); |
90 SharedMemoryHandle handle = NULL; | 94 SharedMemoryHandle handle = NULL; |
91 { | 95 { |
92 SharedMemory memory1; | 96 SharedMemory memory1; |
93 EXPECT_TRUE(memory1.CreateNamed("SharedMemoryMultipleLockThreadTest", | 97 EXPECT_TRUE(memory1.CreateNamed("SharedMemoryMultipleLockThreadTest", |
94 true, kDataSize)); | 98 true, kDataSize, false)); |
95 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); | 99 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); |
96 // TODO(paulg): Implement this once we have a posix version of | 100 // TODO(paulg): Implement this once we have a posix version of |
97 // SharedMemory::ShareToProcess. | 101 // SharedMemory::ShareToProcess. |
98 EXPECT_TRUE(true); | 102 EXPECT_TRUE(true); |
99 } | 103 } |
100 | 104 |
101 SharedMemory memory2(handle, false); | 105 SharedMemory memory2(handle, false); |
102 EXPECT_TRUE(memory2.Map(kDataSize)); | 106 EXPECT_TRUE(memory2.Map(kDataSize)); |
103 volatile int* const ptr = static_cast<int*>(memory2.memory()); | 107 volatile int* const ptr = static_cast<int*>(memory2.memory()); |
104 | 108 |
(...skipping 24 matching lines...) Expand all Loading... |
129 | 133 |
130 // Open two handles to a memory segment, confirm that they are mapped | 134 // Open two handles to a memory segment, confirm that they are mapped |
131 // separately yet point to the same space. | 135 // separately yet point to the same space. |
132 SharedMemory memory1; | 136 SharedMemory memory1; |
133 bool rv = memory1.Delete(test_name); | 137 bool rv = memory1.Delete(test_name); |
134 EXPECT_TRUE(rv); | 138 EXPECT_TRUE(rv); |
135 rv = memory1.Delete(test_name); | 139 rv = memory1.Delete(test_name); |
136 EXPECT_TRUE(rv); | 140 EXPECT_TRUE(rv); |
137 rv = memory1.Open(test_name, false); | 141 rv = memory1.Open(test_name, false); |
138 EXPECT_FALSE(rv); | 142 EXPECT_FALSE(rv); |
139 rv = memory1.CreateNamed(test_name, false, kDataSize); | 143 rv = memory1.CreateNamed(test_name, false, kDataSize, false); |
140 EXPECT_TRUE(rv); | 144 EXPECT_TRUE(rv); |
141 rv = memory1.Map(kDataSize); | 145 rv = memory1.Map(kDataSize); |
142 EXPECT_TRUE(rv); | 146 EXPECT_TRUE(rv); |
143 SharedMemory memory2; | 147 SharedMemory memory2; |
144 rv = memory2.Open(test_name, false); | 148 rv = memory2.Open(test_name, false); |
145 EXPECT_TRUE(rv); | 149 EXPECT_TRUE(rv); |
146 rv = memory2.Map(kDataSize); | 150 rv = memory2.Map(kDataSize); |
147 EXPECT_TRUE(rv); | 151 EXPECT_TRUE(rv); |
148 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. | 152 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. |
149 | 153 |
(...skipping 25 matching lines...) Expand all Loading... |
175 const uint32 kDataSize = 1024; | 179 const uint32 kDataSize = 1024; |
176 const uint32 kDataSize2 = 2048; | 180 const uint32 kDataSize2 = 2048; |
177 std::ostringstream test_name_stream; | 181 std::ostringstream test_name_stream; |
178 test_name_stream << "SharedMemoryOpenExclusiveTest." | 182 test_name_stream << "SharedMemoryOpenExclusiveTest." |
179 << Time::Now().ToDoubleT(); | 183 << Time::Now().ToDoubleT(); |
180 std::string test_name = test_name_stream.str(); | 184 std::string test_name = test_name_stream.str(); |
181 | 185 |
182 // Open two handles to a memory segment and check that open_existing works | 186 // Open two handles to a memory segment and check that open_existing works |
183 // as expected. | 187 // as expected. |
184 SharedMemory memory1; | 188 SharedMemory memory1; |
185 bool rv = memory1.CreateNamed(test_name, false, kDataSize); | 189 bool rv = memory1.CreateNamed(test_name, false, kDataSize, false); |
186 EXPECT_TRUE(rv); | 190 EXPECT_TRUE(rv); |
187 | 191 |
188 // Memory1 knows it's size because it created it. | 192 // Memory1 knows it's size because it created it. |
189 EXPECT_EQ(memory1.created_size(), kDataSize); | 193 EXPECT_EQ(memory1.created_size(), kDataSize); |
190 | 194 |
191 rv = memory1.Map(kDataSize); | 195 rv = memory1.Map(kDataSize); |
192 EXPECT_TRUE(rv); | 196 EXPECT_TRUE(rv); |
193 | 197 |
194 memset(memory1.memory(), 'G', kDataSize); | 198 memset(memory1.memory(), 'G', kDataSize); |
195 | 199 |
196 SharedMemory memory2; | 200 SharedMemory memory2; |
197 // Should not be able to create if openExisting is false. | 201 // Should not be able to create if openExisting is false. |
198 rv = memory2.CreateNamed(test_name, false, kDataSize2); | 202 rv = memory2.CreateNamed(test_name, false, kDataSize2, false); |
199 EXPECT_FALSE(rv); | 203 EXPECT_FALSE(rv); |
200 | 204 |
201 // Should be able to create with openExisting true. | 205 // Should be able to create with openExisting true. |
202 rv = memory2.CreateNamed(test_name, true, kDataSize2); | 206 rv = memory2.CreateNamed(test_name, true, kDataSize2, false); |
203 EXPECT_TRUE(rv); | 207 EXPECT_TRUE(rv); |
204 | 208 |
205 // Memory2 shouldn't know the size because we didn't create it. | 209 // Memory2 shouldn't know the size because we didn't create it. |
206 EXPECT_EQ(memory2.created_size(), 0U); | 210 EXPECT_EQ(memory2.created_size(), 0U); |
207 | 211 |
208 // We should be able to map the original size. | 212 // We should be able to map the original size. |
209 rv = memory2.Map(kDataSize); | 213 rv = memory2.Map(kDataSize); |
210 EXPECT_TRUE(rv); | 214 EXPECT_TRUE(rv); |
211 | 215 |
212 // Verify that opening memory2 didn't truncate or delete memory 1. | 216 // Verify that opening memory2 didn't truncate or delete memory 1. |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 else | 329 else |
326 EXPECT_EQ(0, pointers[j][0]); | 330 EXPECT_EQ(0, pointers[j][0]); |
327 } | 331 } |
328 } | 332 } |
329 | 333 |
330 for (int i = 0; i < count; i++) { | 334 for (int i = 0; i < count; i++) { |
331 memories[i].Close(); | 335 memories[i].Close(); |
332 } | 336 } |
333 } | 337 } |
334 | 338 |
| 339 #if defined(OS_POSIX) |
| 340 // Create a shared memory object, mmap it, and mprotect it to PROT_EXEC. |
| 341 TEST(SharedMemoryTest, AnonymousExecutable) { |
| 342 const uint32 kTestSize = 1 << 16; |
| 343 |
| 344 SharedMemory shared_memory; |
| 345 |
| 346 EXPECT_TRUE(shared_memory.CreateAnonymous(kTestSize, true)); |
| 347 EXPECT_TRUE(shared_memory.Map(shared_memory.created_size())); |
| 348 |
| 349 EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.created_size(), |
| 350 PROT_READ | PROT_EXEC)); |
| 351 } |
| 352 #endif |
| 353 |
335 // On POSIX it is especially important we test shmem across processes, | 354 // On POSIX it is especially important we test shmem across processes, |
336 // not just across threads. But the test is enabled on all platforms. | 355 // not just across threads. But the test is enabled on all platforms. |
337 class SharedMemoryProcessTest : public MultiProcessTest { | 356 class SharedMemoryProcessTest : public MultiProcessTest { |
338 public: | 357 public: |
339 | 358 |
340 static void CleanUp() { | 359 static void CleanUp() { |
341 SharedMemory memory; | 360 SharedMemory memory; |
342 memory.Delete(s_test_name_); | 361 memory.Delete(s_test_name_); |
343 } | 362 } |
344 | 363 |
345 static int TaskTestMain() { | 364 static int TaskTestMain() { |
346 int errors = 0; | 365 int errors = 0; |
347 #if defined(OS_MACOSX) | 366 #if defined(OS_MACOSX) |
348 mac::ScopedNSAutoreleasePool pool; | 367 mac::ScopedNSAutoreleasePool pool; |
349 #endif | 368 #endif |
350 const uint32 kDataSize = 1024; | 369 const uint32 kDataSize = 1024; |
351 SharedMemory memory; | 370 SharedMemory memory; |
352 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize); | 371 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize, false); |
353 EXPECT_TRUE(rv); | 372 EXPECT_TRUE(rv); |
354 if (rv != true) | 373 if (rv != true) |
355 errors++; | 374 errors++; |
356 rv = memory.Map(kDataSize); | 375 rv = memory.Map(kDataSize); |
357 EXPECT_TRUE(rv); | 376 EXPECT_TRUE(rv); |
358 if (rv != true) | 377 if (rv != true) |
359 errors++; | 378 errors++; |
360 int *ptr = static_cast<int*>(memory.memory()); | 379 int *ptr = static_cast<int*>(memory.memory()); |
361 | 380 |
362 for (int idx = 0; idx < 20; idx++) { | 381 for (int idx = 0; idx < 20; idx++) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 } | 421 } |
403 | 422 |
404 SharedMemoryProcessTest::CleanUp(); | 423 SharedMemoryProcessTest::CleanUp(); |
405 } | 424 } |
406 | 425 |
407 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { | 426 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { |
408 return SharedMemoryProcessTest::TaskTestMain(); | 427 return SharedMemoryProcessTest::TaskTestMain(); |
409 } | 428 } |
410 | 429 |
411 } // namespace base | 430 } // namespace base |
OLD | NEW |