Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(154)

Side by Side Diff: mojo/edk/system/mutex_unittest.cc

Issue 1426343002: EDK: Move mutex.*, cond_var.*, and thread_annotations.h to //mojo/edk/util. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: oops Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/edk/system/mutex.cc ('k') | mojo/edk/system/platform_handle_dispatcher.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 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.
4
5 #include "mojo/edk/system/mutex.h"
6
7 #include <stdlib.h>
8
9 #include <thread>
10
11 #include "mojo/edk/system/test/sleep.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace mojo {
15 namespace system {
16 namespace {
17
18 // Sleeps for a "very small" amount of time.
19 void EpsilonRandomSleep() {
20 test::SleepMilliseconds(static_cast<unsigned>(rand()) % 20u);
21 }
22
23 // Basic test to make sure that Lock()/Unlock()/TryLock() don't crash ----------
24
25 TEST(MutexTest, Basic) {
26 Mutex mutex;
27
28 int thread_acquired = 0;
29 auto thread = std::thread([&mutex, &thread_acquired]() {
30 for (int i = 0; i < 10; i++) {
31 mutex.Lock();
32 mutex.AssertHeld();
33 thread_acquired++;
34 mutex.Unlock();
35 }
36 for (int i = 0; i < 10; i++) {
37 mutex.Lock();
38 mutex.AssertHeld();
39 thread_acquired++;
40 EpsilonRandomSleep();
41 mutex.Unlock();
42 }
43 for (int i = 0; i < 10; i++) {
44 if (mutex.TryLock()) {
45 mutex.AssertHeld();
46 thread_acquired++;
47 EpsilonRandomSleep();
48 mutex.Unlock();
49 }
50 }
51 });
52
53 int acquired = 0;
54 for (int i = 0; i < 5; i++) {
55 mutex.Lock();
56 mutex.AssertHeld();
57 acquired++;
58 mutex.Unlock();
59 }
60 for (int i = 0; i < 10; i++) {
61 mutex.Lock();
62 mutex.AssertHeld();
63 acquired++;
64 EpsilonRandomSleep();
65 mutex.Unlock();
66 }
67 for (int i = 0; i < 10; i++) {
68 if (mutex.TryLock()) {
69 mutex.AssertHeld();
70 acquired++;
71 EpsilonRandomSleep();
72 mutex.Unlock();
73 }
74 }
75 for (int i = 0; i < 5; i++) {
76 mutex.Lock();
77 mutex.AssertHeld();
78 acquired++;
79 EpsilonRandomSleep();
80 mutex.Unlock();
81 }
82
83 thread.join();
84
85 EXPECT_GE(acquired, 20);
86 EXPECT_GE(thread_acquired, 20);
87 }
88
89 TEST(MutexTest, AssertHeld) {
90 Mutex mutex;
91
92 #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
93 // For non-Debug builds, |AssertHeld()| should do nothing.
94 mutex.AssertHeld();
95 #else
96 EXPECT_DEATH_IF_SUPPORTED({ mutex.AssertHeld(); }, "Check failed");
97 #endif // defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
98
99 // TODO(vtl): Should also test the case when the mutex is held by another
100 // thread, though this is more annoying since it requires synchronization.
101 }
102
103 // Test that TryLock() works as expected ---------------------------------------
104
105 TEST(MutexTest, TryLock) MOJO_NO_THREAD_SAFETY_ANALYSIS {
106 Mutex mutex;
107
108 ASSERT_TRUE(mutex.TryLock());
109 // We now have the mutex....
110
111 {
112 // This thread will not be able to get the mutex.
113 auto thread = std::thread([&mutex]() { EXPECT_FALSE(mutex.TryLock()); });
114 thread.join();
115 }
116
117 mutex.Unlock();
118 // And now we don't.
119
120 {
121 // This thread will be able to get it (and then release it).
122 auto thread = std::thread([&mutex]() {
123 EXPECT_TRUE(mutex.TryLock());
124 mutex.AssertHeld();
125 mutex.Unlock();
126 });
127 thread.join();
128
129 // And we can take it again.
130 ASSERT_TRUE(mutex.TryLock());
131 }
132
133 mutex.Unlock();
134 }
135
136 // Tests that mutexes actually exclude -----------------------------------------
137
138 // We'll call this from both the main thread and secondary threads.
139 void DoStuffWithMutex(Mutex* mutex, int* value) {
140 for (int i = 0; i < 40; i++) {
141 mutex->Lock();
142 int v = *value;
143 EpsilonRandomSleep();
144 *value = v + 1;
145 mutex->Unlock();
146 }
147 }
148
149 std::thread MakeMutexTestThread(Mutex* mutex, int* value) {
150 return std::thread([mutex, value]() { DoStuffWithMutex(mutex, value); });
151 }
152
153 TEST(MutexTest, MutexTwoThreads) {
154 Mutex mutex;
155 int value = 0;
156
157 std::thread thread = MakeMutexTestThread(&mutex, &value);
158
159 DoStuffWithMutex(&mutex, &value);
160
161 thread.join();
162
163 EXPECT_EQ(2 * 40, value);
164 }
165
166 TEST(MutexTest, MutexFourThreads) {
167 Mutex mutex;
168 int value = 0;
169
170 std::thread thread1 = MakeMutexTestThread(&mutex, &value);
171 std::thread thread2 = MakeMutexTestThread(&mutex, &value);
172 std::thread thread3 = MakeMutexTestThread(&mutex, &value);
173
174 DoStuffWithMutex(&mutex, &value);
175
176 thread1.join();
177 thread2.join();
178 thread3.join();
179
180 EXPECT_EQ(4 * 40, value);
181 }
182
183 // MutexLocker -----------------------------------------------------------------
184
185 TEST(MutexTest, MutexLocker) {
186 Mutex mutex;
187
188 {
189 MutexLocker locker(&mutex);
190 mutex.AssertHeld();
191 }
192
193 // The destruction of |locker| should unlock |mutex|.
194 ASSERT_TRUE(mutex.TryLock());
195 mutex.AssertHeld();
196 mutex.Unlock();
197 }
198
199 } // namespace
200 } // namespace system
201 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/system/mutex.cc ('k') | mojo/edk/system/platform_handle_dispatcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698