| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/platform_thread.h" | 6 #include "base/platform_thread.h" |
| 7 #include "base/scoped_nsautorelease_pool.h" |
| 7 #include "base/shared_memory.h" | 8 #include "base/shared_memory.h" |
| 8 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 9 | 10 |
| 10 static const int kNumThreads = 5; | 11 static const int kNumThreads = 5; |
| 11 | 12 |
| 12 namespace base { | 13 namespace base { |
| 13 | 14 |
| 14 namespace { | 15 namespace { |
| 15 | 16 |
| 16 // Each thread will open the shared memory. Each thread will take a different 4 | 17 // Each thread will open the shared memory. Each thread will take a different 4 |
| 17 // byte int pointer, and keep changing it, with some small pauses in between. | 18 // byte int pointer, and keep changing it, with some small pauses in between. |
| 18 // Verify that each thread's value in the shared memory is always correct. | 19 // Verify that each thread's value in the shared memory is always correct. |
| 19 class MultipleThreadMain : public PlatformThread::Delegate { | 20 class MultipleThreadMain : public PlatformThread::Delegate { |
| 20 public: | 21 public: |
| 21 explicit MultipleThreadMain(int16 id) : id_(id) {} | 22 explicit MultipleThreadMain(int16 id) : id_(id) {} |
| 22 ~MultipleThreadMain() {} | 23 ~MultipleThreadMain() {} |
| 23 | 24 |
| 25 static void CleanUp() { |
| 26 SharedMemory memory; |
| 27 memory.Delete(test_name_); |
| 28 } |
| 29 |
| 24 // PlatformThread::Delegate interface. | 30 // PlatformThread::Delegate interface. |
| 25 void ThreadMain() { | 31 void ThreadMain() { |
| 32 ScopedNSAutoreleasePool pool; // noop if not OSX |
| 26 const int kDataSize = 1024; | 33 const int kDataSize = 1024; |
| 27 std::wstring test_name = L"SharedMemoryOpenThreadTest"; | |
| 28 SharedMemory memory; | 34 SharedMemory memory; |
| 29 bool rv = memory.Create(test_name, false, true, kDataSize); | 35 bool rv = memory.Create(test_name_, false, true, kDataSize); |
| 30 EXPECT_TRUE(rv); | 36 EXPECT_TRUE(rv); |
| 31 rv = memory.Map(kDataSize); | 37 rv = memory.Map(kDataSize); |
| 32 EXPECT_TRUE(rv); | 38 EXPECT_TRUE(rv); |
| 33 int *ptr = static_cast<int*>(memory.memory()) + id_; | 39 int *ptr = static_cast<int*>(memory.memory()) + id_; |
| 34 EXPECT_EQ(*ptr, 0); | 40 EXPECT_EQ(*ptr, 0); |
| 35 | 41 |
| 36 for (int idx = 0; idx < 100; idx++) { | 42 for (int idx = 0; idx < 100; idx++) { |
| 37 *ptr = idx; | 43 *ptr = idx; |
| 38 PlatformThread::Sleep(1); // Short wait. | 44 PlatformThread::Sleep(1); // Short wait. |
| 39 EXPECT_EQ(*ptr, idx); | 45 EXPECT_EQ(*ptr, idx); |
| 40 } | 46 } |
| 41 | 47 |
| 42 memory.Close(); | 48 memory.Close(); |
| 43 } | 49 } |
| 44 | 50 |
| 45 private: | 51 private: |
| 46 int16 id_; | 52 int16 id_; |
| 47 | 53 |
| 54 static const std::wstring test_name_; |
| 55 |
| 48 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); | 56 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); |
| 49 }; | 57 }; |
| 50 | 58 |
| 59 const std::wstring MultipleThreadMain::test_name_ = L"SharedMemoryOpenThreadTest
"; |
| 60 |
| 61 // TODO(port): |
| 62 // This test requires the ability to pass file descriptors between processes. |
| 63 // We haven't done that yet in Chrome for POSIX. |
| 51 #if defined(OS_WIN) | 64 #if defined(OS_WIN) |
| 52 // Each thread will open the shared memory. Each thread will take the memory, | 65 // Each thread will open the shared memory. Each thread will take the memory, |
| 53 // and keep changing it while trying to lock it, with some small pauses in | 66 // and keep changing it while trying to lock it, with some small pauses in |
| 54 // between. Verify that each thread's value in the shared memory is always | 67 // between. Verify that each thread's value in the shared memory is always |
| 55 // correct. | 68 // correct. |
| 56 class MultipleLockThread : public PlatformThread::Delegate { | 69 class MultipleLockThread : public PlatformThread::Delegate { |
| 57 public: | 70 public: |
| 58 explicit MultipleLockThread(int id) : id_(id) {} | 71 explicit MultipleLockThread(int id) : id_(id) {} |
| 59 ~MultipleLockThread() {} | 72 ~MultipleLockThread() {} |
| 60 | 73 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 | 110 |
| 98 } // namespace | 111 } // namespace |
| 99 | 112 |
| 100 TEST(SharedMemoryTest, OpenClose) { | 113 TEST(SharedMemoryTest, OpenClose) { |
| 101 const int kDataSize = 1024; | 114 const int kDataSize = 1024; |
| 102 std::wstring test_name = L"SharedMemoryOpenCloseTest"; | 115 std::wstring test_name = L"SharedMemoryOpenCloseTest"; |
| 103 | 116 |
| 104 // Open two handles to a memory segment, confirm that they are mapped | 117 // Open two handles to a memory segment, confirm that they are mapped |
| 105 // separately yet point to the same space. | 118 // separately yet point to the same space. |
| 106 SharedMemory memory1; | 119 SharedMemory memory1; |
| 107 bool rv = memory1.Open(test_name, false); | 120 bool rv = memory1.Delete(test_name); |
| 121 EXPECT_TRUE(rv); |
| 122 rv = memory1.Delete(test_name); |
| 123 EXPECT_TRUE(rv); |
| 124 rv = memory1.Open(test_name, false); |
| 108 EXPECT_FALSE(rv); | 125 EXPECT_FALSE(rv); |
| 109 rv = memory1.Create(test_name, false, false, kDataSize); | 126 rv = memory1.Create(test_name, false, false, kDataSize); |
| 110 EXPECT_TRUE(rv); | 127 EXPECT_TRUE(rv); |
| 111 rv = memory1.Map(kDataSize); | 128 rv = memory1.Map(kDataSize); |
| 112 EXPECT_TRUE(rv); | 129 EXPECT_TRUE(rv); |
| 113 SharedMemory memory2; | 130 SharedMemory memory2; |
| 114 rv = memory2.Open(test_name, false); | 131 rv = memory2.Open(test_name, false); |
| 115 EXPECT_TRUE(rv); | 132 EXPECT_TRUE(rv); |
| 116 rv = memory2.Map(kDataSize); | 133 rv = memory2.Map(kDataSize); |
| 117 EXPECT_TRUE(rv); | 134 EXPECT_TRUE(rv); |
| 118 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. | 135 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. |
| 119 | 136 |
| 120 // Make sure we don't segfault. (it actually happened!) | 137 // Make sure we don't segfault. (it actually happened!) |
| 121 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); | 138 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); |
| 122 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); | 139 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); |
| 123 | 140 |
| 124 // Write data to the first memory segment, verify contents of second. | 141 // Write data to the first memory segment, verify contents of second. |
| 125 memset(memory1.memory(), '1', kDataSize); | 142 memset(memory1.memory(), '1', kDataSize); |
| 126 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); | 143 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); |
| 127 | 144 |
| 128 // Close the first memory segment, and verify the second has the right data. | 145 // Close the first memory segment, and verify the second has the right data. |
| 129 memory1.Close(); | 146 memory1.Close(); |
| 130 char *start_ptr = static_cast<char *>(memory2.memory()); | 147 char *start_ptr = static_cast<char *>(memory2.memory()); |
| 131 char *end_ptr = start_ptr + kDataSize; | 148 char *end_ptr = start_ptr + kDataSize; |
| 132 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) | 149 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) |
| 133 EXPECT_EQ(*ptr, '1'); | 150 EXPECT_EQ(*ptr, '1'); |
| 134 | 151 |
| 135 // Close the second memory segment. | 152 // Close the second memory segment. |
| 136 memory2.Close(); | 153 memory2.Close(); |
| 154 |
| 155 rv = memory1.Delete(test_name); |
| 156 EXPECT_TRUE(rv); |
| 157 rv = memory2.Delete(test_name); |
| 158 EXPECT_TRUE(rv); |
| 137 } | 159 } |
| 138 | 160 |
| 139 #if defined(OS_WIN) | |
| 140 // Create a set of 5 threads to each open a shared memory segment and write to | 161 // Create a set of 5 threads to each open a shared memory segment and write to |
| 141 // it. Verify that they are always reading/writing consistent data. | 162 // it. Verify that they are always reading/writing consistent data. |
| 142 TEST(SharedMemoryTest, MultipleThreads) { | 163 TEST(SharedMemoryTest, MultipleThreads) { |
| 164 MultipleThreadMain::CleanUp(); |
| 143 PlatformThreadHandle thread_handles[kNumThreads]; | 165 PlatformThreadHandle thread_handles[kNumThreads]; |
| 144 MultipleThreadMain* thread_delegates[kNumThreads]; | 166 MultipleThreadMain* thread_delegates[kNumThreads]; |
| 145 | 167 |
| 146 // Spawn the threads. | 168 // Spawn the threads. |
| 147 for (int16 index = 0; index < kNumThreads; index++) { | 169 for (int16 index = 0; index < kNumThreads; index++) { |
| 148 PlatformThreadHandle pth; | 170 PlatformThreadHandle pth; |
| 149 thread_delegates[index] = new MultipleThreadMain(index); | 171 thread_delegates[index] = new MultipleThreadMain(index); |
| 150 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); | 172 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); |
| 151 thread_handles[index] = pth; | 173 thread_handles[index] = pth; |
| 152 } | 174 } |
| 153 | 175 |
| 154 // Wait for the threads to finish. | 176 // Wait for the threads to finish. |
| 155 for (int index = 0; index < kNumThreads; index++) { | 177 for (int index = 0; index < kNumThreads; index++) { |
| 156 PlatformThread::Join(thread_handles[index]); | 178 PlatformThread::Join(thread_handles[index]); |
| 157 delete thread_delegates[index]; | 179 delete thread_delegates[index]; |
| 158 } | 180 } |
| 181 |
| 182 MultipleThreadMain::CleanUp(); |
| 159 } | 183 } |
| 160 | 184 |
| 185 // TODO(port): this test requires the MultipleLockThread class |
| 186 // (defined above), which requires the ability to pass file |
| 187 // descriptors between processes. We haven't done that yet in Chrome |
| 188 // for POSIX. |
| 189 #if defined(OS_WIN) |
| 161 // Create a set of threads to each open a shared memory segment and write to it | 190 // Create a set of threads to each open a shared memory segment and write to it |
| 162 // with the lock held. Verify that they are always reading/writing consistent | 191 // with the lock held. Verify that they are always reading/writing consistent |
| 163 // data. | 192 // data. |
| 164 TEST(SharedMemoryTest, Lock) { | 193 TEST(SharedMemoryTest, Lock) { |
| 165 PlatformThreadHandle thread_handles[kNumThreads]; | 194 PlatformThreadHandle thread_handles[kNumThreads]; |
| 166 MultipleLockThread* thread_delegates[kNumThreads]; | 195 MultipleLockThread* thread_delegates[kNumThreads]; |
| 167 | 196 |
| 168 // Spawn the threads. | 197 // Spawn the threads. |
| 169 for (int index = 0; index < kNumThreads; ++index) { | 198 for (int index = 0; index < kNumThreads; ++index) { |
| 170 PlatformThreadHandle pth; | 199 PlatformThreadHandle pth; |
| 171 thread_delegates[index] = new MultipleLockThread(index); | 200 thread_delegates[index] = new MultipleLockThread(index); |
| 172 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); | 201 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); |
| 173 thread_handles[index] = pth; | 202 thread_handles[index] = pth; |
| 174 } | 203 } |
| 175 | 204 |
| 176 // Wait for the threads to finish. | 205 // Wait for the threads to finish. |
| 177 for (int index = 0; index < kNumThreads; ++index) { | 206 for (int index = 0; index < kNumThreads; ++index) { |
| 178 PlatformThread::Join(thread_handles[index]); | 207 PlatformThread::Join(thread_handles[index]); |
| 179 delete thread_delegates[index]; | 208 delete thread_delegates[index]; |
| 180 } | 209 } |
| 181 } | 210 } |
| 182 #endif | 211 #endif |
| 183 | 212 |
| 213 // Allocate private (unique) shared memory with an empty string for a |
| 214 // name. Make sure several of them don't point to the same thing as |
| 215 // we might expect if the names are equal. |
| 216 TEST(SharedMemoryTest, AnonymousPrivate) { |
| 217 int i, j; |
| 218 int count = 4; |
| 219 bool rv; |
| 220 const int kDataSize = 8192; |
| 221 |
| 222 SharedMemory* memories = new SharedMemory[count]; |
| 223 int **pointers = new int*[count]; |
| 224 ASSERT_TRUE(memories); |
| 225 ASSERT_TRUE(pointers); |
| 226 |
| 227 for (i = 0; i < count; i++) { |
| 228 rv = memories[i].Create(L"", false, true, kDataSize); |
| 229 EXPECT_TRUE(rv); |
| 230 rv = memories[i].Map(kDataSize); |
| 231 EXPECT_TRUE(rv); |
| 232 int *ptr = static_cast<int*>(memories[i].memory()); |
| 233 EXPECT_TRUE(ptr); |
| 234 pointers[i] = ptr; |
| 235 } |
| 236 |
| 237 for (i = 0; i < count; i++) { |
| 238 // zero out the first int in each except for i; for that one, make it 100. |
| 239 for (j = 0; j < count; j++) { |
| 240 if (i == j) |
| 241 pointers[j][0] = 100; |
| 242 else |
| 243 pointers[j][0] = 0; |
| 244 } |
| 245 // make sure there is no bleeding of the 100 into the other pointers |
| 246 for (j = 0; j < count; j++) { |
| 247 if (i == j) |
| 248 EXPECT_EQ(100, pointers[j][0]); |
| 249 else |
| 250 EXPECT_EQ(0, pointers[j][0]); |
| 251 } |
| 252 } |
| 253 |
| 254 for (int i = 0; i < count; i++) { |
| 255 memories[i].Close(); |
| 256 } |
| 257 } |
| 258 |
| 259 |
| 184 } // namespace base | 260 } // namespace base |
| OLD | NEW |