OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/atomicops.h" | 5 #include "base/atomicops.h" |
6 #include "base/basictypes.h" | 6 #include "base/basictypes.h" |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/memory/shared_memory.h" | 8 #include "base/memory/shared_memory.h" |
9 #include "base/process/kill.h" | 9 #include "base/process/kill.h" |
10 #include "base/rand_util.h" | 10 #include "base/rand_util.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/sys_info.h" | 12 #include "base/sys_info.h" |
13 #include "base/test/multiprocess_test.h" | 13 #include "base/test/multiprocess_test.h" |
14 #include "base/threading/platform_thread.h" | 14 #include "base/threading/platform_thread.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
17 #include "testing/multiprocess_func_list.h" | 17 #include "testing/multiprocess_func_list.h" |
18 | 18 |
19 #if defined(OS_MACOSX) | |
20 #include "base/mac/scoped_nsautorelease_pool.h" | |
21 #endif | |
22 | |
23 #if defined(OS_POSIX) | 19 #if defined(OS_POSIX) |
24 #include <errno.h> | 20 #include <errno.h> |
25 #include <fcntl.h> | 21 #include <fcntl.h> |
26 #include <sys/mman.h> | 22 #include <sys/mman.h> |
27 #include <sys/stat.h> | 23 #include <sys/stat.h> |
28 #include <sys/types.h> | 24 #include <sys/types.h> |
29 #include <unistd.h> | 25 #include <unistd.h> |
30 #endif | 26 #endif |
31 | 27 |
32 #if defined(OS_WIN) | 28 #if defined(OS_WIN) |
33 #include "base/win/scoped_handle.h" | 29 #include "base/win/scoped_handle.h" |
34 #endif | 30 #endif |
35 | 31 |
36 static const int kNumThreads = 5; | |
37 #if !defined(OS_IOS) && !defined(OS_ANDROID) | |
38 static const int kNumTasks = 5; | |
39 #endif | |
40 | |
41 namespace base { | 32 namespace base { |
42 | 33 |
43 namespace { | 34 namespace { |
44 | 35 |
| 36 #if !defined(OS_MACOSX) |
45 // Each thread will open the shared memory. Each thread will take a different 4 | 37 // Each thread will open the shared memory. Each thread will take a different 4 |
46 // byte int pointer, and keep changing it, with some small pauses in between. | 38 // byte int pointer, and keep changing it, with some small pauses in between. |
47 // Verify that each thread's value in the shared memory is always correct. | 39 // Verify that each thread's value in the shared memory is always correct. |
48 class MultipleThreadMain : public PlatformThread::Delegate { | 40 class MultipleThreadMain : public PlatformThread::Delegate { |
49 public: | 41 public: |
50 explicit MultipleThreadMain(int16 id) : id_(id) {} | 42 explicit MultipleThreadMain(int16 id) : id_(id) {} |
51 ~MultipleThreadMain() override {} | 43 ~MultipleThreadMain() override {} |
52 | 44 |
53 static void CleanUp() { | 45 static void CleanUp() { |
54 SharedMemory memory; | 46 SharedMemory memory; |
55 memory.Delete(s_test_name_); | 47 memory.Delete(s_test_name_); |
56 } | 48 } |
57 | 49 |
58 // PlatformThread::Delegate interface. | 50 // PlatformThread::Delegate interface. |
59 void ThreadMain() override { | 51 void ThreadMain() override { |
60 #if defined(OS_MACOSX) | |
61 mac::ScopedNSAutoreleasePool pool; | |
62 #endif | |
63 const uint32 kDataSize = 1024; | 52 const uint32 kDataSize = 1024; |
64 SharedMemory memory; | 53 SharedMemory memory; |
65 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); | 54 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize); |
66 EXPECT_TRUE(rv); | 55 EXPECT_TRUE(rv); |
67 rv = memory.Map(kDataSize); | 56 rv = memory.Map(kDataSize); |
68 EXPECT_TRUE(rv); | 57 EXPECT_TRUE(rv); |
69 int *ptr = static_cast<int*>(memory.memory()) + id_; | 58 int* ptr = static_cast<int*>(memory.memory()) + id_; |
70 EXPECT_EQ(0, *ptr); | 59 EXPECT_EQ(0, *ptr); |
71 | 60 |
72 for (int idx = 0; idx < 100; idx++) { | 61 for (int idx = 0; idx < 100; idx++) { |
73 *ptr = idx; | 62 *ptr = idx; |
74 PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1)); | 63 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); |
75 EXPECT_EQ(*ptr, idx); | 64 EXPECT_EQ(*ptr, idx); |
76 } | 65 } |
77 // Reset back to 0 for the next test that uses the same name. | 66 // Reset back to 0 for the next test that uses the same name. |
78 *ptr = 0; | 67 *ptr = 0; |
79 | 68 |
80 memory.Close(); | 69 memory.Close(); |
81 } | 70 } |
82 | 71 |
83 private: | 72 private: |
84 int16 id_; | 73 int16 id_; |
85 | 74 |
86 static const char* const s_test_name_; | 75 static const char* const s_test_name_; |
87 | 76 |
88 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); | 77 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); |
89 }; | 78 }; |
90 | 79 |
91 const char* const MultipleThreadMain::s_test_name_ = | 80 const char* const MultipleThreadMain::s_test_name_ = |
92 "SharedMemoryOpenThreadTest"; | 81 "SharedMemoryOpenThreadTest"; |
| 82 #endif // !defined(OS_MACOSX) |
93 | 83 |
94 } // namespace | 84 } // namespace |
95 | 85 |
96 // Android doesn't support SharedMemory::Open/Delete/ | 86 // Android/Mac doesn't support SharedMemory::Open/Delete/ |
97 // CreateNamedDeprecated(openExisting=true) | 87 // CreateNamedDeprecated(openExisting=true) |
98 #if !defined(OS_ANDROID) | 88 #if !defined(OS_ANDROID) && !defined(OS_MACOSX) |
99 TEST(SharedMemoryTest, OpenClose) { | 89 TEST(SharedMemoryTest, OpenClose) { |
100 const uint32 kDataSize = 1024; | 90 const uint32 kDataSize = 1024; |
101 std::string test_name = "SharedMemoryOpenCloseTest"; | 91 std::string test_name = "SharedMemoryOpenCloseTest"; |
102 | 92 |
103 // Open two handles to a memory segment, confirm that they are mapped | 93 // Open two handles to a memory segment, confirm that they are mapped |
104 // separately yet point to the same space. | 94 // separately yet point to the same space. |
105 SharedMemory memory1; | 95 SharedMemory memory1; |
106 bool rv = memory1.Delete(test_name); | 96 bool rv = memory1.Delete(test_name); |
107 EXPECT_TRUE(rv); | 97 EXPECT_TRUE(rv); |
108 rv = memory1.Delete(test_name); | 98 rv = memory1.Delete(test_name); |
(...skipping 14 matching lines...) Expand all Loading... |
123 // Make sure we don't segfault. (it actually happened!) | 113 // Make sure we don't segfault. (it actually happened!) |
124 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); | 114 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); |
125 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); | 115 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); |
126 | 116 |
127 // Write data to the first memory segment, verify contents of second. | 117 // Write data to the first memory segment, verify contents of second. |
128 memset(memory1.memory(), '1', kDataSize); | 118 memset(memory1.memory(), '1', kDataSize); |
129 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); | 119 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); |
130 | 120 |
131 // Close the first memory segment, and verify the second has the right data. | 121 // Close the first memory segment, and verify the second has the right data. |
132 memory1.Close(); | 122 memory1.Close(); |
133 char *start_ptr = static_cast<char *>(memory2.memory()); | 123 char* start_ptr = static_cast<char*>(memory2.memory()); |
134 char *end_ptr = start_ptr + kDataSize; | 124 char* end_ptr = start_ptr + kDataSize; |
135 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) | 125 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) |
136 EXPECT_EQ(*ptr, '1'); | 126 EXPECT_EQ(*ptr, '1'); |
137 | 127 |
138 // Close the second memory segment. | 128 // Close the second memory segment. |
139 memory2.Close(); | 129 memory2.Close(); |
140 | 130 |
141 rv = memory1.Delete(test_name); | 131 rv = memory1.Delete(test_name); |
142 EXPECT_TRUE(rv); | 132 EXPECT_TRUE(rv); |
143 rv = memory2.Delete(test_name); | 133 rv = memory2.Delete(test_name); |
144 EXPECT_TRUE(rv); | 134 EXPECT_TRUE(rv); |
(...skipping 17 matching lines...) Expand all Loading... |
162 EXPECT_EQ(memory1.requested_size(), kDataSize); | 152 EXPECT_EQ(memory1.requested_size(), kDataSize); |
163 | 153 |
164 rv = memory1.Map(kDataSize); | 154 rv = memory1.Map(kDataSize); |
165 EXPECT_TRUE(rv); | 155 EXPECT_TRUE(rv); |
166 | 156 |
167 // The mapped memory1 must be at least the size we asked for. | 157 // The mapped memory1 must be at least the size we asked for. |
168 EXPECT_GE(memory1.mapped_size(), kDataSize); | 158 EXPECT_GE(memory1.mapped_size(), kDataSize); |
169 | 159 |
170 // The mapped memory1 shouldn't exceed rounding for allocation granularity. | 160 // The mapped memory1 shouldn't exceed rounding for allocation granularity. |
171 EXPECT_LT(memory1.mapped_size(), | 161 EXPECT_LT(memory1.mapped_size(), |
172 kDataSize + base::SysInfo::VMAllocationGranularity()); | 162 kDataSize + SysInfo::VMAllocationGranularity()); |
173 | 163 |
174 memset(memory1.memory(), 'G', kDataSize); | 164 memset(memory1.memory(), 'G', kDataSize); |
175 | 165 |
176 SharedMemory memory2; | 166 SharedMemory memory2; |
177 // Should not be able to create if openExisting is false. | 167 // Should not be able to create if openExisting is false. |
178 rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2); | 168 rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2); |
179 EXPECT_FALSE(rv); | 169 EXPECT_FALSE(rv); |
180 | 170 |
181 // Should be able to create with openExisting true. | 171 // Should be able to create with openExisting true. |
182 rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2); | 172 rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2); |
183 EXPECT_TRUE(rv); | 173 EXPECT_TRUE(rv); |
184 | 174 |
185 // Memory2 shouldn't know the size because we didn't create it. | 175 // Memory2 shouldn't know the size because we didn't create it. |
186 EXPECT_EQ(memory2.requested_size(), 0U); | 176 EXPECT_EQ(memory2.requested_size(), 0U); |
187 | 177 |
188 // We should be able to map the original size. | 178 // We should be able to map the original size. |
189 rv = memory2.Map(kDataSize); | 179 rv = memory2.Map(kDataSize); |
190 EXPECT_TRUE(rv); | 180 EXPECT_TRUE(rv); |
191 | 181 |
192 // The mapped memory2 must be at least the size of the original. | 182 // The mapped memory2 must be at least the size of the original. |
193 EXPECT_GE(memory2.mapped_size(), kDataSize); | 183 EXPECT_GE(memory2.mapped_size(), kDataSize); |
194 | 184 |
195 // The mapped memory2 shouldn't exceed rounding for allocation granularity. | 185 // The mapped memory2 shouldn't exceed rounding for allocation granularity. |
196 EXPECT_LT(memory2.mapped_size(), | 186 EXPECT_LT(memory2.mapped_size(), |
197 kDataSize2 + base::SysInfo::VMAllocationGranularity()); | 187 kDataSize2 + SysInfo::VMAllocationGranularity()); |
198 | 188 |
199 // Verify that opening memory2 didn't truncate or delete memory 1. | 189 // Verify that opening memory2 didn't truncate or delete memory 1. |
200 char *start_ptr = static_cast<char *>(memory2.memory()); | 190 char* start_ptr = static_cast<char*>(memory2.memory()); |
201 char *end_ptr = start_ptr + kDataSize; | 191 char* end_ptr = start_ptr + kDataSize; |
202 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) { | 192 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) { |
203 EXPECT_EQ(*ptr, 'G'); | 193 EXPECT_EQ(*ptr, 'G'); |
204 } | 194 } |
205 | 195 |
206 memory1.Close(); | 196 memory1.Close(); |
207 memory2.Close(); | 197 memory2.Close(); |
208 | 198 |
209 rv = memory1.Delete(test_name); | 199 rv = memory1.Delete(test_name); |
210 EXPECT_TRUE(rv); | 200 EXPECT_TRUE(rv); |
211 } | 201 } |
212 #endif | 202 #endif // !defined(OS_ANDROID) && !defined(OS_MACOSX) |
213 | 203 |
214 // Check that memory is still mapped after its closed. | 204 // Check that memory is still mapped after its closed. |
215 TEST(SharedMemoryTest, CloseNoUnmap) { | 205 TEST(SharedMemoryTest, CloseNoUnmap) { |
216 const size_t kDataSize = 4096; | 206 const size_t kDataSize = 4096; |
217 | 207 |
218 SharedMemory memory; | 208 SharedMemory memory; |
219 ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); | 209 ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize)); |
220 char* ptr = static_cast<char*>(memory.memory()); | 210 char* ptr = static_cast<char*>(memory.memory()); |
221 ASSERT_NE(ptr, static_cast<void*>(NULL)); | 211 ASSERT_NE(ptr, static_cast<void*>(NULL)); |
222 memset(ptr, 'G', kDataSize); | 212 memset(ptr, 'G', kDataSize); |
223 | 213 |
224 memory.Close(); | 214 memory.Close(); |
225 | 215 |
226 EXPECT_EQ(ptr, memory.memory()); | 216 EXPECT_EQ(ptr, memory.memory()); |
227 EXPECT_EQ(SharedMemory::NULLHandle(), memory.handle()); | 217 EXPECT_EQ(SharedMemory::NULLHandle(), memory.handle()); |
228 | 218 |
229 for (size_t i = 0; i < kDataSize; i++) { | 219 for (size_t i = 0; i < kDataSize; i++) { |
230 EXPECT_EQ('G', ptr[i]); | 220 EXPECT_EQ('G', ptr[i]); |
231 } | 221 } |
232 | 222 |
233 memory.Unmap(); | 223 memory.Unmap(); |
234 EXPECT_EQ(nullptr, memory.memory()); | 224 EXPECT_EQ(nullptr, memory.memory()); |
235 } | 225 } |
236 | 226 |
| 227 #if !defined(OS_MACOSX) |
237 // Create a set of N threads to each open a shared memory segment and write to | 228 // 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. | 229 // it. Verify that they are always reading/writing consistent data. |
239 TEST(SharedMemoryTest, MultipleThreads) { | 230 TEST(SharedMemoryTest, MultipleThreads) { |
| 231 const int kNumThreads = 5; |
| 232 |
240 MultipleThreadMain::CleanUp(); | 233 MultipleThreadMain::CleanUp(); |
241 // On POSIX we have a problem when 2 threads try to create the shmem | 234 // 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 | 235 // (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 | 236 // file and zerofills it. We solve the problem for this unit test |
244 // (make it not flaky) by starting with 1 thread, then | 237 // (make it not flaky) by starting with 1 thread, then |
245 // intentionally don't clean up its shmem before running with | 238 // intentionally don't clean up its shmem before running with |
246 // kNumThreads. | 239 // kNumThreads. |
247 | 240 |
248 int threadcounts[] = { 1, kNumThreads }; | 241 int threadcounts[] = { 1, kNumThreads }; |
249 for (size_t i = 0; i < arraysize(threadcounts); i++) { | 242 for (size_t i = 0; i < arraysize(threadcounts); i++) { |
(...skipping 13 matching lines...) Expand all Loading... |
263 } | 256 } |
264 | 257 |
265 // Wait for the threads to finish. | 258 // Wait for the threads to finish. |
266 for (int index = 0; index < numthreads; index++) { | 259 for (int index = 0; index < numthreads; index++) { |
267 PlatformThread::Join(thread_handles[index]); | 260 PlatformThread::Join(thread_handles[index]); |
268 delete thread_delegates[index]; | 261 delete thread_delegates[index]; |
269 } | 262 } |
270 } | 263 } |
271 MultipleThreadMain::CleanUp(); | 264 MultipleThreadMain::CleanUp(); |
272 } | 265 } |
| 266 #endif |
273 | 267 |
274 // Allocate private (unique) shared memory with an empty string for a | 268 // Allocate private (unique) shared memory with an empty string for a |
275 // name. Make sure several of them don't point to the same thing as | 269 // name. Make sure several of them don't point to the same thing as |
276 // we might expect if the names are equal. | 270 // we might expect if the names are equal. |
277 TEST(SharedMemoryTest, AnonymousPrivate) { | 271 TEST(SharedMemoryTest, AnonymousPrivate) { |
278 int i, j; | 272 int i, j; |
279 int count = 4; | 273 int count = 4; |
280 bool rv; | 274 bool rv; |
281 const uint32 kDataSize = 8192; | 275 const uint32 kDataSize = 8192; |
282 | 276 |
283 scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]); | 277 scoped_ptr<SharedMemory[]> memories(new SharedMemory[count]); |
284 scoped_ptr<int*[]> pointers(new int*[count]); | 278 scoped_ptr<int*[]> pointers(new int*[count]); |
285 ASSERT_TRUE(memories.get()); | 279 ASSERT_TRUE(memories.get()); |
286 ASSERT_TRUE(pointers.get()); | 280 ASSERT_TRUE(pointers.get()); |
287 | 281 |
288 for (i = 0; i < count; i++) { | 282 for (i = 0; i < count; i++) { |
289 rv = memories[i].CreateAndMapAnonymous(kDataSize); | 283 rv = memories[i].CreateAndMapAnonymous(kDataSize); |
290 EXPECT_TRUE(rv); | 284 EXPECT_TRUE(rv); |
291 int *ptr = static_cast<int*>(memories[i].memory()); | 285 int* ptr = static_cast<int*>(memories[i].memory()); |
292 EXPECT_TRUE(ptr); | 286 EXPECT_TRUE(ptr); |
293 pointers[i] = ptr; | 287 pointers[i] = ptr; |
294 } | 288 } |
295 | 289 |
296 for (i = 0; i < count; i++) { | 290 for (i = 0; i < count; i++) { |
297 // zero out the first int in each except for i; for that one, make it 100. | 291 // zero out the first int in each except for i; for that one, make it 100. |
298 for (j = 0; j < count; j++) { | 292 for (j = 0; j < count; j++) { |
299 if (i == j) | 293 if (i == j) |
300 pointers[j][0] = 100; | 294 pointers[j][0] = 100; |
301 else | 295 else |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 BOOL rv = ::DuplicateHandle(GetCurrentProcess(), | 376 BOOL rv = ::DuplicateHandle(GetCurrentProcess(), |
383 handle, | 377 handle, |
384 GetCurrentProcess(), | 378 GetCurrentProcess(), |
385 &temp_handle, | 379 &temp_handle, |
386 FILE_MAP_ALL_ACCESS, | 380 FILE_MAP_ALL_ACCESS, |
387 false, | 381 false, |
388 0); | 382 0); |
389 EXPECT_EQ(FALSE, rv) | 383 EXPECT_EQ(FALSE, rv) |
390 << "Shouldn't be able to duplicate the handle into a writable one."; | 384 << "Shouldn't be able to duplicate the handle into a writable one."; |
391 if (rv) | 385 if (rv) |
392 base::win::ScopedHandle writable_handle(temp_handle); | 386 win::ScopedHandle writable_handle(temp_handle); |
393 rv = ::DuplicateHandle(GetCurrentProcess(), | 387 rv = ::DuplicateHandle(GetCurrentProcess(), |
394 handle, | 388 handle, |
395 GetCurrentProcess(), | 389 GetCurrentProcess(), |
396 &temp_handle, | 390 &temp_handle, |
397 FILE_MAP_READ, | 391 FILE_MAP_READ, |
398 false, | 392 false, |
399 0); | 393 0); |
400 EXPECT_EQ(TRUE, rv) | 394 EXPECT_EQ(TRUE, rv) |
401 << "Should be able to duplicate the handle into a readable one."; | 395 << "Should be able to duplicate the handle into a readable one."; |
402 if (rv) | 396 if (rv) |
403 base::win::ScopedHandle writable_handle(temp_handle); | 397 win::ScopedHandle writable_handle(temp_handle); |
404 #else | 398 #else |
405 #error Unexpected platform; write a test that tries to make 'handle' writable. | 399 #error Unexpected platform; write a test that tries to make 'handle' writable. |
406 #endif // defined(OS_POSIX) || defined(OS_WIN) | 400 #endif // defined(OS_POSIX) || defined(OS_WIN) |
407 } | 401 } |
408 | 402 |
409 TEST(SharedMemoryTest, ShareToSelf) { | 403 TEST(SharedMemoryTest, ShareToSelf) { |
410 StringPiece contents = "Hello World"; | 404 StringPiece contents = "Hello World"; |
411 | 405 |
412 SharedMemory shmem; | 406 SharedMemory shmem; |
413 ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size())); | 407 ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size())); |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 struct stat shm_stat; | 519 struct stat shm_stat; |
526 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); | 520 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); |
527 // Neither the group, nor others should be able to read the shared memory | 521 // Neither the group, nor others should be able to read the shared memory |
528 // file. | 522 // file. |
529 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); | 523 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); |
530 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); | 524 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); |
531 } | 525 } |
532 | 526 |
533 // Create a shared memory object, check its permissions. | 527 // Create a shared memory object, check its permissions. |
534 TEST(SharedMemoryTest, FilePermissionsNamed) { | 528 TEST(SharedMemoryTest, FilePermissionsNamed) { |
535 const uint32 kTestSize = 1 << 8; | 529 const uint32_t kTestSize = 1 << 8; |
536 | 530 |
537 SharedMemory shared_memory; | 531 SharedMemory shared_memory; |
538 SharedMemoryCreateOptions options; | 532 SharedMemoryCreateOptions options; |
539 options.size = kTestSize; | 533 options.size = kTestSize; |
540 std::string shared_mem_name = "shared_perm_test-" + IntToString(getpid()) + | 534 |
541 "-" + Uint64ToString(RandUint64()); | |
542 options.name_deprecated = &shared_mem_name; | |
543 // Set a file mode creation mask that gives all permissions. | 535 // Set a file mode creation mask that gives all permissions. |
544 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); | 536 ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH); |
545 | 537 |
546 EXPECT_TRUE(shared_memory.Create(options)); | 538 EXPECT_TRUE(shared_memory.Create(options)); |
547 // Clean-up the backing file name immediately, we don't need it. | |
548 EXPECT_TRUE(shared_memory.Delete(shared_mem_name)); | |
549 | 539 |
550 int shm_fd = | 540 int fd = SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); |
551 SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle()); | |
552 struct stat shm_stat; | 541 struct stat shm_stat; |
553 EXPECT_EQ(0, fstat(shm_fd, &shm_stat)); | 542 EXPECT_EQ(0, fstat(fd, &shm_stat)); |
554 // Neither the group, nor others should have been able to open the shared | 543 // Neither the group, nor others should have been able to open the shared |
555 // memory file while its name existed. | 544 // memory file while its name existed. |
556 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); | 545 EXPECT_FALSE(shm_stat.st_mode & S_IRWXO); |
557 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); | 546 EXPECT_FALSE(shm_stat.st_mode & S_IRWXG); |
558 } | 547 } |
559 #endif // !defined(OS_ANDROID) | 548 #endif // !defined(OS_ANDROID) |
560 | 549 |
561 #endif // defined(OS_POSIX) | 550 #endif // defined(OS_POSIX) |
562 | 551 |
563 // Map() will return addresses which are aligned to the platform page size, this | 552 // Map() will return addresses which are aligned to the platform page size, this |
564 // varies from platform to platform though. Since we'd like to advertise a | 553 // varies from platform to platform though. Since we'd like to advertise a |
565 // minimum alignment that callers can count on, test for it here. | 554 // minimum alignment that callers can count on, test for it here. |
566 TEST(SharedMemoryTest, MapMinimumAlignment) { | 555 TEST(SharedMemoryTest, MapMinimumAlignment) { |
567 static const int kDataSize = 8192; | 556 static const int kDataSize = 8192; |
568 | 557 |
569 SharedMemory shared_memory; | 558 SharedMemory shared_memory; |
570 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize)); | 559 ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize)); |
571 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>( | 560 EXPECT_EQ(0U, reinterpret_cast<uintptr_t>( |
572 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); | 561 shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1)); |
573 shared_memory.Close(); | 562 shared_memory.Close(); |
574 } | 563 } |
575 | 564 |
576 // iOS does not allow multiple processes. | 565 // iOS does not allow multiple processes. |
577 // Android ashmem doesn't support named shared memory. | 566 // Android ashmem does not support named shared memory. |
578 #if !defined(OS_IOS) && !defined(OS_ANDROID) | 567 // Mac SharedMemory does not support named shared memory. crbug.com/345734 |
579 | 568 #if !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) |
580 // On POSIX it is especially important we test shmem across processes, | 569 // On POSIX it is especially important we test shmem across processes, |
581 // not just across threads. But the test is enabled on all platforms. | 570 // not just across threads. But the test is enabled on all platforms. |
582 class SharedMemoryProcessTest : public MultiProcessTest { | 571 class SharedMemoryProcessTest : public MultiProcessTest { |
583 public: | 572 public: |
584 | |
585 static void CleanUp() { | 573 static void CleanUp() { |
586 SharedMemory memory; | 574 SharedMemory memory; |
587 memory.Delete(s_test_name_); | 575 memory.Delete(s_test_name_); |
588 } | 576 } |
589 | 577 |
590 static int TaskTestMain() { | 578 static int TaskTestMain() { |
591 int errors = 0; | 579 int errors = 0; |
592 #if defined(OS_MACOSX) | |
593 mac::ScopedNSAutoreleasePool pool; | |
594 #endif | |
595 SharedMemory memory; | 580 SharedMemory memory; |
596 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); | 581 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); |
597 EXPECT_TRUE(rv); | 582 EXPECT_TRUE(rv); |
598 if (rv != true) | 583 if (rv != true) |
599 errors++; | 584 errors++; |
600 rv = memory.Map(s_data_size_); | 585 rv = memory.Map(s_data_size_); |
601 EXPECT_TRUE(rv); | 586 EXPECT_TRUE(rv); |
602 if (rv != true) | 587 if (rv != true) |
603 errors++; | 588 errors++; |
604 int *ptr = static_cast<int*>(memory.memory()); | 589 int* ptr = static_cast<int*>(memory.memory()); |
605 | 590 |
606 // This runs concurrently in multiple processes. Writes need to be atomic. | 591 // This runs concurrently in multiple processes. Writes need to be atomic. |
607 base::subtle::Barrier_AtomicIncrement(ptr, 1); | 592 subtle::Barrier_AtomicIncrement(ptr, 1); |
608 memory.Close(); | 593 memory.Close(); |
609 return errors; | 594 return errors; |
610 } | 595 } |
611 | 596 |
612 static const char* const s_test_name_; | 597 static const char* const s_test_name_; |
613 static const uint32 s_data_size_; | 598 static const uint32 s_data_size_; |
614 }; | 599 }; |
615 | 600 |
616 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem"; | 601 const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem"; |
617 const uint32 SharedMemoryProcessTest::s_data_size_ = 1024; | 602 const uint32 SharedMemoryProcessTest::s_data_size_ = 1024; |
618 | 603 |
619 TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) { | 604 TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) { |
| 605 const int kNumTasks = 5; |
| 606 |
620 SharedMemoryProcessTest::CleanUp(); | 607 SharedMemoryProcessTest::CleanUp(); |
621 | 608 |
622 // Create a shared memory region. Set the first word to 0. | 609 // Create a shared memory region. Set the first word to 0. |
623 SharedMemory memory; | 610 SharedMemory memory; |
624 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); | 611 bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_); |
625 ASSERT_TRUE(rv); | 612 ASSERT_TRUE(rv); |
626 rv = memory.Map(s_data_size_); | 613 rv = memory.Map(s_data_size_); |
627 ASSERT_TRUE(rv); | 614 ASSERT_TRUE(rv); |
628 int* ptr = static_cast<int*>(memory.memory()); | 615 int* ptr = static_cast<int*>(memory.memory()); |
629 *ptr = 0; | 616 *ptr = 0; |
(...skipping 16 matching lines...) Expand all Loading... |
646 // Check that the shared memory region reflects |kNumTasks| increments. | 633 // Check that the shared memory region reflects |kNumTasks| increments. |
647 ASSERT_EQ(kNumTasks, *ptr); | 634 ASSERT_EQ(kNumTasks, *ptr); |
648 | 635 |
649 memory.Close(); | 636 memory.Close(); |
650 SharedMemoryProcessTest::CleanUp(); | 637 SharedMemoryProcessTest::CleanUp(); |
651 } | 638 } |
652 | 639 |
653 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { | 640 MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { |
654 return SharedMemoryProcessTest::TaskTestMain(); | 641 return SharedMemoryProcessTest::TaskTestMain(); |
655 } | 642 } |
656 | 643 #endif // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) |
657 #endif // !defined(OS_IOS) && !defined(OS_ANDROID) | |
658 | 644 |
659 } // namespace base | 645 } // namespace base |
OLD | NEW |