Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / mojo / system / waiter_list_unittest.cc
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::EpsilonTimeout()| 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/system/waiter_list.h"
11
12 #include "base/threading/platform_thread.h"  // For |Sleep()|.
13 #include "base/time/time.h"
14 #include "mojo/system/handle_signals_state.h"
15 #include "mojo/system/test_utils.h"
16 #include "mojo/system/waiter.h"
17 #include "mojo/system/waiter_test_utils.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 namespace mojo {
21 namespace system {
22 namespace {
23
24 TEST(WaiterListTest, BasicCancel) {
25   MojoResult result;
26   uint32_t context;
27
28   // Cancel immediately after thread start.
29   {
30     WaiterList waiter_list;
31     test::SimpleWaiterThread thread(&result, &context);
32     waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1);
33     thread.Start();
34     waiter_list.CancelAllWaiters();
35     // Double-remove okay:
36     waiter_list.RemoveWaiter(thread.waiter());
37   }  // Join |thread|.
38   EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
39   EXPECT_EQ(1u, context);
40
41   // Cancel before after thread start.
42   {
43     WaiterList waiter_list;
44     test::SimpleWaiterThread thread(&result, &context);
45     waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2);
46     waiter_list.CancelAllWaiters();
47     thread.Start();
48   }  // Join |thread|.
49   EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
50   EXPECT_EQ(2u, context);
51
52   // Cancel some time after thread start.
53   {
54     WaiterList waiter_list;
55     test::SimpleWaiterThread thread(&result, &context);
56     waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
57     thread.Start();
58     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
59     waiter_list.CancelAllWaiters();
60   }  // Join |thread|.
61   EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
62   EXPECT_EQ(3u, context);
63 }
64
65 TEST(WaiterListTest, BasicAwakeSatisfied) {
66   MojoResult result;
67   uint32_t context;
68
69   // Awake immediately after thread start.
70   {
71     WaiterList waiter_list;
72     test::SimpleWaiterThread thread(&result, &context);
73     waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1);
74     thread.Start();
75     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
76         MOJO_HANDLE_SIGNAL_READABLE,
77         MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
78     waiter_list.RemoveWaiter(thread.waiter());
79   }  // Join |thread|.
80   EXPECT_EQ(MOJO_RESULT_OK, result);
81   EXPECT_EQ(1u, context);
82
83   // Awake before after thread start.
84   {
85     WaiterList waiter_list;
86     test::SimpleWaiterThread thread(&result, &context);
87     waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2);
88     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
89         MOJO_HANDLE_SIGNAL_WRITABLE,
90         MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
91     waiter_list.RemoveWaiter(thread.waiter());
92     // Double-remove okay:
93     waiter_list.RemoveWaiter(thread.waiter());
94     thread.Start();
95   }  // Join |thread|.
96   EXPECT_EQ(MOJO_RESULT_OK, result);
97   EXPECT_EQ(2u, context);
98
99   // Awake some time after thread start.
100   {
101     WaiterList waiter_list;
102     test::SimpleWaiterThread thread(&result, &context);
103     waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
104     thread.Start();
105     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
106     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
107         MOJO_HANDLE_SIGNAL_READABLE,
108         MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
109     waiter_list.RemoveWaiter(thread.waiter());
110   }  // Join |thread|.
111   EXPECT_EQ(MOJO_RESULT_OK, result);
112   EXPECT_EQ(3u, context);
113 }
114
115 TEST(WaiterListTest, BasicAwakeUnsatisfiable) {
116   MojoResult result;
117   uint32_t context;
118
119   // Awake (for unsatisfiability) immediately after thread start.
120   {
121     WaiterList waiter_list;
122     test::SimpleWaiterThread thread(&result, &context);
123     waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1);
124     thread.Start();
125     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
126         MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE));
127     waiter_list.RemoveWaiter(thread.waiter());
128   }  // Join |thread|.
129   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
130   EXPECT_EQ(1u, context);
131
132   // Awake (for unsatisfiability) before after thread start.
133   {
134     WaiterList waiter_list;
135     test::SimpleWaiterThread thread(&result, &context);
136     waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2);
137     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
138         MOJO_HANDLE_SIGNAL_READABLE, MOJO_HANDLE_SIGNAL_READABLE));
139     waiter_list.RemoveWaiter(thread.waiter());
140     thread.Start();
141   }  // Join |thread|.
142   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
143   EXPECT_EQ(2u, context);
144
145   // Awake (for unsatisfiability) some time after thread start.
146   {
147     WaiterList waiter_list;
148     test::SimpleWaiterThread thread(&result, &context);
149     waiter_list.AddWaiter(thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
150     thread.Start();
151     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
152     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
153         MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_WRITABLE));
154     waiter_list.RemoveWaiter(thread.waiter());
155     // Double-remove okay:
156     waiter_list.RemoveWaiter(thread.waiter());
157   }  // Join |thread|.
158   EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
159   EXPECT_EQ(3u, context);
160 }
161
162 TEST(WaiterListTest, MultipleWaiters) {
163   MojoResult result1;
164   MojoResult result2;
165   MojoResult result3;
166   MojoResult result4;
167   uint32_t context1;
168   uint32_t context2;
169   uint32_t context3;
170   uint32_t context4;
171
172   // Cancel two waiters.
173   {
174     WaiterList waiter_list;
175     test::SimpleWaiterThread thread1(&result1, &context1);
176     waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1);
177     thread1.Start();
178     test::SimpleWaiterThread thread2(&result2, &context2);
179     waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 2);
180     thread2.Start();
181     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
182     waiter_list.CancelAllWaiters();
183   }  // Join threads.
184   EXPECT_EQ(MOJO_RESULT_CANCELLED, result1);
185   EXPECT_EQ(1u, context1);
186   EXPECT_EQ(MOJO_RESULT_CANCELLED, result2);
187   EXPECT_EQ(2u, context2);
188
189   // Awake one waiter, cancel other.
190   {
191     WaiterList waiter_list;
192     test::SimpleWaiterThread thread1(&result1, &context1);
193     waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3);
194     thread1.Start();
195     test::SimpleWaiterThread thread2(&result2, &context2);
196     waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 4);
197     thread2.Start();
198     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
199     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
200         MOJO_HANDLE_SIGNAL_READABLE,
201         MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
202     waiter_list.RemoveWaiter(thread1.waiter());
203     waiter_list.CancelAllWaiters();
204   }  // Join threads.
205   EXPECT_EQ(MOJO_RESULT_OK, result1);
206   EXPECT_EQ(3u, context1);
207   EXPECT_EQ(MOJO_RESULT_CANCELLED, result2);
208   EXPECT_EQ(4u, context2);
209
210   // Cancel one waiter, awake other for unsatisfiability.
211   {
212     WaiterList waiter_list;
213     test::SimpleWaiterThread thread1(&result1, &context1);
214     waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 5);
215     thread1.Start();
216     test::SimpleWaiterThread thread2(&result2, &context2);
217     waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 6);
218     thread2.Start();
219     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
220     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
221         MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE));
222     waiter_list.RemoveWaiter(thread2.waiter());
223     waiter_list.CancelAllWaiters();
224   }  // Join threads.
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);
229
230   // Cancel one waiter, awake other for unsatisfiability.
231   {
232     WaiterList waiter_list;
233     test::SimpleWaiterThread thread1(&result1, &context1);
234     waiter_list.AddWaiter(thread1.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 7);
235     thread1.Start();
236
237     base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
238
239     // Should do nothing.
240     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
241         MOJO_HANDLE_SIGNAL_NONE,
242         MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
243
244     test::SimpleWaiterThread thread2(&result2, &context2);
245     waiter_list.AddWaiter(thread2.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 8);
246     thread2.Start();
247
248     base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
249
250     // Awake #1.
251     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
252         MOJO_HANDLE_SIGNAL_READABLE,
253         MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE));
254     waiter_list.RemoveWaiter(thread1.waiter());
255
256     base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
257
258     test::SimpleWaiterThread thread3(&result3, &context3);
259     waiter_list.AddWaiter(thread3.waiter(), MOJO_HANDLE_SIGNAL_WRITABLE, 9);
260     thread3.Start();
261
262     test::SimpleWaiterThread thread4(&result4, &context4);
263     waiter_list.AddWaiter(thread4.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 10);
264     thread4.Start();
265
266     base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
267
268     // Awake #2 and #3 for unsatisfiability.
269     waiter_list.AwakeWaitersForStateChange(HandleSignalsState(
270         MOJO_HANDLE_SIGNAL_NONE, MOJO_HANDLE_SIGNAL_READABLE));
271     waiter_list.RemoveWaiter(thread2.waiter());
272     waiter_list.RemoveWaiter(thread3.waiter());
273
274     // Cancel #4.
275     waiter_list.CancelAllWaiters();
276   }  // Join threads.
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);
285 }
286
287 }  // namespace
288 }  // namespace system
289 }  // namespace mojo