blob: 274c48039789b88d0396624a8709d555a576c56e [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// 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.commit3f4a7322008-07-27 06:49:38 +09004
5#include <process.h> // _beginthreadex
6#include "base/shared_memory.h"
7#include "testing/gtest/include/gtest/gtest.h"
8
9
10namespace {
11
12class SharedMemoryTest : public testing::Test {
13};
14
15unsigned __stdcall MultipleThreadMain(void* param) {
16 // Each thread will open the shared memory. Each thread will take
17 // a different 4 byte int pointer, and keep changing it, with some
18 // small pauses in between. Verify that each thread's value in the
19 // shared memory is always correct.
20 const int kDataSize = 1024;
21 std::wstring test_name = L"SharedMemoryOpenThreadTest";
22 int16 id = reinterpret_cast<int16>(param);
23 SharedMemory memory;
24 bool rv = memory.Create(test_name, false, true, kDataSize);
25 EXPECT_TRUE(rv);
26 rv = memory.Map(kDataSize);
27 EXPECT_TRUE(rv);
28 int *ptr = static_cast<int*>(memory.memory()) + id;
29 EXPECT_EQ(*ptr, 0);
30 for (int idx = 0; idx < 100; idx++) {
31 *ptr = idx;
32 Sleep(1); // short wait
33 EXPECT_EQ(*ptr, idx);
34 }
35 memory.Close();
36 return 0;
37}
38
39unsigned __stdcall MultipleLockThread(void* param) {
40 // Each thread will open the shared memory. Each thread will take
41 // the memory, and keep changing it while trying to lock it, with some
42 // small pauses in between. Verify that each thread's value in the
43 // shared memory is always correct.
44 const int kDataSize = sizeof(int);
45 int id = static_cast<int>(reinterpret_cast<INT_PTR>(param));
46 SharedMemoryHandle handle = NULL;
47 {
48 SharedMemory memory1;
49 EXPECT_TRUE(memory1.Create(L"SharedMemoryMultipleLockThreadTest", false, true,
50 kDataSize));
51 EXPECT_TRUE(memory1.ShareToProcess(GetCurrentProcess(), &handle));
52 }
53 SharedMemory memory2(handle, false);
54 EXPECT_TRUE(memory2.Map(kDataSize));
55 volatile int* const ptr = static_cast<int*>(memory2.memory());
56 for (int idx = 0; idx < 20; idx++) {
57 memory2.Lock();
58 int i = (id << 16) + idx;
59 *ptr = i;
60 // short wait
61 Sleep(1);
62 EXPECT_EQ(*ptr, i);
63 memory2.Unlock();
64 }
65 memory2.Close();
66 return 0;
67}
68
69} // namespace
70
71TEST(SharedMemoryTest, OpenClose) {
72 const int kDataSize = 1024;
73 std::wstring test_name = L"SharedMemoryOpenCloseTest";
74
75 // Open two handles to a memory segment, confirm that they
76 // are mapped separately yet point to the same space.
77 SharedMemory memory1;
78 bool rv = memory1.Open(test_name, false);
79 EXPECT_FALSE(rv);
80 rv = memory1.Create(test_name, false, false, kDataSize);
81 EXPECT_TRUE(rv);
82 rv = memory1.Map(kDataSize);
83 EXPECT_TRUE(rv);
84 SharedMemory memory2;
85 rv = memory2.Open(test_name, false);
86 EXPECT_TRUE(rv);
87 rv = memory2.Map(kDataSize);
88 EXPECT_TRUE(rv);
89 EXPECT_NE(memory1.memory(), memory2.memory()); // compare the pointers
90
91
92 // Write data to the first memory segment, verify contents of second.
93 memset(memory1.memory(), '1', kDataSize);
94 EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
95
96 // Close the first memory segment, and verify the
97 // second still has the right data.
98 memory1.Close();
99 char *start_ptr = static_cast<char *>(memory2.memory());
100 char *end_ptr = start_ptr + kDataSize;
101 for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
102 EXPECT_EQ(*ptr, '1');
103
104 // Close the second memory segment
105 memory2.Close();
106}
107
108
109TEST(SharedMemoryTest, MultipleThreads) {
110 // Create a set of 5 threads to each open a shared memory segment
111 // and write to it. Verify that they are always reading/writing
112 // consistent data.
113 const int kNumThreads = 5;
114 HANDLE threads[kNumThreads];
115
116 // Spawn the threads.
117 for (int16 index = 0; index < kNumThreads; index++) {
118 void *argument = reinterpret_cast<void*>(index);
119 unsigned thread_id;
120 threads[index] = reinterpret_cast<HANDLE>(
121 _beginthreadex(NULL, 0, MultipleThreadMain, argument, 0, &thread_id));
122 EXPECT_NE(threads[index], static_cast<HANDLE>(NULL));
123 }
124
125 // Wait for the threads to finish.
126 for (int index = 0; index < kNumThreads; index++) {
127 DWORD rv = WaitForSingleObject(threads[index], 60*1000);
128 EXPECT_EQ(rv, WAIT_OBJECT_0); // verify all threads finished
129 CloseHandle(threads[index]);
130 }
131}
132
133
134TEST(SharedMemoryTest, Lock) {
135 // Create a set of threads to each open a shared memory segment and write to
136 // it with the lock held. Verify that they are always reading/writing
137 // consistent data.
138 const int kNumThreads = 5;
139 HANDLE threads[kNumThreads];
140
141 // Spawn the threads.
142 for (int index = 0; index < kNumThreads; ++index) {
143 void *argument = reinterpret_cast<void*>(static_cast<INT_PTR>(index));
144 threads[index] = reinterpret_cast<HANDLE>(
145 _beginthreadex(NULL, 0, &MultipleLockThread, argument, 0, NULL));
146 EXPECT_NE(threads[index], static_cast<HANDLE>(NULL));
147 }
148
149 // Wait for the threads to finish.
150 for (int index = 0; index < kNumThreads; ++index) {
151 DWORD rv = WaitForSingleObject(threads[index], 60*1000);
152 EXPECT_EQ(rv, WAIT_OBJECT_0); // verify all threads finished
153 CloseHandle(threads[index]);
154 }
155}
license.botf003cfe2008-08-24 09:55:55 +0900156