Upstream version 11.40.271.0
[platform/framework/web/crosswalk.git] / src / mojo / edk / system / waiter_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/edk/system/waiter.h"
11
12 #include <stdint.h>
13
14 #include "base/macros.h"
15 #include "base/synchronization/lock.h"
16 #include "base/threading/platform_thread.h"  // For |Sleep()|.
17 #include "base/threading/simple_thread.h"
18 #include "base/time/time.h"
19 #include "mojo/edk/system/test_utils.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace mojo {
23 namespace system {
24 namespace {
25
26 const int64_t kMicrosPerMs = 1000;
27 const int64_t kPollTimeMicros = 10 * kMicrosPerMs;  // 10 ms.
28
29 class WaitingThread : public base::SimpleThread {
30  public:
31   explicit WaitingThread(MojoDeadline deadline)
32       : base::SimpleThread("waiting_thread"),
33         deadline_(deadline),
34         done_(false),
35         result_(MOJO_RESULT_UNKNOWN),
36         context_(static_cast<uint32_t>(-1)) {
37     waiter_.Init();
38   }
39
40   ~WaitingThread() override { Join(); }
41
42   void WaitUntilDone(MojoResult* result,
43                      uint32_t* context,
44                      base::TimeDelta* elapsed) {
45     for (;;) {
46       {
47         base::AutoLock locker(lock_);
48         if (done_) {
49           *result = result_;
50           *context = context_;
51           *elapsed = elapsed_;
52           break;
53         }
54       }
55
56       base::PlatformThread::Sleep(
57           base::TimeDelta::FromMicroseconds(kPollTimeMicros));
58     }
59   }
60
61   Waiter* waiter() { return &waiter_; }
62
63  private:
64   void Run() override {
65     test::Stopwatch stopwatch;
66     MojoResult result;
67     uint32_t context = static_cast<uint32_t>(-1);
68     base::TimeDelta elapsed;
69
70     stopwatch.Start();
71     result = waiter_.Wait(deadline_, &context);
72     elapsed = stopwatch.Elapsed();
73
74     {
75       base::AutoLock locker(lock_);
76       done_ = true;
77       result_ = result;
78       context_ = context;
79       elapsed_ = elapsed;
80     }
81   }
82
83   const MojoDeadline deadline_;
84   Waiter waiter_;  // Thread-safe.
85
86   base::Lock lock_;  // Protects the following members.
87   bool done_;
88   MojoResult result_;
89   uint32_t context_;
90   base::TimeDelta elapsed_;
91
92   DISALLOW_COPY_AND_ASSIGN(WaitingThread);
93 };
94
95 TEST(WaiterTest, Basic) {
96   MojoResult result;
97   uint32_t context;
98   base::TimeDelta elapsed;
99
100   // Finite deadline.
101
102   // Awake immediately after thread start.
103   {
104     WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
105     thread.Start();
106     thread.waiter()->Awake(MOJO_RESULT_OK, 1);
107     thread.WaitUntilDone(&result, &context, &elapsed);
108     EXPECT_EQ(MOJO_RESULT_OK, result);
109     EXPECT_EQ(1u, context);
110     EXPECT_LT(elapsed, test::EpsilonTimeout());
111   }
112
113   // Awake before after thread start.
114   {
115     WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
116     thread.waiter()->Awake(MOJO_RESULT_CANCELLED, 2);
117     thread.Start();
118     thread.WaitUntilDone(&result, &context, &elapsed);
119     EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
120     EXPECT_EQ(2u, context);
121     EXPECT_LT(elapsed, test::EpsilonTimeout());
122   }
123
124   // Awake some time after thread start.
125   {
126     WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
127     thread.Start();
128     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
129     thread.waiter()->Awake(1, 3);
130     thread.WaitUntilDone(&result, &context, &elapsed);
131     EXPECT_EQ(1, result);
132     EXPECT_EQ(3u, context);
133     EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
134     EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
135   }
136
137   // Awake some longer time after thread start.
138   {
139     WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
140     thread.Start();
141     base::PlatformThread::Sleep(5 * test::EpsilonTimeout());
142     thread.waiter()->Awake(2, 4);
143     thread.WaitUntilDone(&result, &context, &elapsed);
144     EXPECT_EQ(2, result);
145     EXPECT_EQ(4u, context);
146     EXPECT_GT(elapsed, (5 - 1) * test::EpsilonTimeout());
147     EXPECT_LT(elapsed, (5 + 1) * test::EpsilonTimeout());
148   }
149
150   // Don't awake -- time out (on another thread).
151   {
152     WaitingThread thread(2 * test::EpsilonTimeout().InMicroseconds());
153     thread.Start();
154     thread.WaitUntilDone(&result, &context, &elapsed);
155     EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result);
156     EXPECT_EQ(static_cast<uint32_t>(-1), context);
157     EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
158     EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
159   }
160
161   // No (indefinite) deadline.
162
163   // Awake immediately after thread start.
164   {
165     WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
166     thread.Start();
167     thread.waiter()->Awake(MOJO_RESULT_OK, 5);
168     thread.WaitUntilDone(&result, &context, &elapsed);
169     EXPECT_EQ(MOJO_RESULT_OK, result);
170     EXPECT_EQ(5u, context);
171     EXPECT_LT(elapsed, test::EpsilonTimeout());
172   }
173
174   // Awake before after thread start.
175   {
176     WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
177     thread.waiter()->Awake(MOJO_RESULT_CANCELLED, 6);
178     thread.Start();
179     thread.WaitUntilDone(&result, &context, &elapsed);
180     EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
181     EXPECT_EQ(6u, context);
182     EXPECT_LT(elapsed, test::EpsilonTimeout());
183   }
184
185   // Awake some time after thread start.
186   {
187     WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
188     thread.Start();
189     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
190     thread.waiter()->Awake(1, 7);
191     thread.WaitUntilDone(&result, &context, &elapsed);
192     EXPECT_EQ(1, result);
193     EXPECT_EQ(7u, context);
194     EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
195     EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
196   }
197
198   // Awake some longer time after thread start.
199   {
200     WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
201     thread.Start();
202     base::PlatformThread::Sleep(5 * test::EpsilonTimeout());
203     thread.waiter()->Awake(2, 8);
204     thread.WaitUntilDone(&result, &context, &elapsed);
205     EXPECT_EQ(2, result);
206     EXPECT_EQ(8u, context);
207     EXPECT_GT(elapsed, (5 - 1) * test::EpsilonTimeout());
208     EXPECT_LT(elapsed, (5 + 1) * test::EpsilonTimeout());
209   }
210 }
211
212 TEST(WaiterTest, TimeOut) {
213   test::Stopwatch stopwatch;
214   base::TimeDelta elapsed;
215
216   Waiter waiter;
217   uint32_t context = 123;
218
219   waiter.Init();
220   stopwatch.Start();
221   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, &context));
222   elapsed = stopwatch.Elapsed();
223   EXPECT_LT(elapsed, test::EpsilonTimeout());
224   EXPECT_EQ(123u, context);
225
226   waiter.Init();
227   stopwatch.Start();
228   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
229             waiter.Wait(2 * test::EpsilonTimeout().InMicroseconds(), &context));
230   elapsed = stopwatch.Elapsed();
231   EXPECT_GT(elapsed, (2 - 1) * test::EpsilonTimeout());
232   EXPECT_LT(elapsed, (2 + 1) * test::EpsilonTimeout());
233   EXPECT_EQ(123u, context);
234
235   waiter.Init();
236   stopwatch.Start();
237   EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
238             waiter.Wait(5 * test::EpsilonTimeout().InMicroseconds(), &context));
239   elapsed = stopwatch.Elapsed();
240   EXPECT_GT(elapsed, (5 - 1) * test::EpsilonTimeout());
241   EXPECT_LT(elapsed, (5 + 1) * test::EpsilonTimeout());
242   EXPECT_EQ(123u, context);
243 }
244
245 // The first |Awake()| should always win.
246 TEST(WaiterTest, MultipleAwakes) {
247   MojoResult result;
248   uint32_t context;
249   base::TimeDelta elapsed;
250
251   {
252     WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
253     thread.Start();
254     thread.waiter()->Awake(MOJO_RESULT_OK, 1);
255     thread.waiter()->Awake(1, 2);
256     thread.WaitUntilDone(&result, &context, &elapsed);
257     EXPECT_EQ(MOJO_RESULT_OK, result);
258     EXPECT_EQ(1u, context);
259     EXPECT_LT(elapsed, test::EpsilonTimeout());
260   }
261
262   {
263     WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
264     thread.waiter()->Awake(1, 3);
265     thread.Start();
266     thread.waiter()->Awake(MOJO_RESULT_OK, 4);
267     thread.WaitUntilDone(&result, &context, &elapsed);
268     EXPECT_EQ(1, result);
269     EXPECT_EQ(3u, context);
270     EXPECT_LT(elapsed, test::EpsilonTimeout());
271   }
272
273   {
274     WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
275     thread.Start();
276     thread.waiter()->Awake(10, 5);
277     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
278     thread.waiter()->Awake(20, 6);
279     thread.WaitUntilDone(&result, &context, &elapsed);
280     EXPECT_EQ(10, result);
281     EXPECT_EQ(5u, context);
282     EXPECT_LT(elapsed, test::EpsilonTimeout());
283   }
284
285   {
286     WaitingThread thread(10 * test::EpsilonTimeout().InMicroseconds());
287     thread.Start();
288     base::PlatformThread::Sleep(1 * test::EpsilonTimeout());
289     thread.waiter()->Awake(MOJO_RESULT_FAILED_PRECONDITION, 7);
290     base::PlatformThread::Sleep(2 * test::EpsilonTimeout());
291     thread.waiter()->Awake(MOJO_RESULT_OK, 8);
292     thread.WaitUntilDone(&result, &context, &elapsed);
293     EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
294     EXPECT_EQ(7u, context);
295     EXPECT_GT(elapsed, (1 - 1) * test::EpsilonTimeout());
296     EXPECT_LT(elapsed, (1 + 1) * test::EpsilonTimeout());
297   }
298 }
299
300 }  // namespace
301 }  // namespace system
302 }  // namespace mojo