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 |