| Index: base/shared_memory_unittest.cc
|
| ===================================================================
|
| --- base/shared_memory_unittest.cc (revision 9116)
|
| +++ base/shared_memory_unittest.cc (working copy)
|
| @@ -3,12 +3,15 @@
|
| // found in the LICENSE file.
|
|
|
| #include "base/basictypes.h"
|
| +#include "base/multiprocess_test.h"
|
| #include "base/platform_thread.h"
|
| #include "base/scoped_nsautorelease_pool.h"
|
| #include "base/shared_memory.h"
|
| +#include "base/scoped_ptr.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| static const int kNumThreads = 5;
|
| +static const int kNumTasks = 5;
|
|
|
| namespace base {
|
|
|
| @@ -158,27 +161,40 @@
|
| EXPECT_TRUE(rv);
|
| }
|
|
|
| -// Create a set of 5 threads to each open a shared memory segment and write to
|
| +// Create a set of N threads to each open a shared memory segment and write to
|
| // it. Verify that they are always reading/writing consistent data.
|
| TEST(SharedMemoryTest, MultipleThreads) {
|
| MultipleThreadMain::CleanUp();
|
| - PlatformThreadHandle thread_handles[kNumThreads];
|
| - MultipleThreadMain* thread_delegates[kNumThreads];
|
| + // On POSIX we have a problem when 2 threads try to create the shmem
|
| + // (a file) at exactly the same time, since create both creates the
|
| + // file and zerofills it. We solve the problem for this unit test
|
| + // (make it not flaky) by starting with 1 thread, then
|
| + // intentionally don't clean up its shmem before running with
|
| + // kNumThreads.
|
|
|
| - // Spawn the threads.
|
| - for (int16 index = 0; index < kNumThreads; index++) {
|
| - PlatformThreadHandle pth;
|
| - thread_delegates[index] = new MultipleThreadMain(index);
|
| - EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
|
| - thread_handles[index] = pth;
|
| - }
|
| + int threadcounts[] = { 1, kNumThreads };
|
| + for (size_t i = 0; i < sizeof(threadcounts) / sizeof(threadcounts); i++) {
|
| + int numthreads = threadcounts[i];
|
| + scoped_array<PlatformThreadHandle> thread_handles;
|
| + scoped_array<MultipleThreadMain*> thread_delegates;
|
|
|
| - // Wait for the threads to finish.
|
| - for (int index = 0; index < kNumThreads; index++) {
|
| - PlatformThread::Join(thread_handles[index]);
|
| - delete thread_delegates[index];
|
| + thread_handles.reset(new PlatformThreadHandle[numthreads]);
|
| + thread_delegates.reset(new MultipleThreadMain*[numthreads]);
|
| +
|
| + // Spawn the threads.
|
| + for (int16 index = 0; index < numthreads; index++) {
|
| + PlatformThreadHandle pth;
|
| + thread_delegates[index] = new MultipleThreadMain(index);
|
| + EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
|
| + thread_handles[index] = pth;
|
| + }
|
| +
|
| + // Wait for the threads to finish.
|
| + for (int index = 0; index < numthreads; index++) {
|
| + PlatformThread::Join(thread_handles[index]);
|
| + delete thread_delegates[index];
|
| + }
|
| }
|
| -
|
| MultipleThreadMain::CleanUp();
|
| }
|
|
|
| @@ -219,10 +235,10 @@
|
| bool rv;
|
| const int kDataSize = 8192;
|
|
|
| - SharedMemory* memories = new SharedMemory[count];
|
| - int **pointers = new int*[count];
|
| - ASSERT_TRUE(memories);
|
| - ASSERT_TRUE(pointers);
|
| + scoped_array<SharedMemory> memories(new SharedMemory[count]);
|
| + scoped_array<int*> pointers(new int*[count]);
|
| + ASSERT_TRUE(memories.get());
|
| + ASSERT_TRUE(pointers.get());
|
|
|
| for (i = 0; i < count; i++) {
|
| rv = memories[i].Create(L"", false, true, kDataSize);
|
| @@ -254,7 +270,76 @@
|
| for (int i = 0; i < count; i++) {
|
| memories[i].Close();
|
| }
|
| +
|
| }
|
|
|
|
|
| +// On POSIX it is especially important we test shmem across processes,
|
| +// not just across threads. But the test is enabled on all platforms.
|
| +class SharedMemoryProcessTest : public MultiProcessTest {
|
| + public:
|
| +
|
| + static void CleanUp() {
|
| + SharedMemory memory;
|
| + memory.Delete(test_name_);
|
| + }
|
| +
|
| + static int TaskTestMain() {
|
| + int errors = 0;
|
| + ScopedNSAutoreleasePool pool; // noop if not OSX
|
| + const int kDataSize = 1024;
|
| + SharedMemory memory;
|
| + bool rv = memory.Create(test_name_, false, true, kDataSize);
|
| + EXPECT_TRUE(rv);
|
| + if (rv != true)
|
| + errors++;
|
| + rv = memory.Map(kDataSize);
|
| + EXPECT_TRUE(rv);
|
| + if (rv != true)
|
| + errors++;
|
| + int *ptr = static_cast<int*>(memory.memory());
|
| +
|
| + for (int idx = 0; idx < 20; idx++) {
|
| + memory.Lock();
|
| + int i = (1 << 16) + idx;
|
| + *ptr = i;
|
| + PlatformThread::Sleep(10); // Short wait.
|
| + if (*ptr != i)
|
| + errors++;
|
| + memory.Unlock();
|
| + }
|
| +
|
| + memory.Close();
|
| + return errors;
|
| + }
|
| +
|
| + private:
|
| + static const std::wstring test_name_;
|
| +};
|
| +
|
| +const std::wstring SharedMemoryProcessTest::test_name_ = L"MPMem";
|
| +
|
| +
|
| +TEST_F(SharedMemoryProcessTest, Tasks) {
|
| + SharedMemoryProcessTest::CleanUp();
|
| +
|
| + base::ProcessHandle handles[kNumTasks];
|
| + for (int index = 0; index < kNumTasks; ++index) {
|
| + handles[index] = SpawnChild(L"SharedMemoryTestMain");
|
| + }
|
| +
|
| + int exit_code = 0;
|
| + for (int index = 0; index < kNumTasks; ++index) {
|
| + EXPECT_TRUE(base::WaitForExitCode(handles[index], &exit_code));
|
| + EXPECT_TRUE(exit_code == 0);
|
| + }
|
| +
|
| + SharedMemoryProcessTest::CleanUp();
|
| +}
|
| +
|
| +MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
|
| + return SharedMemoryProcessTest::TaskTestMain();
|
| +}
|
| +
|
| +
|
| } // namespace base
|
|
|