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