blob: fd88274b5458748535539e3a7e7eb2b87ee3d733 [file] [log] [blame]
evan@chromium.org3c0bc352012-02-14 09:29:14 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botf003cfe2008-08-24 09:55:55 +09002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit3f4a7322008-07-27 06:49:38 +09004
paulg@google.com78da6632008-09-11 09:31:43 +09005#include "base/basictypes.h"
ensonic@google.com23b1cc02011-12-07 00:09:56 +09006#if defined(OS_MACOSX)
7#include "base/mac/scoped_nsautorelease_pool.h"
8#endif
levin@chromium.org5c528682011-03-28 10:54:15 +09009#include "base/memory/scoped_ptr.h"
initial.commit3f4a7322008-07-27 06:49:38 +090010#include "base/shared_memory.h"
brettw@chromium.org1c8c3be2010-08-18 04:40:11 +090011#include "base/test/multiprocess_test.h"
brettw@chromium.org61391822011-01-01 05:02:16 +090012#include "base/threading/platform_thread.h"
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +090013#include "base/time.h"
initial.commit3f4a7322008-07-27 06:49:38 +090014#include "testing/gtest/include/gtest/gtest.h"
brettw@chromium.org1c8c3be2010-08-18 04:40:11 +090015#include "testing/multiprocess_func_list.h"
initial.commit3f4a7322008-07-27 06:49:38 +090016
jam@chromium.org9730fbd2011-10-29 12:44:44 +090017#if defined(OS_MACOSX)
18#include "base/mac/scoped_nsautorelease_pool.h"
19#endif
20
mcgrathr@chromium.org45910f72011-12-02 08:19:31 +090021#if defined(OS_POSIX)
22#include <sys/mman.h>
23#endif
24
paulg@google.com78da6632008-09-11 09:31:43 +090025static const int kNumThreads = 5;
jrg@chromium.org81e22602009-02-06 04:04:34 +090026static const int kNumTasks = 5;
initial.commit3f4a7322008-07-27 06:49:38 +090027
brettw@google.comc60d9892008-11-14 12:25:15 +090028namespace base {
initial.commit3f4a7322008-07-27 06:49:38 +090029
brettw@google.comc60d9892008-11-14 12:25:15 +090030namespace {
initial.commit3f4a7322008-07-27 06:49:38 +090031
paulg@google.com78da6632008-09-11 09:31:43 +090032// Each thread will open the shared memory. Each thread will take a different 4
33// byte int pointer, and keep changing it, with some small pauses in between.
34// Verify that each thread's value in the shared memory is always correct.
35class MultipleThreadMain : public PlatformThread::Delegate {
36 public:
37 explicit MultipleThreadMain(int16 id) : id_(id) {}
38 ~MultipleThreadMain() {}
initial.commit3f4a7322008-07-27 06:49:38 +090039
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +090040 static void CleanUp() {
41 SharedMemory memory;
maruel@chromium.org8fe7adc2009-03-04 00:01:12 +090042 memory.Delete(s_test_name_);
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +090043 }
44
paulg@google.com78da6632008-09-11 09:31:43 +090045 // PlatformThread::Delegate interface.
46 void ThreadMain() {
jam@chromium.org9730fbd2011-10-29 12:44:44 +090047#if defined(OS_MACOSX)
48 mac::ScopedNSAutoreleasePool pool;
49#endif
jam@chromium.orge74ca942010-02-17 08:58:27 +090050 const uint32 kDataSize = 1024;
paulg@google.com78da6632008-09-11 09:31:43 +090051 SharedMemory memory;
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +090052 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
paulg@google.com78da6632008-09-11 09:31:43 +090053 EXPECT_TRUE(rv);
54 rv = memory.Map(kDataSize);
55 EXPECT_TRUE(rv);
56 int *ptr = static_cast<int*>(memory.memory()) + id_;
thakis@chromium.orgf75ccb42011-10-14 16:28:03 +090057 EXPECT_EQ(0, *ptr);
paulg@google.com78da6632008-09-11 09:31:43 +090058
59 for (int idx = 0; idx < 100; idx++) {
60 *ptr = idx;
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +090061 PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
paulg@google.com78da6632008-09-11 09:31:43 +090062 EXPECT_EQ(*ptr, idx);
63 }
thakis@chromium.orgf75ccb42011-10-14 16:28:03 +090064 // Reset back to 0 for the next test that uses the same name.
65 *ptr = 0;
paulg@google.com78da6632008-09-11 09:31:43 +090066
67 memory.Close();
initial.commit3f4a7322008-07-27 06:49:38 +090068 }
paulg@google.com78da6632008-09-11 09:31:43 +090069
70 private:
71 int16 id_;
72
evan@chromium.org56756992010-09-30 05:32:22 +090073 static const char* const s_test_name_;
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +090074
paulg@google.com78da6632008-09-11 09:31:43 +090075 DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
76};
77
evan@chromium.org56756992010-09-30 05:32:22 +090078const char* const MultipleThreadMain::s_test_name_ =
79 "SharedMemoryOpenThreadTest";
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +090080
81// TODO(port):
82// This test requires the ability to pass file descriptors between processes.
83// We haven't done that yet in Chrome for POSIX.
paulg@google.com78da6632008-09-11 09:31:43 +090084#if defined(OS_WIN)
85// Each thread will open the shared memory. Each thread will take the memory,
86// and keep changing it while trying to lock it, with some small pauses in
87// between. Verify that each thread's value in the shared memory is always
88// correct.
89class MultipleLockThread : public PlatformThread::Delegate {
90 public:
91 explicit MultipleLockThread(int id) : id_(id) {}
92 ~MultipleLockThread() {}
93
94 // PlatformThread::Delegate interface.
95 void ThreadMain() {
jam@chromium.orge74ca942010-02-17 08:58:27 +090096 const uint32 kDataSize = sizeof(int);
paulg@google.com78da6632008-09-11 09:31:43 +090097 SharedMemoryHandle handle = NULL;
98 {
99 SharedMemory memory1;
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900100 EXPECT_TRUE(memory1.CreateNamed("SharedMemoryMultipleLockThreadTest",
101 true, kDataSize));
paulg@google.com78da6632008-09-11 09:31:43 +0900102 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle));
103 // TODO(paulg): Implement this once we have a posix version of
104 // SharedMemory::ShareToProcess.
105 EXPECT_TRUE(true);
106 }
107
108 SharedMemory memory2(handle, false);
109 EXPECT_TRUE(memory2.Map(kDataSize));
110 volatile int* const ptr = static_cast<int*>(memory2.memory());
111
112 for (int idx = 0; idx < 20; idx++) {
113 memory2.Lock();
114 int i = (id_ << 16) + idx;
115 *ptr = i;
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900116 PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
paulg@google.com78da6632008-09-11 09:31:43 +0900117 EXPECT_EQ(*ptr, i);
118 memory2.Unlock();
119 }
120
121 memory2.Close();
initial.commit3f4a7322008-07-27 06:49:38 +0900122 }
paulg@google.com78da6632008-09-11 09:31:43 +0900123
124 private:
125 int id_;
126
127 DISALLOW_COPY_AND_ASSIGN(MultipleLockThread);
128};
129#endif
initial.commit3f4a7322008-07-27 06:49:38 +0900130
131} // namespace
132
133TEST(SharedMemoryTest, OpenClose) {
jam@chromium.orge74ca942010-02-17 08:58:27 +0900134 const uint32 kDataSize = 1024;
evan@chromium.org56756992010-09-30 05:32:22 +0900135 std::string test_name = "SharedMemoryOpenCloseTest";
initial.commit3f4a7322008-07-27 06:49:38 +0900136
paulg@google.com78da6632008-09-11 09:31:43 +0900137 // Open two handles to a memory segment, confirm that they are mapped
138 // separately yet point to the same space.
initial.commit3f4a7322008-07-27 06:49:38 +0900139 SharedMemory memory1;
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900140 bool rv = memory1.Delete(test_name);
141 EXPECT_TRUE(rv);
142 rv = memory1.Delete(test_name);
143 EXPECT_TRUE(rv);
144 rv = memory1.Open(test_name, false);
initial.commit3f4a7322008-07-27 06:49:38 +0900145 EXPECT_FALSE(rv);
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900146 rv = memory1.CreateNamed(test_name, false, kDataSize);
initial.commit3f4a7322008-07-27 06:49:38 +0900147 EXPECT_TRUE(rv);
148 rv = memory1.Map(kDataSize);
149 EXPECT_TRUE(rv);
150 SharedMemory memory2;
151 rv = memory2.Open(test_name, false);
152 EXPECT_TRUE(rv);
153 rv = memory2.Map(kDataSize);
154 EXPECT_TRUE(rv);
paulg@google.com78da6632008-09-11 09:31:43 +0900155 EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers.
initial.commit3f4a7322008-07-27 06:49:38 +0900156
maruel@google.com76cff082008-09-13 02:41:52 +0900157 // Make sure we don't segfault. (it actually happened!)
158 ASSERT_NE(memory1.memory(), static_cast<void*>(NULL));
159 ASSERT_NE(memory2.memory(), static_cast<void*>(NULL));
initial.commit3f4a7322008-07-27 06:49:38 +0900160
161 // Write data to the first memory segment, verify contents of second.
162 memset(memory1.memory(), '1', kDataSize);
163 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
164
paulg@google.com78da6632008-09-11 09:31:43 +0900165 // Close the first memory segment, and verify the second has the right data.
initial.commit3f4a7322008-07-27 06:49:38 +0900166 memory1.Close();
167 char *start_ptr = static_cast<char *>(memory2.memory());
168 char *end_ptr = start_ptr + kDataSize;
169 for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
170 EXPECT_EQ(*ptr, '1');
171
paulg@google.com78da6632008-09-11 09:31:43 +0900172 // Close the second memory segment.
initial.commit3f4a7322008-07-27 06:49:38 +0900173 memory2.Close();
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900174
175 rv = memory1.Delete(test_name);
176 EXPECT_TRUE(rv);
177 rv = memory2.Delete(test_name);
178 EXPECT_TRUE(rv);
initial.commit3f4a7322008-07-27 06:49:38 +0900179}
180
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900181TEST(SharedMemoryTest, OpenExclusive) {
182 const uint32 kDataSize = 1024;
183 const uint32 kDataSize2 = 2048;
184 std::ostringstream test_name_stream;
185 test_name_stream << "SharedMemoryOpenExclusiveTest."
186 << Time::Now().ToDoubleT();
187 std::string test_name = test_name_stream.str();
188
189 // Open two handles to a memory segment and check that open_existing works
190 // as expected.
191 SharedMemory memory1;
192 bool rv = memory1.CreateNamed(test_name, false, kDataSize);
193 EXPECT_TRUE(rv);
194
195 // Memory1 knows it's size because it created it.
196 EXPECT_EQ(memory1.created_size(), kDataSize);
197
198 rv = memory1.Map(kDataSize);
199 EXPECT_TRUE(rv);
200
201 memset(memory1.memory(), 'G', kDataSize);
202
203 SharedMemory memory2;
204 // Should not be able to create if openExisting is false.
205 rv = memory2.CreateNamed(test_name, false, kDataSize2);
206 EXPECT_FALSE(rv);
207
208 // Should be able to create with openExisting true.
209 rv = memory2.CreateNamed(test_name, true, kDataSize2);
210 EXPECT_TRUE(rv);
211
212 // Memory2 shouldn't know the size because we didn't create it.
213 EXPECT_EQ(memory2.created_size(), 0U);
214
215 // We should be able to map the original size.
216 rv = memory2.Map(kDataSize);
217 EXPECT_TRUE(rv);
218
219 // Verify that opening memory2 didn't truncate or delete memory 1.
220 char *start_ptr = static_cast<char *>(memory2.memory());
221 char *end_ptr = start_ptr + kDataSize;
222 for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
223 EXPECT_EQ(*ptr, 'G');
224 }
225
226 memory1.Close();
227 memory2.Close();
228
229 rv = memory1.Delete(test_name);
230 EXPECT_TRUE(rv);
231}
232
jrg@chromium.org81e22602009-02-06 04:04:34 +0900233// Create a set of N threads to each open a shared memory segment and write to
paulg@google.com78da6632008-09-11 09:31:43 +0900234// it. Verify that they are always reading/writing consistent data.
initial.commit3f4a7322008-07-27 06:49:38 +0900235TEST(SharedMemoryTest, MultipleThreads) {
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900236 MultipleThreadMain::CleanUp();
jrg@chromium.org81e22602009-02-06 04:04:34 +0900237 // On POSIX we have a problem when 2 threads try to create the shmem
238 // (a file) at exactly the same time, since create both creates the
239 // file and zerofills it. We solve the problem for this unit test
240 // (make it not flaky) by starting with 1 thread, then
241 // intentionally don't clean up its shmem before running with
242 // kNumThreads.
initial.commit3f4a7322008-07-27 06:49:38 +0900243
jrg@chromium.org81e22602009-02-06 04:04:34 +0900244 int threadcounts[] = { 1, kNumThreads };
thakis@chromium.orgf75ccb42011-10-14 16:28:03 +0900245 for (size_t i = 0; i < arraysize(threadcounts); i++) {
jrg@chromium.org81e22602009-02-06 04:04:34 +0900246 int numthreads = threadcounts[i];
247 scoped_array<PlatformThreadHandle> thread_handles;
248 scoped_array<MultipleThreadMain*> thread_delegates;
249
250 thread_handles.reset(new PlatformThreadHandle[numthreads]);
251 thread_delegates.reset(new MultipleThreadMain*[numthreads]);
252
253 // Spawn the threads.
254 for (int16 index = 0; index < numthreads; index++) {
255 PlatformThreadHandle pth;
256 thread_delegates[index] = new MultipleThreadMain(index);
257 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
258 thread_handles[index] = pth;
259 }
260
261 // Wait for the threads to finish.
262 for (int index = 0; index < numthreads; index++) {
263 PlatformThread::Join(thread_handles[index]);
264 delete thread_delegates[index];
265 }
initial.commit3f4a7322008-07-27 06:49:38 +0900266 }
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900267 MultipleThreadMain::CleanUp();
initial.commit3f4a7322008-07-27 06:49:38 +0900268}
269
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900270// TODO(port): this test requires the MultipleLockThread class
271// (defined above), which requires the ability to pass file
272// descriptors between processes. We haven't done that yet in Chrome
273// for POSIX.
274#if defined(OS_WIN)
paulg@google.com78da6632008-09-11 09:31:43 +0900275// Create a set of threads to each open a shared memory segment and write to it
276// with the lock held. Verify that they are always reading/writing consistent
277// data.
initial.commit3f4a7322008-07-27 06:49:38 +0900278TEST(SharedMemoryTest, Lock) {
paulg@google.com78da6632008-09-11 09:31:43 +0900279 PlatformThreadHandle thread_handles[kNumThreads];
280 MultipleLockThread* thread_delegates[kNumThreads];
initial.commit3f4a7322008-07-27 06:49:38 +0900281
282 // Spawn the threads.
283 for (int index = 0; index < kNumThreads; ++index) {
paulg@google.com78da6632008-09-11 09:31:43 +0900284 PlatformThreadHandle pth;
285 thread_delegates[index] = new MultipleLockThread(index);
286 EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
287 thread_handles[index] = pth;
initial.commit3f4a7322008-07-27 06:49:38 +0900288 }
289
290 // Wait for the threads to finish.
291 for (int index = 0; index < kNumThreads; ++index) {
paulg@google.com78da6632008-09-11 09:31:43 +0900292 PlatformThread::Join(thread_handles[index]);
293 delete thread_delegates[index];
initial.commit3f4a7322008-07-27 06:49:38 +0900294 }
295}
paulg@google.com78da6632008-09-11 09:31:43 +0900296#endif
brettw@google.comc60d9892008-11-14 12:25:15 +0900297
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900298// Allocate private (unique) shared memory with an empty string for a
299// name. Make sure several of them don't point to the same thing as
300// we might expect if the names are equal.
301TEST(SharedMemoryTest, AnonymousPrivate) {
302 int i, j;
303 int count = 4;
304 bool rv;
jam@chromium.orge74ca942010-02-17 08:58:27 +0900305 const uint32 kDataSize = 8192;
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900306
jrg@chromium.org81e22602009-02-06 04:04:34 +0900307 scoped_array<SharedMemory> memories(new SharedMemory[count]);
308 scoped_array<int*> pointers(new int*[count]);
309 ASSERT_TRUE(memories.get());
310 ASSERT_TRUE(pointers.get());
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900311
312 for (i = 0; i < count; i++) {
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900313 rv = memories[i].CreateAndMapAnonymous(kDataSize);
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900314 EXPECT_TRUE(rv);
315 int *ptr = static_cast<int*>(memories[i].memory());
316 EXPECT_TRUE(ptr);
317 pointers[i] = ptr;
318 }
319
320 for (i = 0; i < count; i++) {
321 // zero out the first int in each except for i; for that one, make it 100.
322 for (j = 0; j < count; j++) {
323 if (i == j)
324 pointers[j][0] = 100;
325 else
326 pointers[j][0] = 0;
327 }
328 // make sure there is no bleeding of the 100 into the other pointers
329 for (j = 0; j < count; j++) {
330 if (i == j)
331 EXPECT_EQ(100, pointers[j][0]);
332 else
333 EXPECT_EQ(0, pointers[j][0]);
334 }
335 }
336
337 for (int i = 0; i < count; i++) {
338 memories[i].Close();
339 }
jrg@chromium.org81e22602009-02-06 04:04:34 +0900340}
341
mcgrathr@chromium.org45910f72011-12-02 08:19:31 +0900342#if defined(OS_POSIX)
343// Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
344TEST(SharedMemoryTest, AnonymousExecutable) {
345 const uint32 kTestSize = 1 << 16;
346
347 SharedMemory shared_memory;
348 SharedMemoryCreateOptions options;
349 options.size = kTestSize;
350 options.executable = true;
351
352 EXPECT_TRUE(shared_memory.Create(options));
353 EXPECT_TRUE(shared_memory.Map(shared_memory.created_size()));
354
355 EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.created_size(),
356 PROT_READ | PROT_EXEC));
357}
358#endif
359
jrg@chromium.org81e22602009-02-06 04:04:34 +0900360// On POSIX it is especially important we test shmem across processes,
361// not just across threads. But the test is enabled on all platforms.
brettw@chromium.org61391822011-01-01 05:02:16 +0900362class SharedMemoryProcessTest : public MultiProcessTest {
jrg@chromium.org81e22602009-02-06 04:04:34 +0900363 public:
364
365 static void CleanUp() {
366 SharedMemory memory;
maruel@chromium.org8fe7adc2009-03-04 00:01:12 +0900367 memory.Delete(s_test_name_);
jrg@chromium.org81e22602009-02-06 04:04:34 +0900368 }
369
370 static int TaskTestMain() {
371 int errors = 0;
jam@chromium.org9730fbd2011-10-29 12:44:44 +0900372#if defined(OS_MACOSX)
373 mac::ScopedNSAutoreleasePool pool;
374#endif
jam@chromium.orge74ca942010-02-17 08:58:27 +0900375 const uint32 kDataSize = 1024;
jrg@chromium.org81e22602009-02-06 04:04:34 +0900376 SharedMemory memory;
dmaclach@chromium.orgbb6b7632010-10-28 03:16:06 +0900377 bool rv = memory.CreateNamed(s_test_name_, true, kDataSize);
jrg@chromium.org81e22602009-02-06 04:04:34 +0900378 EXPECT_TRUE(rv);
379 if (rv != true)
380 errors++;
381 rv = memory.Map(kDataSize);
382 EXPECT_TRUE(rv);
383 if (rv != true)
384 errors++;
385 int *ptr = static_cast<int*>(memory.memory());
386
387 for (int idx = 0; idx < 20; idx++) {
388 memory.Lock();
389 int i = (1 << 16) + idx;
390 *ptr = i;
tedvessenes@gmail.comaaa63032012-01-01 07:53:51 +0900391 PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
jrg@chromium.org81e22602009-02-06 04:04:34 +0900392 if (*ptr != i)
393 errors++;
394 memory.Unlock();
395 }
396
397 memory.Close();
398 return errors;
399 }
400
401 private:
evan@chromium.org56756992010-09-30 05:32:22 +0900402 static const char* const s_test_name_;
jrg@chromium.org81e22602009-02-06 04:04:34 +0900403};
404
evan@chromium.org56756992010-09-30 05:32:22 +0900405const char* const SharedMemoryProcessTest::s_test_name_ = "MPMem";
jrg@chromium.org81e22602009-02-06 04:04:34 +0900406
evan@chromium.org3c0bc352012-02-14 09:29:14 +0900407// http://crbug.com/61589
bauerb@chromium.orge5caa272010-11-03 00:55:45 +0900408#if defined(OS_MACOSX)
evan@chromium.org3c0bc352012-02-14 09:29:14 +0900409#define MAYBE_Tasks DISABLED_Tasks
bauerb@chromium.orge5caa272010-11-03 00:55:45 +0900410#else
411#define MAYBE_Tasks Tasks
412#endif
413
414TEST_F(SharedMemoryProcessTest, MAYBE_Tasks) {
jrg@chromium.org81e22602009-02-06 04:04:34 +0900415 SharedMemoryProcessTest::CleanUp();
416
brettw@chromium.org61391822011-01-01 05:02:16 +0900417 ProcessHandle handles[kNumTasks];
jrg@chromium.org81e22602009-02-06 04:04:34 +0900418 for (int index = 0; index < kNumTasks; ++index) {
brettw@chromium.org1c8c3be2010-08-18 04:40:11 +0900419 handles[index] = SpawnChild("SharedMemoryTestMain", false);
rsleevi@chromium.org014b1f92011-07-03 07:01:14 +0900420 ASSERT_TRUE(handles[index]);
jrg@chromium.org81e22602009-02-06 04:04:34 +0900421 }
422
423 int exit_code = 0;
424 for (int index = 0; index < kNumTasks; ++index) {
brettw@chromium.org61391822011-01-01 05:02:16 +0900425 EXPECT_TRUE(WaitForExitCode(handles[index], &exit_code));
tbreisacher@chromium.org4474fb12012-03-17 07:09:29 +0900426 EXPECT_EQ(0, exit_code);
jrg@chromium.org81e22602009-02-06 04:04:34 +0900427 }
428
429 SharedMemoryProcessTest::CleanUp();
430}
431
432MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
433 return SharedMemoryProcessTest::TaskTestMain();
jrg@chromium.orgd505c3a2009-02-04 09:58:39 +0900434}
435
brettw@google.comc60d9892008-11-14 12:25:15 +0900436} // namespace base