14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file.
44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// NOTE(vtl): These tests are inherently flaky (e.g., if run on a heavily-loaded
64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// system). Sorry. |kEpsilonMicros| may be increased to increase tolerance and
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// reduce observed flakiness.
84e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/waiter.h"
104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/basictypes.h"
124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/compiler_specific.h"
134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/synchronization/lock.h"
144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/threading/platform_thread.h"  // For |Sleep()|.
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/threading/simple_thread.h"
164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/time/time.h"
174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "mojo/system/test_utils.h"
184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace mojo {
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace system {
224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace {
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const int64_t kMicrosPerMs = 1000;
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const int64_t kEpsilonMicros = 15 * kMicrosPerMs;  // 15 ms.
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const int64_t kPollTimeMicros = 10 * kMicrosPerMs;  // 10 ms.
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class WaitingThread : public base::SimpleThread {
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  explicit WaitingThread(MojoDeadline deadline)
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : base::SimpleThread("waiting_thread"),
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        deadline_(deadline),
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        done_(false),
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        result_(MOJO_RESULT_UNKNOWN),
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        elapsed_micros_(-1) {
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    waiter_.Init();
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual ~WaitingThread() {
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    Join();
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void WaitUntilDone(MojoResult* result, int64_t* elapsed_micros) {
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (;;) {
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      {
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::AutoLock locker(lock_);
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        if (done_) {
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          *result = result_;
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          *elapsed_micros = elapsed_micros_;
504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          break;
514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        }
524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::PlatformThread::Sleep(
554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          base::TimeDelta::FromMicroseconds(kPollTimeMicros));
564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Waiter* waiter() { return &waiter_; }
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void Run() OVERRIDE {
634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    test::Stopwatch stopwatch;
644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    MojoResult result;
654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    int64_t elapsed_micros;
664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    stopwatch.Start();
684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    result = waiter_.Wait(deadline_);
694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    elapsed_micros = stopwatch.Elapsed();
704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    {
724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      base::AutoLock locker(lock_);
734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      done_ = true;
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      result_ = result;
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      elapsed_micros_ = elapsed_micros;
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const MojoDeadline deadline_;
804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Waiter waiter_;  // Thread-safe.
814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  base::Lock lock_;  // Protects the following members.
834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool done_;
844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  MojoResult result_;
854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int64_t elapsed_micros_;
864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(WaitingThread);
884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)};
894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(WaiterTest, Basic) {
914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  MojoResult result;
924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int64_t elapsed_micros;
934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Finite deadline.
954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Awake immediately after thread start.
974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(static_cast<MojoDeadline>(10 * kEpsilonMicros));
994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(0);
1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(0, result);
1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, kEpsilonMicros);
1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Awake before after thread start.
1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(static_cast<MojoDeadline>(10 * kEpsilonMicros));
1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(MOJO_RESULT_CANCELLED);
1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, kEpsilonMicros);
1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Awake some time after thread start.
1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(static_cast<MojoDeadline>(10 * kEpsilonMicros));
1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::PlatformThread::Sleep(
1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros));
1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(1);
1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(1, result);
1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros);
1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros);
1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Awake some longer time after thread start.
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(static_cast<MojoDeadline>(10 * kEpsilonMicros));
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::PlatformThread::Sleep(
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::TimeDelta::FromMicroseconds(5 * kEpsilonMicros));
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(1);
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(1, result);
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_GT(elapsed_micros, (5-1) * kEpsilonMicros);
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, (5+1) * kEpsilonMicros);
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Don't awake -- time out (on another thread).
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(static_cast<MojoDeadline>(2 * kEpsilonMicros));
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, result);
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros);
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros);
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // No (indefinite) deadline.
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Awake immediately after thread start.
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(0);
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(0, result);
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, kEpsilonMicros);
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Awake before after thread start.
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(MOJO_RESULT_CANCELLED);
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, kEpsilonMicros);
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Awake some time after thread start.
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::PlatformThread::Sleep(
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros));
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(1);
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(1, result);
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros);
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros);
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Awake some longer time after thread start.
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
1894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::PlatformThread::Sleep(
1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::TimeDelta::FromMicroseconds(5 * kEpsilonMicros));
1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(1);
1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(1, result);
1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_GT(elapsed_micros, (5-1) * kEpsilonMicros);
1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, (5+1) * kEpsilonMicros);
1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(WaiterTest, TimeOut) {
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  test::Stopwatch stopwatch;
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int64_t elapsed_micros;
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Waiter waiter;
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  waiter.Init();
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  stopwatch.Start();
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0));
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  elapsed_micros = stopwatch.Elapsed();
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_LT(elapsed_micros, kEpsilonMicros);
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  waiter.Init();
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  stopwatch.Start();
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            waiter.Wait(static_cast<MojoDeadline>(2 * kEpsilonMicros)));
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  elapsed_micros = stopwatch.Elapsed();
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_GT(elapsed_micros, (2-1) * kEpsilonMicros);
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_LT(elapsed_micros, (2+1) * kEpsilonMicros);
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  waiter.Init();
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  stopwatch.Start();
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)            waiter.Wait(static_cast<MojoDeadline>(5 * kEpsilonMicros)));
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  elapsed_micros = stopwatch.Elapsed();
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_GT(elapsed_micros, (5-1) * kEpsilonMicros);
2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_LT(elapsed_micros, (5+1) * kEpsilonMicros);
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// The first |Awake()| should always win.
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST(WaiterTest, MultipleAwakes) {
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  MojoResult result;
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int64_t elapsed_micros;
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(0);
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(1);
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(0, result);
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, kEpsilonMicros);
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
2464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
2474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(1);
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(0);
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(1, result);
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, kEpsilonMicros);
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(MOJO_DEADLINE_INDEFINITE);
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(10);
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::PlatformThread::Sleep(
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros));
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(20);
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(10, result);
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, kEpsilonMicros);
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    WaitingThread thread(static_cast<MojoDeadline>(10 * kEpsilonMicros));
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.Start();
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::PlatformThread::Sleep(
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::TimeDelta::FromMicroseconds(1 * kEpsilonMicros));
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(MOJO_RESULT_FAILED_PRECONDITION);
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    base::PlatformThread::Sleep(
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        base::TimeDelta::FromMicroseconds(2 * kEpsilonMicros));
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.waiter()->Awake(0);
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread.WaitUntilDone(&result, &elapsed_micros);
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_GT(elapsed_micros, (1-1) * kEpsilonMicros);
2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    EXPECT_LT(elapsed_micros, (1+1) * kEpsilonMicros);
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace
2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace system
2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}  // namespace mojo
286