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.
5 // NOTE(vtl): Some of these tests are inherently flaky (e.g., if run on a
6 // heavily-loaded system). Sorry. |test::EpsilonTimeout()| may be increased to
7 // increase tolerance and reduce observed flakiness (though doing so reduces the
8 // meaningfulness of the test).
10 #include "mojo/edk/system/awakable_list.h"
12 #include "base/threading/platform_thread.h" // For |Sleep()|.
13 #include "base/time/time.h"
14 #include "mojo/edk/system/handle_signals_state.h"
15 #include "mojo/edk/system/test_utils.h"
16 #include "mojo/edk/system/waiter.h"
17 #include "mojo/edk/system/waiter_test_utils.h"
18 #include "testing/gtest/include/gtest/gtest.h"
24 TEST(AwakableListTest
, BasicCancel
) {
28 // Cancel immediately after thread start.
30 AwakableList awakable_list
;
31 test::SimpleWaiterThread
thread(&result
, &context
);
32 awakable_list
.Add(thread
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 1);
34 awakable_list
.CancelAll();
35 // Double-remove okay:
36 awakable_list
.Remove(thread
.waiter());
38 EXPECT_EQ(MOJO_RESULT_CANCELLED
, result
);
39 EXPECT_EQ(1u, context
);
41 // Cancel before after thread start.
43 AwakableList awakable_list
;
44 test::SimpleWaiterThread
thread(&result
, &context
);
45 awakable_list
.Add(thread
.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE
, 2);
46 awakable_list
.CancelAll();
49 EXPECT_EQ(MOJO_RESULT_CANCELLED
, result
);
50 EXPECT_EQ(2u, context
);
52 // Cancel some time after thread start.
54 AwakableList awakable_list
;
55 test::SimpleWaiterThread
thread(&result
, &context
);
56 awakable_list
.Add(thread
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 3);
58 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
59 awakable_list
.CancelAll();
61 EXPECT_EQ(MOJO_RESULT_CANCELLED
, result
);
62 EXPECT_EQ(3u, context
);
65 TEST(AwakableListTest
, BasicAwakeSatisfied
) {
69 // Awake immediately after thread start.
71 AwakableList awakable_list
;
72 test::SimpleWaiterThread
thread(&result
, &context
);
73 awakable_list
.Add(thread
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 1);
75 awakable_list
.AwakeForStateChange(HandleSignalsState(
76 MOJO_HANDLE_SIGNAL_READABLE
,
77 MOJO_HANDLE_SIGNAL_READABLE
| MOJO_HANDLE_SIGNAL_WRITABLE
));
78 awakable_list
.Remove(thread
.waiter());
80 EXPECT_EQ(MOJO_RESULT_OK
, result
);
81 EXPECT_EQ(1u, context
);
83 // Awake before after thread start.
85 AwakableList awakable_list
;
86 test::SimpleWaiterThread
thread(&result
, &context
);
87 awakable_list
.Add(thread
.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE
, 2);
88 awakable_list
.AwakeForStateChange(HandleSignalsState(
89 MOJO_HANDLE_SIGNAL_WRITABLE
,
90 MOJO_HANDLE_SIGNAL_READABLE
| MOJO_HANDLE_SIGNAL_WRITABLE
));
91 awakable_list
.Remove(thread
.waiter());
92 // Double-remove okay:
93 awakable_list
.Remove(thread
.waiter());
96 EXPECT_EQ(MOJO_RESULT_OK
, result
);
97 EXPECT_EQ(2u, context
);
99 // Awake some time after thread start.
101 AwakableList awakable_list
;
102 test::SimpleWaiterThread
thread(&result
, &context
);
103 awakable_list
.Add(thread
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 3);
105 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
106 awakable_list
.AwakeForStateChange(HandleSignalsState(
107 MOJO_HANDLE_SIGNAL_READABLE
,
108 MOJO_HANDLE_SIGNAL_READABLE
| MOJO_HANDLE_SIGNAL_WRITABLE
));
109 awakable_list
.Remove(thread
.waiter());
111 EXPECT_EQ(MOJO_RESULT_OK
, result
);
112 EXPECT_EQ(3u, context
);
115 TEST(AwakableListTest
, BasicAwakeUnsatisfiable
) {
119 // Awake (for unsatisfiability) immediately after thread start.
121 AwakableList awakable_list
;
122 test::SimpleWaiterThread
thread(&result
, &context
);
123 awakable_list
.Add(thread
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 1);
125 awakable_list
.AwakeForStateChange(HandleSignalsState(
126 MOJO_HANDLE_SIGNAL_NONE
, MOJO_HANDLE_SIGNAL_WRITABLE
));
127 awakable_list
.Remove(thread
.waiter());
129 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION
, result
);
130 EXPECT_EQ(1u, context
);
132 // Awake (for unsatisfiability) before after thread start.
134 AwakableList awakable_list
;
135 test::SimpleWaiterThread
thread(&result
, &context
);
136 awakable_list
.Add(thread
.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE
, 2);
137 awakable_list
.AwakeForStateChange(HandleSignalsState(
138 MOJO_HANDLE_SIGNAL_READABLE
, MOJO_HANDLE_SIGNAL_READABLE
));
139 awakable_list
.Remove(thread
.waiter());
142 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION
, result
);
143 EXPECT_EQ(2u, context
);
145 // Awake (for unsatisfiability) some time after thread start.
147 AwakableList awakable_list
;
148 test::SimpleWaiterThread
thread(&result
, &context
);
149 awakable_list
.Add(thread
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 3);
151 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
152 awakable_list
.AwakeForStateChange(HandleSignalsState(
153 MOJO_HANDLE_SIGNAL_NONE
, MOJO_HANDLE_SIGNAL_WRITABLE
));
154 awakable_list
.Remove(thread
.waiter());
155 // Double-remove okay:
156 awakable_list
.Remove(thread
.waiter());
158 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION
, result
);
159 EXPECT_EQ(3u, context
);
162 TEST(AwakableListTest
, MultipleAwakables
) {
172 // Cancel two awakables.
174 AwakableList awakable_list
;
175 test::SimpleWaiterThread
thread1(&result1
, &context1
);
176 awakable_list
.Add(thread1
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 1);
178 test::SimpleWaiterThread
thread2(&result2
, &context2
);
179 awakable_list
.Add(thread2
.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE
, 2);
181 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
182 awakable_list
.CancelAll();
184 EXPECT_EQ(MOJO_RESULT_CANCELLED
, result1
);
185 EXPECT_EQ(1u, context1
);
186 EXPECT_EQ(MOJO_RESULT_CANCELLED
, result2
);
187 EXPECT_EQ(2u, context2
);
189 // Awake one awakable, cancel other.
191 AwakableList awakable_list
;
192 test::SimpleWaiterThread
thread1(&result1
, &context1
);
193 awakable_list
.Add(thread1
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 3);
195 test::SimpleWaiterThread
thread2(&result2
, &context2
);
196 awakable_list
.Add(thread2
.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE
, 4);
198 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
199 awakable_list
.AwakeForStateChange(HandleSignalsState(
200 MOJO_HANDLE_SIGNAL_READABLE
,
201 MOJO_HANDLE_SIGNAL_READABLE
| MOJO_HANDLE_SIGNAL_WRITABLE
));
202 awakable_list
.Remove(thread1
.waiter());
203 awakable_list
.CancelAll();
205 EXPECT_EQ(MOJO_RESULT_OK
, result1
);
206 EXPECT_EQ(3u, context1
);
207 EXPECT_EQ(MOJO_RESULT_CANCELLED
, result2
);
208 EXPECT_EQ(4u, context2
);
210 // Cancel one awakable, awake other for unsatisfiability.
212 AwakableList awakable_list
;
213 test::SimpleWaiterThread
thread1(&result1
, &context1
);
214 awakable_list
.Add(thread1
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 5);
216 test::SimpleWaiterThread
thread2(&result2
, &context2
);
217 awakable_list
.Add(thread2
.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE
, 6);
219 base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
220 awakable_list
.AwakeForStateChange(HandleSignalsState(
221 MOJO_HANDLE_SIGNAL_NONE
, MOJO_HANDLE_SIGNAL_READABLE
));
222 awakable_list
.Remove(thread2
.waiter());
223 awakable_list
.CancelAll();
225 EXPECT_EQ(MOJO_RESULT_CANCELLED
, result1
);
226 EXPECT_EQ(5u, context1
);
227 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION
, result2
);
228 EXPECT_EQ(6u, context2
);
230 // Cancel one awakable, awake other for unsatisfiability.
232 AwakableList awakable_list
;
233 test::SimpleWaiterThread
thread1(&result1
, &context1
);
234 awakable_list
.Add(thread1
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 7);
237 base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
239 // Should do nothing.
240 awakable_list
.AwakeForStateChange(HandleSignalsState(
241 MOJO_HANDLE_SIGNAL_NONE
,
242 MOJO_HANDLE_SIGNAL_READABLE
| MOJO_HANDLE_SIGNAL_WRITABLE
));
244 test::SimpleWaiterThread
thread2(&result2
, &context2
);
245 awakable_list
.Add(thread2
.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE
, 8);
248 base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
251 awakable_list
.AwakeForStateChange(HandleSignalsState(
252 MOJO_HANDLE_SIGNAL_READABLE
,
253 MOJO_HANDLE_SIGNAL_READABLE
| MOJO_HANDLE_SIGNAL_WRITABLE
));
254 awakable_list
.Remove(thread1
.waiter());
256 base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
258 test::SimpleWaiterThread
thread3(&result3
, &context3
);
259 awakable_list
.Add(thread3
.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE
, 9);
262 test::SimpleWaiterThread
thread4(&result4
, &context4
);
263 awakable_list
.Add(thread4
.waiter(), MOJO_HANDLE_SIGNAL_READABLE
, 10);
266 base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
268 // Awake #2 and #3 for unsatisfiability.
269 awakable_list
.AwakeForStateChange(HandleSignalsState(
270 MOJO_HANDLE_SIGNAL_NONE
, MOJO_HANDLE_SIGNAL_READABLE
));
271 awakable_list
.Remove(thread2
.waiter());
272 awakable_list
.Remove(thread3
.waiter());
275 awakable_list
.CancelAll();
277 EXPECT_EQ(MOJO_RESULT_OK
, result1
);
278 EXPECT_EQ(7u, context1
);
279 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION
, result2
);
280 EXPECT_EQ(8u, context2
);
281 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION
, result3
);
282 EXPECT_EQ(9u, context3
);
283 EXPECT_EQ(MOJO_RESULT_CANCELLED
, result4
);
284 EXPECT_EQ(10u, context4
);
287 class KeepAwakable
: public Awakable
{
289 KeepAwakable() : awake_count(0) {}
291 bool Awake(MojoResult result
, uintptr_t context
) override
{
298 DISALLOW_COPY_AND_ASSIGN(KeepAwakable
);
301 class RemoveAwakable
: public Awakable
{
303 RemoveAwakable() : awake_count(0) {}
305 bool Awake(MojoResult result
, uintptr_t context
) override
{
312 DISALLOW_COPY_AND_ASSIGN(RemoveAwakable
);
315 TEST(AwakableListTest
, KeepAwakablesReturningTrue
) {
318 RemoveAwakable remove0
;
319 RemoveAwakable remove1
;
320 RemoveAwakable remove2
;
322 HandleSignalsState
hss(MOJO_HANDLE_SIGNAL_WRITABLE
,
323 MOJO_HANDLE_SIGNAL_WRITABLE
);
325 AwakableList remove_all
;
326 remove_all
.Add(&remove0
, MOJO_HANDLE_SIGNAL_WRITABLE
, 0);
327 remove_all
.Add(&remove1
, MOJO_HANDLE_SIGNAL_WRITABLE
, 0);
329 remove_all
.AwakeForStateChange(hss
);
330 EXPECT_EQ(remove0
.awake_count
, 1);
331 EXPECT_EQ(remove1
.awake_count
, 1);
333 remove_all
.AwakeForStateChange(hss
);
334 EXPECT_EQ(remove0
.awake_count
, 1);
335 EXPECT_EQ(remove1
.awake_count
, 1);
337 AwakableList remove_first
;
338 remove_first
.Add(&remove2
, MOJO_HANDLE_SIGNAL_WRITABLE
, 0);
339 remove_first
.Add(&keep0
, MOJO_HANDLE_SIGNAL_WRITABLE
, 0);
340 remove_first
.Add(&keep1
, MOJO_HANDLE_SIGNAL_WRITABLE
, 0);
342 remove_first
.AwakeForStateChange(hss
);
343 EXPECT_EQ(keep0
.awake_count
, 1);
344 EXPECT_EQ(keep1
.awake_count
, 1);
345 EXPECT_EQ(remove2
.awake_count
, 1);
347 remove_first
.AwakeForStateChange(hss
);
348 EXPECT_EQ(keep0
.awake_count
, 2);
349 EXPECT_EQ(keep1
.awake_count
, 2);
350 EXPECT_EQ(remove2
.awake_count
, 1);
352 remove_first
.Remove(&keep0
);
353 remove_first
.Remove(&keep1
);
357 } // namespace system