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

Side by Side Diff: mojo/edk/util/waitable_event_unittest.cc

Issue 1420713006: Revert "EDK: Move //mojo/edk/system/waitable_event* to edk/util." (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: 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/util/waitable_event.cc ('k') | no next file » | 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/util/waitable_event.h"
6
7 #include <stdint.h>
8 #include <stdlib.h>
9
10 #include <atomic>
11 #include <thread>
12 #include <type_traits>
13 #include <vector>
14
15 #include "mojo/edk/system/test/sleep.h"
16 #include "mojo/edk/system/test/stopwatch.h"
17 #include "mojo/edk/system/test/timeouts.h"
18 #include "mojo/public/cpp/system/macros.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20
21 using mojo::system::test::ActionTimeout;
22 using mojo::system::test::DeadlineFromMilliseconds;
23 using mojo::system::test::EpsilonTimeout;
24 using mojo::system::test::Sleep;
25 using mojo::system::test::SleepMilliseconds;
26 using mojo::system::test::Stopwatch;
27 using mojo::system::test::TinyTimeout;
28
29 namespace mojo {
30 namespace util {
31 namespace {
32
33 // Sleeps for a "very small" amount of time.
34 void EpsilonRandomSleep() {
35 SleepMilliseconds(static_cast<unsigned>(rand()) % 20u);
36 }
37
38 // We'll use |MojoDeadline| with |uint64_t| (for |WaitWithTimeout()|'s timeout
39 // argument), though note that |WaitWithTimeout()| doesn't support
40 // |MOJO_DEADLINE_INDEFINITE|.
41 static_assert(std::is_same<uint64_t, MojoDeadline>::value,
42 "MojoDeadline isn't uint64_t!");
43
44 // AutoResetWaitableEvent ------------------------------------------------------
45
46 TEST(AutoResetWaitableEventTest, Basic) {
47 AutoResetWaitableEvent ev;
48 EXPECT_FALSE(ev.IsSignaledForTest());
49 ev.Signal();
50 EXPECT_TRUE(ev.IsSignaledForTest());
51 ev.Wait();
52 EXPECT_FALSE(ev.IsSignaledForTest());
53 ev.Reset();
54 EXPECT_FALSE(ev.IsSignaledForTest());
55 ev.Signal();
56 EXPECT_TRUE(ev.IsSignaledForTest());
57 ev.Reset();
58 EXPECT_FALSE(ev.IsSignaledForTest());
59 EXPECT_TRUE(ev.WaitWithTimeout(0));
60 EXPECT_FALSE(ev.IsSignaledForTest());
61 EXPECT_TRUE(ev.WaitWithTimeout(DeadlineFromMilliseconds(1)));
62 EXPECT_FALSE(ev.IsSignaledForTest());
63 ev.Signal();
64 EXPECT_TRUE(ev.IsSignaledForTest());
65 EXPECT_FALSE(ev.WaitWithTimeout(0));
66 EXPECT_FALSE(ev.IsSignaledForTest());
67 EXPECT_TRUE(ev.WaitWithTimeout(DeadlineFromMilliseconds(1)));
68 EXPECT_FALSE(ev.IsSignaledForTest());
69 ev.Signal();
70 EXPECT_FALSE(ev.WaitWithTimeout(DeadlineFromMilliseconds(1)));
71 EXPECT_FALSE(ev.IsSignaledForTest());
72 }
73
74 TEST(AutoResetWaitableEventTest, MultipleWaiters) {
75 AutoResetWaitableEvent ev;
76
77 for (size_t i = 0u; i < 5u; i++) {
78 std::atomic_uint wake_count(0u);
79 std::vector<std::thread> threads;
80 for (size_t j = 0u; j < 4u; j++) {
81 threads.push_back(std::thread([&ev, &wake_count]() {
82 if (rand() % 2 == 0)
83 ev.Wait();
84 else
85 EXPECT_FALSE(ev.WaitWithTimeout(ActionTimeout()));
86 wake_count.fetch_add(1u);
87 // Note: We can't say anything about the signaled state of |ev| here,
88 // since the main thread may have already signaled it again.
89 }));
90 }
91
92 // Unfortunately, we can't really wait for the threads to be waiting, so we
93 // just sleep for a bit, and count on them having started and advanced to
94 // waiting.
95 Sleep(2 * TinyTimeout());
96
97 for (size_t j = 0u; j < threads.size(); j++) {
98 unsigned old_wake_count = wake_count.load();
99 EXPECT_EQ(j, old_wake_count);
100
101 // Each |Signal()| should wake exactly one thread.
102 ev.Signal();
103
104 // Poll for |wake_count| to change.
105 while (wake_count.load() == old_wake_count)
106 Sleep(EpsilonTimeout());
107
108 EXPECT_FALSE(ev.IsSignaledForTest());
109
110 // And once it's changed, wait a little longer, to see if any other
111 // threads are awoken (they shouldn't be).
112 Sleep(EpsilonTimeout());
113
114 EXPECT_EQ(old_wake_count + 1u, wake_count.load());
115
116 EXPECT_FALSE(ev.IsSignaledForTest());
117 }
118
119 // Having done that, if we signal |ev| now, it should stay signaled.
120 ev.Signal();
121 Sleep(EpsilonTimeout());
122 EXPECT_TRUE(ev.IsSignaledForTest());
123
124 for (auto& thread : threads)
125 thread.join();
126
127 ev.Reset();
128 }
129 }
130
131 TEST(AutoResetWaitableEventTest, Timeouts) {
132 static const unsigned kTestTimeoutsMs[] = {0, 10, 20, 40, 80};
133
134 Stopwatch stopwatch;
135
136 AutoResetWaitableEvent ev;
137
138 for (size_t i = 0u; i < MOJO_ARRAYSIZE(kTestTimeoutsMs); i++) {
139 uint64_t timeout = DeadlineFromMilliseconds(kTestTimeoutsMs[i]);
140
141 stopwatch.Start();
142 EXPECT_TRUE(ev.WaitWithTimeout(timeout));
143 MojoDeadline elapsed = stopwatch.Elapsed();
144
145 // It should time out after *at least* the specified amount of time.
146 EXPECT_GE(elapsed, timeout);
147 // But we expect that it should time out soon after that amount of time.
148 EXPECT_LT(elapsed, timeout + EpsilonTimeout());
149 }
150 }
151
152 // ManualResetWaitableEvent ----------------------------------------------------
153
154 TEST(ManualResetWaitableEventTest, Basic) {
155 ManualResetWaitableEvent ev;
156 EXPECT_FALSE(ev.IsSignaledForTest());
157 ev.Signal();
158 EXPECT_TRUE(ev.IsSignaledForTest());
159 ev.Wait();
160 EXPECT_TRUE(ev.IsSignaledForTest());
161 ev.Reset();
162 EXPECT_FALSE(ev.IsSignaledForTest());
163 EXPECT_TRUE(ev.WaitWithTimeout(0));
164 EXPECT_FALSE(ev.IsSignaledForTest());
165 EXPECT_TRUE(ev.WaitWithTimeout(DeadlineFromMilliseconds(1)));
166 EXPECT_FALSE(ev.IsSignaledForTest());
167 ev.Signal();
168 EXPECT_TRUE(ev.IsSignaledForTest());
169 EXPECT_FALSE(ev.WaitWithTimeout(0));
170 EXPECT_TRUE(ev.IsSignaledForTest());
171 EXPECT_FALSE(ev.WaitWithTimeout(DeadlineFromMilliseconds(1)));
172 EXPECT_TRUE(ev.IsSignaledForTest());
173 }
174
175 TEST(ManualResetWaitableEventTest, SignalMultiple) {
176 ManualResetWaitableEvent ev;
177
178 for (size_t i = 0u; i < 10u; i++) {
179 for (size_t num_waiters = 1u; num_waiters < 5u; num_waiters++) {
180 std::vector<std::thread> threads;
181 for (size_t j = 0u; j < num_waiters; j++) {
182 threads.push_back(std::thread([&ev]() {
183 EpsilonRandomSleep();
184
185 if (rand() % 2 == 0)
186 ev.Wait();
187 else
188 EXPECT_FALSE(ev.WaitWithTimeout(ActionTimeout()));
189 }));
190 }
191
192 EpsilonRandomSleep();
193
194 ev.Signal();
195
196 // The threads will only terminate once they've successfully waited (or
197 // timed out).
198 for (auto& thread : threads)
199 thread.join();
200
201 ev.Reset();
202 }
203 }
204 }
205
206 // Tries to test that threads that are awoken may immediately call |Reset()|
207 // without affecting other threads that are awoken.
208 TEST(ManualResetWaitableEventTest, SignalMultipleWaitReset) {
209 ManualResetWaitableEvent ev;
210
211 for (size_t i = 0u; i < 5u; i++) {
212 std::vector<std::thread> threads;
213 for (size_t j = 0u; j < 4u; j++) {
214 threads.push_back(std::thread([&ev]() {
215 if (rand() % 2 == 0)
216 ev.Wait();
217 else
218 EXPECT_FALSE(ev.WaitWithTimeout(ActionTimeout()));
219 ev.Reset();
220 }));
221 }
222
223 // Unfortunately, we can't really wait for the threads to be waiting, so we
224 // just sleep for a bit, and count on them having started and advanced to
225 // waiting.
226 Sleep(2 * TinyTimeout());
227
228 ev.Signal();
229
230 // In fact, we may ourselves call |Reset()| immediately.
231 ev.Reset();
232
233 // The threads will only terminate once they've successfully waited (or
234 // timed out).
235 for (auto& thread : threads)
236 thread.join();
237
238 ASSERT_FALSE(ev.IsSignaledForTest());
239 }
240 }
241
242 TEST(ManualResetWaitableEventTest, Timeouts) {
243 static const unsigned kTestTimeoutsMs[] = {0, 10, 20, 40, 80};
244
245 Stopwatch stopwatch;
246
247 ManualResetWaitableEvent ev;
248
249 for (size_t i = 0u; i < MOJO_ARRAYSIZE(kTestTimeoutsMs); i++) {
250 uint64_t timeout = DeadlineFromMilliseconds(kTestTimeoutsMs[i]);
251
252 stopwatch.Start();
253 EXPECT_TRUE(ev.WaitWithTimeout(timeout));
254 MojoDeadline elapsed = stopwatch.Elapsed();
255
256 // It should time out after *at least* the specified amount of time.
257 EXPECT_GE(elapsed, timeout);
258 // But we expect that it should time out soon after that amount of time.
259 EXPECT_LT(elapsed, timeout + EpsilonTimeout());
260 }
261 }
262
263 } // namespace
264 } // namespace util
265 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/edk/util/waitable_event.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698