From d7cae12696b96500c05dd2d430f6238922c20c96 Mon Sep 17 00:00:00 2001 From: "initial.commit" Date: Sat, 26 Jul 2008 21:49:38 +0000 Subject: Add base to the repository. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8 0039d316-1c4b-4281-b951-d872f2087c98 --- base/shared_memory_unittest.cc | 180 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 base/shared_memory_unittest.cc (limited to 'base/shared_memory_unittest.cc') diff --git a/base/shared_memory_unittest.cc b/base/shared_memory_unittest.cc new file mode 100644 index 0000000..928326a --- /dev/null +++ b/base/shared_memory_unittest.cc @@ -0,0 +1,180 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include // _beginthreadex +#include "base/shared_memory.h" +#include "testing/gtest/include/gtest/gtest.h" + + +namespace { + +class SharedMemoryTest : public testing::Test { +}; + +unsigned __stdcall MultipleThreadMain(void* param) { + // Each thread will open the shared memory. Each thread will take + // a different 4 byte int pointer, and keep changing it, with some + // small pauses in between. Verify that each thread's value in the + // shared memory is always correct. + const int kDataSize = 1024; + std::wstring test_name = L"SharedMemoryOpenThreadTest"; + int16 id = reinterpret_cast(param); + SharedMemory memory; + bool rv = memory.Create(test_name, false, true, kDataSize); + EXPECT_TRUE(rv); + rv = memory.Map(kDataSize); + EXPECT_TRUE(rv); + int *ptr = static_cast(memory.memory()) + id; + EXPECT_EQ(*ptr, 0); + for (int idx = 0; idx < 100; idx++) { + *ptr = idx; + Sleep(1); // short wait + EXPECT_EQ(*ptr, idx); + } + memory.Close(); + return 0; +} + +unsigned __stdcall MultipleLockThread(void* param) { + // Each thread will open the shared memory. Each thread will take + // the memory, and keep changing it while trying to lock it, with some + // small pauses in between. Verify that each thread's value in the + // shared memory is always correct. + const int kDataSize = sizeof(int); + int id = static_cast(reinterpret_cast(param)); + SharedMemoryHandle handle = NULL; + { + SharedMemory memory1; + EXPECT_TRUE(memory1.Create(L"SharedMemoryMultipleLockThreadTest", false, true, + kDataSize)); + EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle)); + } + SharedMemory memory2(handle, false); + EXPECT_TRUE(memory2.Map(kDataSize)); + volatile int* const ptr = static_cast(memory2.memory()); + for (int idx = 0; idx < 20; idx++) { + memory2.Lock(); + int i = (id << 16) + idx; + *ptr = i; + // short wait + Sleep(1); + EXPECT_EQ(*ptr, i); + memory2.Unlock(); + } + memory2.Close(); + return 0; +} + +} // namespace + +TEST(SharedMemoryTest, OpenClose) { + const int kDataSize = 1024; + std::wstring test_name = L"SharedMemoryOpenCloseTest"; + + // Open two handles to a memory segment, confirm that they + // are mapped separately yet point to the same space. + SharedMemory memory1; + bool rv = memory1.Open(test_name, false); + EXPECT_FALSE(rv); + rv = memory1.Create(test_name, false, false, kDataSize); + EXPECT_TRUE(rv); + rv = memory1.Map(kDataSize); + EXPECT_TRUE(rv); + SharedMemory memory2; + rv = memory2.Open(test_name, false); + EXPECT_TRUE(rv); + rv = memory2.Map(kDataSize); + EXPECT_TRUE(rv); + EXPECT_NE(memory1.memory(), memory2.memory()); // compare the pointers + + + // Write data to the first memory segment, verify contents of second. + memset(memory1.memory(), '1', kDataSize); + EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0); + + // Close the first memory segment, and verify the + // second still has the right data. + memory1.Close(); + char *start_ptr = static_cast(memory2.memory()); + char *end_ptr = start_ptr + kDataSize; + for (char* ptr = start_ptr; ptr < end_ptr; ptr++) + EXPECT_EQ(*ptr, '1'); + + // Close the second memory segment + memory2.Close(); +} + + +TEST(SharedMemoryTest, MultipleThreads) { + // Create a set of 5 threads to each open a shared memory segment + // and write to it. Verify that they are always reading/writing + // consistent data. + const int kNumThreads = 5; + HANDLE threads[kNumThreads]; + + // Spawn the threads. + for (int16 index = 0; index < kNumThreads; index++) { + void *argument = reinterpret_cast(index); + unsigned thread_id; + threads[index] = reinterpret_cast( + _beginthreadex(NULL, 0, MultipleThreadMain, argument, 0, &thread_id)); + EXPECT_NE(threads[index], static_cast(NULL)); + } + + // Wait for the threads to finish. + for (int index = 0; index < kNumThreads; index++) { + DWORD rv = WaitForSingleObject(threads[index], 60*1000); + EXPECT_EQ(rv, WAIT_OBJECT_0); // verify all threads finished + CloseHandle(threads[index]); + } +} + + +TEST(SharedMemoryTest, Lock) { + // Create a set of threads to each open a shared memory segment and write to + // it with the lock held. Verify that they are always reading/writing + // consistent data. + const int kNumThreads = 5; + HANDLE threads[kNumThreads]; + + // Spawn the threads. + for (int index = 0; index < kNumThreads; ++index) { + void *argument = reinterpret_cast(static_cast(index)); + threads[index] = reinterpret_cast( + _beginthreadex(NULL, 0, &MultipleLockThread, argument, 0, NULL)); + EXPECT_NE(threads[index], static_cast(NULL)); + } + + // Wait for the threads to finish. + for (int index = 0; index < kNumThreads; ++index) { + DWORD rv = WaitForSingleObject(threads[index], 60*1000); + EXPECT_EQ(rv, WAIT_OBJECT_0); // verify all threads finished + CloseHandle(threads[index]); + } +} -- cgit v1.1