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

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

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

Powered by Google App Engine
This is Rietveld 408576698