blob: af17a6549742dc32f9decc69202dd73f4ab353de [file] [log] [blame]
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -07001// Copyright 2020 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#include <chrono>
16
17#include "gtest/gtest.h"
18#include "pw_chrono/system_clock.h"
19#include "pw_preprocessor/util.h"
20
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080021using namespace std::chrono_literals;
22
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -070023namespace pw::chrono {
24namespace {
25
26extern "C" {
27
28// Functions defined in system_clock_facade_test_c.c which call the API from C.
29pw_chrono_SystemClock_TimePoint pw_chrono_SystemClock_CallNow();
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080030pw_chrono_SystemClock_Duration pw_chrono_SystemClock_CallTimeElapsed(
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -070031 pw_chrono_SystemClock_TimePoint last_time,
32 pw_chrono_SystemClock_TimePoint current_time);
33
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080034pw_chrono_SystemClock_Nanoseconds pw_chrono_SystemClock_CallDurationToNsFloor(
35 pw_chrono_SystemClock_Duration ticks);
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -070036
37} // extern "C"
38
39// While testing that the clock ticks (i.e. moves forward) we want to ensure a
40// failure can be reported instead of deadlocking the test until it passes.
41// Given that there isn't really a good heuristic for this we instead make some
42// wild assumptions to bound the maximum busy loop iterations.
43// - Assume our clock is < 6Ghz
44// - Assume we can check the clock in a single cycle
45// - Wait for up to 1/10th of a second @ 6Ghz, this may be a long period on a
46// slower (i.e. real) machine.
47constexpr uint64_t kMaxIterations = 6'000'000'000 / 10;
48
49TEST(SystemClock, Now) {
50 const SystemClock::time_point start_time = SystemClock::now();
51 // Verify the clock moves forward.
52 bool clock_moved_forward = false;
53 for (uint64_t i = 0; i < kMaxIterations; ++i) {
54 if (SystemClock::now() > start_time) {
55 clock_moved_forward = true;
56 break;
57 }
58 }
59 EXPECT_TRUE(clock_moved_forward);
60}
61
62TEST(VirtualSystemClock, Now) {
63 auto& clock = VirtualSystemClock::RealClock();
64 const SystemClock::time_point start_time = clock.now();
65 // Verify the clock moves forward.
66 bool clock_moved_forward = false;
67 for (uint64_t i = 0; i < kMaxIterations; ++i) {
68 if (clock.now() > start_time) {
69 clock_moved_forward = true;
70 break;
71 }
72 }
73 EXPECT_TRUE(clock_moved_forward);
74}
75
76TEST(SystemClock, NowInC) {
77 const pw_chrono_SystemClock_TimePoint start_time =
78 pw_chrono_SystemClock_CallNow();
79 // Verify the clock moves forward.
80 bool clock_moved_forward = false;
81 for (uint64_t i = 0; i < kMaxIterations; ++i) {
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080082 if (pw_chrono_SystemClock_CallNow().duration_since_epoch.ticks >
83 start_time.duration_since_epoch.ticks) {
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -070084 clock_moved_forward = true;
85 break;
86 }
87 }
88 EXPECT_TRUE(clock_moved_forward);
89}
90
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080091TEST(SystemClock, TimeElapsedInC) {
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -070092 const pw_chrono_SystemClock_TimePoint first = pw_chrono_SystemClock_CallNow();
93 const pw_chrono_SystemClock_TimePoint last = pw_chrono_SystemClock_CallNow();
94 static_assert(SystemClock::is_monotonic);
Ewout van Bekkum830d5d12021-01-28 18:58:03 -080095 EXPECT_GE(0, pw_chrono_SystemClock_CallTimeElapsed(last, first).ticks);
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -070096}
97
98TEST(SystemClock, DurationCastInC) {
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -070099 // We can't control the SystemClock's period configuration, so just in case
100 // 42 hours cannot be accurately expressed in integer ticks, round the
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800101 // duration w/ floor.
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -0700102 static constexpr auto kRoundedArbitraryDuration =
Ewout van Bekkum830d5d12021-01-28 18:58:03 -0800103 std::chrono::floor<SystemClock::duration>(42h);
104 static constexpr pw_chrono_SystemClock_Duration kRoundedArbitraryDurationInC =
105 PW_SYSTEM_CLOCK_H_FLOOR(42);
106 EXPECT_EQ(
107 std::chrono::floor<std::chrono::nanoseconds>(kRoundedArbitraryDuration)
108 .count(),
109 pw_chrono_SystemClock_CallDurationToNsFloor(
110 kRoundedArbitraryDurationInC));
Ewout van Bekkum3c61ae92020-10-30 15:52:25 -0700111}
112
113} // namespace
114} // namespace pw::chrono