1 // Copyright 2019 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 #include "platform/api/time.h"
6
7 #include <chrono>
8 #include <thread>
9
10 #include "gtest/gtest.h"
11 #include "util/chrono_helpers.h"
12
13 namespace openscreen {
14 namespace {
15
16 // Tests that the clock always seems to tick forward. If this test is broken, or
17 // is flaky, the time source is probably not monotonic.
TEST(TimeTest,PlatformClockIsMonotonic)18 TEST(TimeTest, PlatformClockIsMonotonic) {
19 constexpr auto kSleepPeriod = milliseconds(2);
20 for (int i = 0; i < 50; ++i) {
21 const auto start = Clock::now();
22 std::this_thread::sleep_for(kSleepPeriod);
23 const auto stop = Clock::now();
24 EXPECT_GE(stop - start, kSleepPeriod / 2);
25 }
26 }
27
28 // Tests that the clock ticks at least 10000 times per second, a requirement
29 // specified in the API header comments.
TEST(TimeTest,PlatformClockHasSufficientResolution)30 TEST(TimeTest, PlatformClockHasSufficientResolution) {
31 constexpr std::chrono::duration<int, Clock::kRequiredResolution>
32 kMaxAllowedDurationBetweenTicks(1);
33 constexpr int kMaxRetries = 100;
34
35 // Loop until a small-enough clock change is observed. The platform is given
36 // multiple chances because unpredictable events, like thread context
37 // switches, could suspend the current thread for a "long" time, masking what
38 // the clock is actually capable of.
39 Clock::duration delta = microseconds(0);
40 for (int i = 0; i < kMaxRetries; ++i) {
41 const auto start = Clock::now();
42 // Loop until the clock changes.
43 do {
44 delta = Clock::now() - start;
45 ASSERT_LE(microseconds(0), delta);
46 } while (delta == microseconds(0));
47
48 if (delta <= kMaxAllowedDurationBetweenTicks) {
49 break;
50 }
51 }
52
53 EXPECT_LE(delta, kMaxAllowedDurationBetweenTicks);
54 }
55
56 } // namespace
57 } // namespace openscreen
58