OLD | NEW |
| (Empty) |
1 // Copyright 2013 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 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a | |
6 // heavily-loaded system). Sorry. |test::EpsilonDeadline()| may be increased to | |
7 // increase tolerance and reduce observed flakiness (though doing so reduces the | |
8 // meaningfulness of the test). | |
9 | |
10 #include "mojo/edk/system/awakable_list.h" | |
11 | |
12 #include "mojo/edk/system/handle_signals_state.h" | |
13 #include "mojo/edk/system/test_utils.h" | |
14 #include "mojo/edk/system/waiter.h" | |
15 #include "mojo/edk/system/waiter_test_utils.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 | |
18 namespace mojo { | |
19 namespace edk { | |
20 namespace { | |
21 | |
22 TEST(AwakableListTest, BasicCancel) { | |
23 MojoResult result; | |
24 uintptr_t context; | |
25 | |
26 // Cancel immediately after thread start. | |
27 { | |
28 AwakableList awakable_list; | |
29 test::SimpleWaiterThread thread(&result, &context); | |
30 awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); | |
31 thread.Start(); | |
32 awakable_list.CancelAll(); | |
33 // Double-remove okay: | |
34 awakable_list.Remove(thread.waiter()); | |
35 } // Join |thread|. | |
36 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | |
37 EXPECT_EQ(1u, context); | |
38 | |
39 // Cancel before after thread start. | |
40 { | |
41 AwakableList awakable_list; | |
42 test::SimpleWaiterThread thread(&result, &context); | |
43 awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); | |
44 awakable_list.CancelAll(); | |
45 thread.Start(); | |
46 } // Join |thread|. | |
47 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | |
48 EXPECT_EQ(2u, context); | |
49 | |
50 // Cancel some time after thread start. | |
51 { | |
52 AwakableList awakable_list; | |
53 test::SimpleWaiterThread thread(&result, &context); | |
54 awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); | |
55 thread.Start(); | |
56 test::Sleep(2 * test::EpsilonDeadline()); | |
57 awakable_list.CancelAll(); | |
58 } // Join |thread|. | |
59 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | |
60 EXPECT_EQ(3u, context); | |
61 } | |
62 | |
63 TEST(AwakableListTest, BasicAwakeSatisfied) { | |
64 MojoResult result; | |
65 uintptr_t context; | |
66 | |
67 // Awake immediately after thread start. | |
68 { | |
69 AwakableList awakable_list; | |
70 test::SimpleWaiterThread thread(&result, &context); | |
71 awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); | |
72 thread.Start(); | |
73 awakable_list.AwakeForStateChange(HandleSignalsState( | |
74 MOJO_HANDLE_SIGNAL_READABLE, | |
75 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); | |
76 awakable_list.Remove(thread.waiter()); | |
77 } // Join |thread|. | |
78 EXPECT_EQ(MOJO_RESULT_OK, result); | |
79 EXPECT_EQ(1u, context); | |
80 | |
81 // Awake before after thread start. | |
82 { | |
83 AwakableList awakable_list; | |
84 test::SimpleWaiterThread thread(&result, &context); | |
85 awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); | |
86 awakable_list.AwakeForStateChange(HandleSignalsState( | |
87 MOJO_HANDLE_SIGNAL_WRITABLE, | |
88 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); | |
89 awakable_list.Remove(thread.waiter()); | |
90 // Double-remove okay: | |
91 awakable_list.Remove(thread.waiter()); | |
92 thread.Start(); | |
93 } // Join |thread|. | |
94 EXPECT_EQ(MOJO_RESULT_OK, result); | |
95 EXPECT_EQ(2u, context); | |
96 | |
97 // Awake some time after thread start. | |
98 { | |
99 AwakableList awakable_list; | |
100 test::SimpleWaiterThread thread(&result, &context); | |
101 awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); | |
102 thread.Start(); | |
103 test::Sleep(2 * test::EpsilonDeadline()); | |
104 awakable_list.AwakeForStateChange(HandleSignalsState( | |
105 MOJO_HANDLE_SIGNAL_READABLE, | |
106 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); | |
107 awakable_list.Remove(thread.waiter()); | |
108 } // Join |thread|. | |
109 EXPECT_EQ(MOJO_RESULT_OK, result); | |
110 EXPECT_EQ(3u, context); | |
111 } | |
112 | |
113 TEST(AwakableListTest, BasicAwakeUnsatisfiable) { | |
114 MojoResult result; | |
115 uintptr_t context; | |
116 | |
117 // Awake (for unsatisfiability) immediately after thread start. | |
118 { | |
119 AwakableList awakable_list; | |
120 test::SimpleWaiterThread thread(&result, &context); | |
121 awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); | |
122 thread.Start(); | |
123 awakable_list.AwakeForStateChange(HandleSignalsState( | |
124 MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)); | |
125 awakable_list.Remove(thread.waiter()); | |
126 } // Join |thread|. | |
127 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | |
128 EXPECT_EQ(1u, context); | |
129 | |
130 // Awake (for unsatisfiability) before after thread start. | |
131 { | |
132 AwakableList awakable_list; | |
133 test::SimpleWaiterThread thread(&result, &context); | |
134 awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); | |
135 awakable_list.AwakeForStateChange(HandleSignalsState( | |
136 MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE)); | |
137 awakable_list.Remove(thread.waiter()); | |
138 thread.Start(); | |
139 } // Join |thread|. | |
140 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | |
141 EXPECT_EQ(2u, context); | |
142 | |
143 // Awake (for unsatisfiability) some time after thread start. | |
144 { | |
145 AwakableList awakable_list; | |
146 test::SimpleWaiterThread thread(&result, &context); | |
147 awakable_list.Add(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); | |
148 thread.Start(); | |
149 test::Sleep(2 * test::EpsilonDeadline()); | |
150 awakable_list.AwakeForStateChange(HandleSignalsState( | |
151 MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE)); | |
152 awakable_list.Remove(thread.waiter()); | |
153 // Double-remove okay: | |
154 awakable_list.Remove(thread.waiter()); | |
155 } // Join |thread|. | |
156 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | |
157 EXPECT_EQ(3u, context); | |
158 } | |
159 | |
160 TEST(AwakableListTest, MultipleAwakables) { | |
161 MojoResult result1; | |
162 MojoResult result2; | |
163 MojoResult result3; | |
164 MojoResult result4; | |
165 uintptr_t context1; | |
166 uintptr_t context2; | |
167 uintptr_t context3; | |
168 uintptr_t context4; | |
169 | |
170 // Cancel two awakables. | |
171 { | |
172 AwakableList awakable_list; | |
173 test::SimpleWaiterThread thread1(&result1, &context1); | |
174 awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1); | |
175 thread1.Start(); | |
176 test::SimpleWaiterThread thread2(&result2, &context2); | |
177 awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2); | |
178 thread2.Start(); | |
179 test::Sleep(2 * test::EpsilonDeadline()); | |
180 awakable_list.CancelAll(); | |
181 } // Join threads. | |
182 EXPECT_EQ(MOJO_RESULT_CANCELLED, result1); | |
183 EXPECT_EQ(1u, context1); | |
184 EXPECT_EQ(MOJO_RESULT_CANCELLED, result2); | |
185 EXPECT_EQ(2u, context2); | |
186 | |
187 // Awake one awakable, cancel other. | |
188 { | |
189 AwakableList awakable_list; | |
190 test::SimpleWaiterThread thread1(&result1, &context1); | |
191 awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3); | |
192 thread1.Start(); | |
193 test::SimpleWaiterThread thread2(&result2, &context2); | |
194 awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 4); | |
195 thread2.Start(); | |
196 test::Sleep(2 * test::EpsilonDeadline()); | |
197 awakable_list.AwakeForStateChange(HandleSignalsState( | |
198 MOJO_HANDLE_SIGNAL_READABLE, | |
199 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); | |
200 awakable_list.Remove(thread1.waiter()); | |
201 awakable_list.CancelAll(); | |
202 } // Join threads. | |
203 EXPECT_EQ(MOJO_RESULT_OK, result1); | |
204 EXPECT_EQ(3u, context1); | |
205 EXPECT_EQ(MOJO_RESULT_CANCELLED, result2); | |
206 EXPECT_EQ(4u, context2); | |
207 | |
208 // Cancel one awakable, awake other for unsatisfiability. | |
209 { | |
210 AwakableList awakable_list; | |
211 test::SimpleWaiterThread thread1(&result1, &context1); | |
212 awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 5); | |
213 thread1.Start(); | |
214 test::SimpleWaiterThread thread2(&result2, &context2); | |
215 awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 6); | |
216 thread2.Start(); | |
217 test::Sleep(2 * test::EpsilonDeadline()); | |
218 awakable_list.AwakeForStateChange(HandleSignalsState( | |
219 MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE)); | |
220 awakable_list.Remove(thread2.waiter()); | |
221 awakable_list.CancelAll(); | |
222 } // Join threads. | |
223 EXPECT_EQ(MOJO_RESULT_CANCELLED, result1); | |
224 EXPECT_EQ(5u, context1); | |
225 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2); | |
226 EXPECT_EQ(6u, context2); | |
227 | |
228 // Cancel one awakable, awake other for unsatisfiability. | |
229 { | |
230 AwakableList awakable_list; | |
231 test::SimpleWaiterThread thread1(&result1, &context1); | |
232 awakable_list.Add(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 7); | |
233 thread1.Start(); | |
234 | |
235 test::Sleep(1 * test::EpsilonDeadline()); | |
236 | |
237 // Should do nothing. | |
238 awakable_list.AwakeForStateChange(HandleSignalsState( | |
239 MOJO_HANDLE_SIGNAL_NONE, | |
240 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); | |
241 | |
242 test::SimpleWaiterThread thread2(&result2, &context2); | |
243 awakable_list.Add(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 8); | |
244 thread2.Start(); | |
245 | |
246 test::Sleep(1 * test::EpsilonDeadline()); | |
247 | |
248 // Awake #1. | |
249 awakable_list.AwakeForStateChange(HandleSignalsState( | |
250 MOJO_HANDLE_SIGNAL_READABLE, | |
251 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE)); | |
252 awakable_list.Remove(thread1.waiter()); | |
253 | |
254 test::Sleep(1 * test::EpsilonDeadline()); | |
255 | |
256 test::SimpleWaiterThread thread3(&result3, &context3); | |
257 awakable_list.Add(thread3.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 9); | |
258 thread3.Start(); | |
259 | |
260 test::SimpleWaiterThread thread4(&result4, &context4); | |
261 awakable_list.Add(thread4.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 10); | |
262 thread4.Start(); | |
263 | |
264 test::Sleep(1 * test::EpsilonDeadline()); | |
265 | |
266 // Awake #2 and #3 for unsatisfiability. | |
267 awakable_list.AwakeForStateChange(HandleSignalsState( | |
268 MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE)); | |
269 awakable_list.Remove(thread2.waiter()); | |
270 awakable_list.Remove(thread3.waiter()); | |
271 | |
272 // Cancel #4. | |
273 awakable_list.CancelAll(); | |
274 } // Join threads. | |
275 EXPECT_EQ(MOJO_RESULT_OK, result1); | |
276 EXPECT_EQ(7u, context1); | |
277 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result2); | |
278 EXPECT_EQ(8u, context2); | |
279 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result3); | |
280 EXPECT_EQ(9u, context3); | |
281 EXPECT_EQ(MOJO_RESULT_CANCELLED, result4); | |
282 EXPECT_EQ(10u, context4); | |
283 } | |
284 | |
285 class KeepAwakable : public Awakable { | |
286 public: | |
287 KeepAwakable() : awake_count(0) {} | |
288 | |
289 bool Awake(MojoResult result, uintptr_t context) override { | |
290 awake_count++; | |
291 return true; | |
292 } | |
293 | |
294 int awake_count; | |
295 | |
296 DISALLOW_COPY_AND_ASSIGN(KeepAwakable); | |
297 }; | |
298 | |
299 class RemoveAwakable : public Awakable { | |
300 public: | |
301 RemoveAwakable() : awake_count(0) {} | |
302 | |
303 bool Awake(MojoResult result, uintptr_t context) override { | |
304 awake_count++; | |
305 return false; | |
306 } | |
307 | |
308 int awake_count; | |
309 | |
310 DISALLOW_COPY_AND_ASSIGN(RemoveAwakable); | |
311 }; | |
312 | |
313 TEST(AwakableListTest, KeepAwakablesReturningTrue) { | |
314 KeepAwakable keep0; | |
315 KeepAwakable keep1; | |
316 RemoveAwakable remove0; | |
317 RemoveAwakable remove1; | |
318 RemoveAwakable remove2; | |
319 | |
320 HandleSignalsState hss(MOJO_HANDLE_SIGNAL_WRITABLE, | |
321 MOJO_HANDLE_SIGNAL_WRITABLE); | |
322 | |
323 AwakableList remove_all; | |
324 remove_all.Add(&remove0, MOJO_HANDLE_SIGNAL_WRITABLE, 0); | |
325 remove_all.Add(&remove1, MOJO_HANDLE_SIGNAL_WRITABLE, 0); | |
326 | |
327 remove_all.AwakeForStateChange(hss); | |
328 EXPECT_EQ(remove0.awake_count, 1); | |
329 EXPECT_EQ(remove1.awake_count, 1); | |
330 | |
331 remove_all.AwakeForStateChange(hss); | |
332 EXPECT_EQ(remove0.awake_count, 1); | |
333 EXPECT_EQ(remove1.awake_count, 1); | |
334 | |
335 AwakableList remove_first; | |
336 remove_first.Add(&remove2, MOJO_HANDLE_SIGNAL_WRITABLE, 0); | |
337 remove_first.Add(&keep0, MOJO_HANDLE_SIGNAL_WRITABLE, 0); | |
338 remove_first.Add(&keep1, MOJO_HANDLE_SIGNAL_WRITABLE, 0); | |
339 | |
340 remove_first.AwakeForStateChange(hss); | |
341 EXPECT_EQ(keep0.awake_count, 1); | |
342 EXPECT_EQ(keep1.awake_count, 1); | |
343 EXPECT_EQ(remove2.awake_count, 1); | |
344 | |
345 remove_first.AwakeForStateChange(hss); | |
346 EXPECT_EQ(keep0.awake_count, 2); | |
347 EXPECT_EQ(keep1.awake_count, 2); | |
348 EXPECT_EQ(remove2.awake_count, 1); | |
349 | |
350 remove_first.Remove(&keep0); | |
351 remove_first.Remove(&keep1); | |
352 } | |
353 | |
354 } // namespace | |
355 } // namespace edk | |
356 } // namespace mojo | |
OLD | NEW |