license.bot | f003cfe | 2008-08-24 09:55:55 +0900 | [diff] [blame] | 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 |
| 3 | // found in the LICENSE file. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 4 | |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 5 | #include "base/basictypes.h" |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 6 | #include "base/multiprocess_test.h" |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 7 | #include "base/platform_thread.h" |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 8 | #include "base/scoped_nsautorelease_pool.h" |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 9 | #include "base/shared_memory.h" |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 10 | #include "base/scoped_ptr.h" |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 11 | #include "testing/gtest/include/gtest/gtest.h" |
| 12 | |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 13 | static const int kNumThreads = 5; |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 14 | static const int kNumTasks = 5; |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 15 | |
brettw@google.com | c60d989 | 2008-11-14 12:25:15 +0900 | [diff] [blame] | 16 | namespace base { |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 17 | |
brettw@google.com | c60d989 | 2008-11-14 12:25:15 +0900 | [diff] [blame] | 18 | namespace { |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 19 | |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 20 | // Each thread will open the shared memory. Each thread will take a different 4 |
| 21 | // byte int pointer, and keep changing it, with some small pauses in between. |
| 22 | // Verify that each thread's value in the shared memory is always correct. |
| 23 | class MultipleThreadMain : public PlatformThread::Delegate { |
| 24 | public: |
| 25 | explicit MultipleThreadMain(int16 id) : id_(id) {} |
| 26 | ~MultipleThreadMain() {} |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 27 | |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 28 | static void CleanUp() { |
| 29 | SharedMemory memory; |
maruel@chromium.org | 8fe7adc | 2009-03-04 00:01:12 +0900 | [diff] [blame] | 30 | memory.Delete(s_test_name_); |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 31 | } |
| 32 | |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 33 | // PlatformThread::Delegate interface. |
| 34 | void ThreadMain() { |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 35 | ScopedNSAutoreleasePool pool; // noop if not OSX |
jam@chromium.org | e74ca94 | 2010-02-17 08:58:27 +0900 | [diff] [blame^] | 36 | const uint32 kDataSize = 1024; |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 37 | SharedMemory memory; |
maruel@chromium.org | 8fe7adc | 2009-03-04 00:01:12 +0900 | [diff] [blame] | 38 | bool rv = memory.Create(s_test_name_, false, true, kDataSize); |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 39 | EXPECT_TRUE(rv); |
| 40 | rv = memory.Map(kDataSize); |
| 41 | EXPECT_TRUE(rv); |
| 42 | int *ptr = static_cast<int*>(memory.memory()) + id_; |
| 43 | EXPECT_EQ(*ptr, 0); |
| 44 | |
| 45 | for (int idx = 0; idx < 100; idx++) { |
| 46 | *ptr = idx; |
| 47 | PlatformThread::Sleep(1); // Short wait. |
| 48 | EXPECT_EQ(*ptr, idx); |
| 49 | } |
| 50 | |
| 51 | memory.Close(); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 52 | } |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 53 | |
| 54 | private: |
| 55 | int16 id_; |
| 56 | |
maruel@chromium.org | 8fe7adc | 2009-03-04 00:01:12 +0900 | [diff] [blame] | 57 | static const wchar_t* const s_test_name_; |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 58 | |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 59 | DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain); |
| 60 | }; |
| 61 | |
maruel@chromium.org | 8fe7adc | 2009-03-04 00:01:12 +0900 | [diff] [blame] | 62 | const wchar_t* const MultipleThreadMain::s_test_name_ = |
| 63 | L"SharedMemoryOpenThreadTest"; |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 64 | |
| 65 | // TODO(port): |
| 66 | // This test requires the ability to pass file descriptors between processes. |
| 67 | // We haven't done that yet in Chrome for POSIX. |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 68 | #if defined(OS_WIN) |
| 69 | // Each thread will open the shared memory. Each thread will take the memory, |
| 70 | // and keep changing it while trying to lock it, with some small pauses in |
| 71 | // between. Verify that each thread's value in the shared memory is always |
| 72 | // correct. |
| 73 | class MultipleLockThread : public PlatformThread::Delegate { |
| 74 | public: |
| 75 | explicit MultipleLockThread(int id) : id_(id) {} |
| 76 | ~MultipleLockThread() {} |
| 77 | |
| 78 | // PlatformThread::Delegate interface. |
| 79 | void ThreadMain() { |
jam@chromium.org | e74ca94 | 2010-02-17 08:58:27 +0900 | [diff] [blame^] | 80 | const uint32 kDataSize = sizeof(int); |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 81 | SharedMemoryHandle handle = NULL; |
| 82 | { |
| 83 | SharedMemory memory1; |
| 84 | EXPECT_TRUE(memory1.Create(L"SharedMemoryMultipleLockThreadTest", |
| 85 | false, true, kDataSize)); |
| 86 | EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); |
| 87 | // TODO(paulg): Implement this once we have a posix version of |
| 88 | // SharedMemory::ShareToProcess. |
| 89 | EXPECT_TRUE(true); |
| 90 | } |
| 91 | |
| 92 | SharedMemory memory2(handle, false); |
| 93 | EXPECT_TRUE(memory2.Map(kDataSize)); |
| 94 | volatile int* const ptr = static_cast<int*>(memory2.memory()); |
| 95 | |
| 96 | for (int idx = 0; idx < 20; idx++) { |
| 97 | memory2.Lock(); |
| 98 | int i = (id_ << 16) + idx; |
| 99 | *ptr = i; |
| 100 | PlatformThread::Sleep(1); // Short wait. |
| 101 | EXPECT_EQ(*ptr, i); |
| 102 | memory2.Unlock(); |
| 103 | } |
| 104 | |
| 105 | memory2.Close(); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 106 | } |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 107 | |
| 108 | private: |
| 109 | int id_; |
| 110 | |
| 111 | DISALLOW_COPY_AND_ASSIGN(MultipleLockThread); |
| 112 | }; |
| 113 | #endif |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 114 | |
| 115 | } // namespace |
| 116 | |
| 117 | TEST(SharedMemoryTest, OpenClose) { |
jam@chromium.org | e74ca94 | 2010-02-17 08:58:27 +0900 | [diff] [blame^] | 118 | const uint32 kDataSize = 1024; |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 119 | std::wstring test_name = L"SharedMemoryOpenCloseTest"; |
| 120 | |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 121 | // Open two handles to a memory segment, confirm that they are mapped |
| 122 | // separately yet point to the same space. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 123 | SharedMemory memory1; |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 124 | bool rv = memory1.Delete(test_name); |
| 125 | EXPECT_TRUE(rv); |
| 126 | rv = memory1.Delete(test_name); |
| 127 | EXPECT_TRUE(rv); |
| 128 | rv = memory1.Open(test_name, false); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 129 | EXPECT_FALSE(rv); |
| 130 | rv = memory1.Create(test_name, false, false, kDataSize); |
| 131 | EXPECT_TRUE(rv); |
| 132 | rv = memory1.Map(kDataSize); |
| 133 | EXPECT_TRUE(rv); |
| 134 | SharedMemory memory2; |
| 135 | rv = memory2.Open(test_name, false); |
| 136 | EXPECT_TRUE(rv); |
| 137 | rv = memory2.Map(kDataSize); |
| 138 | EXPECT_TRUE(rv); |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 139 | EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 140 | |
maruel@google.com | 76cff08 | 2008-09-13 02:41:52 +0900 | [diff] [blame] | 141 | // Make sure we don't segfault. (it actually happened!) |
| 142 | ASSERT_NE(memory1.memory(), static_cast<void*>(NULL)); |
| 143 | ASSERT_NE(memory2.memory(), static_cast<void*>(NULL)); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 144 | |
| 145 | // Write data to the first memory segment, verify contents of second. |
| 146 | memset(memory1.memory(), '1', kDataSize); |
| 147 | EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); |
| 148 | |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 149 | // Close the first memory segment, and verify the second has the right data. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 150 | memory1.Close(); |
| 151 | char *start_ptr = static_cast<char *>(memory2.memory()); |
| 152 | char *end_ptr = start_ptr + kDataSize; |
| 153 | for (char* ptr = start_ptr; ptr < end_ptr; ptr++) |
| 154 | EXPECT_EQ(*ptr, '1'); |
| 155 | |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 156 | // Close the second memory segment. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 157 | memory2.Close(); |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 158 | |
| 159 | rv = memory1.Delete(test_name); |
| 160 | EXPECT_TRUE(rv); |
| 161 | rv = memory2.Delete(test_name); |
| 162 | EXPECT_TRUE(rv); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 163 | } |
| 164 | |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 165 | // Create a set of N threads to each open a shared memory segment and write to |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 166 | // it. Verify that they are always reading/writing consistent data. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 167 | TEST(SharedMemoryTest, MultipleThreads) { |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 168 | MultipleThreadMain::CleanUp(); |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 169 | // On POSIX we have a problem when 2 threads try to create the shmem |
| 170 | // (a file) at exactly the same time, since create both creates the |
| 171 | // file and zerofills it. We solve the problem for this unit test |
| 172 | // (make it not flaky) by starting with 1 thread, then |
| 173 | // intentionally don't clean up its shmem before running with |
| 174 | // kNumThreads. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 175 | |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 176 | int threadcounts[] = { 1, kNumThreads }; |
| 177 | for (size_t i = 0; i < sizeof(threadcounts) / sizeof(threadcounts); i++) { |
| 178 | int numthreads = threadcounts[i]; |
| 179 | scoped_array<PlatformThreadHandle> thread_handles; |
| 180 | scoped_array<MultipleThreadMain*> thread_delegates; |
| 181 | |
| 182 | thread_handles.reset(new PlatformThreadHandle[numthreads]); |
| 183 | thread_delegates.reset(new MultipleThreadMain*[numthreads]); |
| 184 | |
| 185 | // Spawn the threads. |
| 186 | for (int16 index = 0; index < numthreads; index++) { |
| 187 | PlatformThreadHandle pth; |
| 188 | thread_delegates[index] = new MultipleThreadMain(index); |
| 189 | EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); |
| 190 | thread_handles[index] = pth; |
| 191 | } |
| 192 | |
| 193 | // Wait for the threads to finish. |
| 194 | for (int index = 0; index < numthreads; index++) { |
| 195 | PlatformThread::Join(thread_handles[index]); |
| 196 | delete thread_delegates[index]; |
| 197 | } |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 198 | } |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 199 | MultipleThreadMain::CleanUp(); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 200 | } |
| 201 | |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 202 | // TODO(port): this test requires the MultipleLockThread class |
| 203 | // (defined above), which requires the ability to pass file |
| 204 | // descriptors between processes. We haven't done that yet in Chrome |
| 205 | // for POSIX. |
| 206 | #if defined(OS_WIN) |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 207 | // Create a set of threads to each open a shared memory segment and write to it |
| 208 | // with the lock held. Verify that they are always reading/writing consistent |
| 209 | // data. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 210 | TEST(SharedMemoryTest, Lock) { |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 211 | PlatformThreadHandle thread_handles[kNumThreads]; |
| 212 | MultipleLockThread* thread_delegates[kNumThreads]; |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 213 | |
| 214 | // Spawn the threads. |
| 215 | for (int index = 0; index < kNumThreads; ++index) { |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 216 | PlatformThreadHandle pth; |
| 217 | thread_delegates[index] = new MultipleLockThread(index); |
| 218 | EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth)); |
| 219 | thread_handles[index] = pth; |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 220 | } |
| 221 | |
| 222 | // Wait for the threads to finish. |
| 223 | for (int index = 0; index < kNumThreads; ++index) { |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 224 | PlatformThread::Join(thread_handles[index]); |
| 225 | delete thread_delegates[index]; |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 226 | } |
| 227 | } |
paulg@google.com | 78da663 | 2008-09-11 09:31:43 +0900 | [diff] [blame] | 228 | #endif |
brettw@google.com | c60d989 | 2008-11-14 12:25:15 +0900 | [diff] [blame] | 229 | |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 230 | // Allocate private (unique) shared memory with an empty string for a |
| 231 | // name. Make sure several of them don't point to the same thing as |
| 232 | // we might expect if the names are equal. |
| 233 | TEST(SharedMemoryTest, AnonymousPrivate) { |
| 234 | int i, j; |
| 235 | int count = 4; |
| 236 | bool rv; |
jam@chromium.org | e74ca94 | 2010-02-17 08:58:27 +0900 | [diff] [blame^] | 237 | const uint32 kDataSize = 8192; |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 238 | |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 239 | scoped_array<SharedMemory> memories(new SharedMemory[count]); |
| 240 | scoped_array<int*> pointers(new int*[count]); |
| 241 | ASSERT_TRUE(memories.get()); |
| 242 | ASSERT_TRUE(pointers.get()); |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 243 | |
| 244 | for (i = 0; i < count; i++) { |
| 245 | rv = memories[i].Create(L"", false, true, kDataSize); |
| 246 | EXPECT_TRUE(rv); |
| 247 | rv = memories[i].Map(kDataSize); |
| 248 | EXPECT_TRUE(rv); |
| 249 | int *ptr = static_cast<int*>(memories[i].memory()); |
| 250 | EXPECT_TRUE(ptr); |
| 251 | pointers[i] = ptr; |
| 252 | } |
| 253 | |
| 254 | for (i = 0; i < count; i++) { |
| 255 | // zero out the first int in each except for i; for that one, make it 100. |
| 256 | for (j = 0; j < count; j++) { |
| 257 | if (i == j) |
| 258 | pointers[j][0] = 100; |
| 259 | else |
| 260 | pointers[j][0] = 0; |
| 261 | } |
| 262 | // make sure there is no bleeding of the 100 into the other pointers |
| 263 | for (j = 0; j < count; j++) { |
| 264 | if (i == j) |
| 265 | EXPECT_EQ(100, pointers[j][0]); |
| 266 | else |
| 267 | EXPECT_EQ(0, pointers[j][0]); |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | for (int i = 0; i < count; i++) { |
| 272 | memories[i].Close(); |
| 273 | } |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 274 | |
| 275 | } |
| 276 | |
| 277 | |
| 278 | // On POSIX it is especially important we test shmem across processes, |
| 279 | // not just across threads. But the test is enabled on all platforms. |
| 280 | class SharedMemoryProcessTest : public MultiProcessTest { |
| 281 | public: |
| 282 | |
| 283 | static void CleanUp() { |
| 284 | SharedMemory memory; |
maruel@chromium.org | 8fe7adc | 2009-03-04 00:01:12 +0900 | [diff] [blame] | 285 | memory.Delete(s_test_name_); |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 286 | } |
| 287 | |
| 288 | static int TaskTestMain() { |
| 289 | int errors = 0; |
| 290 | ScopedNSAutoreleasePool pool; // noop if not OSX |
jam@chromium.org | e74ca94 | 2010-02-17 08:58:27 +0900 | [diff] [blame^] | 291 | const uint32 kDataSize = 1024; |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 292 | SharedMemory memory; |
maruel@chromium.org | 8fe7adc | 2009-03-04 00:01:12 +0900 | [diff] [blame] | 293 | bool rv = memory.Create(s_test_name_, false, true, kDataSize); |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 294 | EXPECT_TRUE(rv); |
| 295 | if (rv != true) |
| 296 | errors++; |
| 297 | rv = memory.Map(kDataSize); |
| 298 | EXPECT_TRUE(rv); |
| 299 | if (rv != true) |
| 300 | errors++; |
| 301 | int *ptr = static_cast<int*>(memory.memory()); |
| 302 | |
| 303 | for (int idx = 0; idx < 20; idx++) { |
| 304 | memory.Lock(); |
| 305 | int i = (1 << 16) + idx; |
| 306 | *ptr = i; |
| 307 | PlatformThread::Sleep(10); // Short wait. |
| 308 | if (*ptr != i) |
| 309 | errors++; |
| 310 | memory.Unlock(); |
| 311 | } |
| 312 | |
| 313 | memory.Close(); |
| 314 | return errors; |
| 315 | } |
| 316 | |
| 317 | private: |
maruel@chromium.org | 8fe7adc | 2009-03-04 00:01:12 +0900 | [diff] [blame] | 318 | static const wchar_t* const s_test_name_; |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 319 | }; |
| 320 | |
maruel@chromium.org | f07658b | 2009-03-04 00:05:48 +0900 | [diff] [blame] | 321 | const wchar_t* const SharedMemoryProcessTest::s_test_name_ = L"MPMem"; |
jrg@chromium.org | 81e2260 | 2009-02-06 04:04:34 +0900 | [diff] [blame] | 322 | |
| 323 | |
| 324 | TEST_F(SharedMemoryProcessTest, Tasks) { |
| 325 | SharedMemoryProcessTest::CleanUp(); |
| 326 | |
| 327 | base::ProcessHandle handles[kNumTasks]; |
| 328 | for (int index = 0; index < kNumTasks; ++index) { |
| 329 | handles[index] = SpawnChild(L"SharedMemoryTestMain"); |
| 330 | } |
| 331 | |
| 332 | int exit_code = 0; |
| 333 | for (int index = 0; index < kNumTasks; ++index) { |
| 334 | EXPECT_TRUE(base::WaitForExitCode(handles[index], &exit_code)); |
| 335 | EXPECT_TRUE(exit_code == 0); |
| 336 | } |
| 337 | |
| 338 | SharedMemoryProcessTest::CleanUp(); |
| 339 | } |
| 340 | |
| 341 | MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) { |
| 342 | return SharedMemoryProcessTest::TaskTestMain(); |
jrg@chromium.org | d505c3a | 2009-02-04 09:58:39 +0900 | [diff] [blame] | 343 | } |
| 344 | |
| 345 | |
brettw@google.com | c60d989 | 2008-11-14 12:25:15 +0900 | [diff] [blame] | 346 | } // namespace base |