| 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 |