summaryrefslogtreecommitdiffstats
path: root/base/shared_memory_unittest.cc
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 21:49:38 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 21:49:38 +0000
commitd7cae12696b96500c05dd2d430f6238922c20c96 (patch)
treeecff27b367735535b2a66477f8cd89d3c462a6c0 /base/shared_memory_unittest.cc
parentee2815e28d408216cf94e874825b6bcf76c69083 (diff)
downloadchromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.zip
chromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.tar.gz
chromium_src-d7cae12696b96500c05dd2d430f6238922c20c96.tar.bz2
Add base to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/shared_memory_unittest.cc')
-rw-r--r--base/shared_memory_unittest.cc180
1 files changed, 180 insertions, 0 deletions
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 <process.h> // _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<int16>(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<int*>(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<int>(reinterpret_cast<INT_PTR>(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<int*>(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<char *>(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<void*>(index);
+ unsigned thread_id;
+ threads[index] = reinterpret_cast<HANDLE>(
+ _beginthreadex(NULL, 0, MultipleThreadMain, argument, 0, &thread_id));
+ EXPECT_NE(threads[index], static_cast<HANDLE>(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<void*>(static_cast<INT_PTR>(index));
+ threads[index] = reinterpret_cast<HANDLE>(
+ _beginthreadex(NULL, 0, &MultipleLockThread, argument, 0, NULL));
+ EXPECT_NE(threads[index], static_cast<HANDLE>(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]);
+ }
+}