1*14675a02SAndroid Build Coastguard Worker /*
2*14675a02SAndroid Build Coastguard Worker * Copyright 2020 Google LLC
3*14675a02SAndroid Build Coastguard Worker *
4*14675a02SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*14675a02SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*14675a02SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*14675a02SAndroid Build Coastguard Worker *
8*14675a02SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*14675a02SAndroid Build Coastguard Worker *
10*14675a02SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*14675a02SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*14675a02SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*14675a02SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*14675a02SAndroid Build Coastguard Worker * limitations under the License.
15*14675a02SAndroid Build Coastguard Worker */
16*14675a02SAndroid Build Coastguard Worker
17*14675a02SAndroid Build Coastguard Worker #include "fcp/base/simulated_clock.h"
18*14675a02SAndroid Build Coastguard Worker
19*14675a02SAndroid Build Coastguard Worker #include <functional>
20*14675a02SAndroid Build Coastguard Worker #include <memory>
21*14675a02SAndroid Build Coastguard Worker #include <utility>
22*14675a02SAndroid Build Coastguard Worker #include <vector>
23*14675a02SAndroid Build Coastguard Worker
24*14675a02SAndroid Build Coastguard Worker #include "gmock/gmock.h"
25*14675a02SAndroid Build Coastguard Worker #include "gtest/gtest.h"
26*14675a02SAndroid Build Coastguard Worker #include "absl/time/civil_time.h"
27*14675a02SAndroid Build Coastguard Worker #include "absl/time/time.h"
28*14675a02SAndroid Build Coastguard Worker
29*14675a02SAndroid Build Coastguard Worker namespace fcp {
30*14675a02SAndroid Build Coastguard Worker namespace {
31*14675a02SAndroid Build Coastguard Worker
32*14675a02SAndroid Build Coastguard Worker using ::testing::ElementsAre;
33*14675a02SAndroid Build Coastguard Worker using ::testing::Eq;
34*14675a02SAndroid Build Coastguard Worker
35*14675a02SAndroid Build Coastguard Worker // Simple callback waiter that runs the function on Wakeup.
36*14675a02SAndroid Build Coastguard Worker class CallbackWaiter : public Clock::Waiter {
37*14675a02SAndroid Build Coastguard Worker public:
CallbackWaiter(std::function<void ()> callback)38*14675a02SAndroid Build Coastguard Worker explicit CallbackWaiter(std::function<void()> callback)
39*14675a02SAndroid Build Coastguard Worker : callback_(std::move(callback)) {}
40*14675a02SAndroid Build Coastguard Worker
WakeUp()41*14675a02SAndroid Build Coastguard Worker void WakeUp() override { callback_(); }
42*14675a02SAndroid Build Coastguard Worker
43*14675a02SAndroid Build Coastguard Worker private:
44*14675a02SAndroid Build Coastguard Worker std::function<void()> callback_;
45*14675a02SAndroid Build Coastguard Worker };
46*14675a02SAndroid Build Coastguard Worker
47*14675a02SAndroid Build Coastguard Worker // Simple test waiter that adds its ID to the provided vector when WakeUp is
48*14675a02SAndroid Build Coastguard Worker // called. This is used to verify that waiters are woken up in the right order.
49*14675a02SAndroid Build Coastguard Worker class TestWaiter : public CallbackWaiter {
50*14675a02SAndroid Build Coastguard Worker public:
TestWaiter(int id,std::vector<int> * output)51*14675a02SAndroid Build Coastguard Worker explicit TestWaiter(int id, std::vector<int>* output)
52*14675a02SAndroid Build Coastguard Worker : CallbackWaiter([=]() { output->push_back(id); }) {}
53*14675a02SAndroid Build Coastguard Worker };
54*14675a02SAndroid Build Coastguard Worker
GetTestInitialTime()55*14675a02SAndroid Build Coastguard Worker absl::Time GetTestInitialTime() {
56*14675a02SAndroid Build Coastguard Worker return absl::FromCivil(absl::CivilDay(2020, 1, 1), absl::LocalTimeZone());
57*14675a02SAndroid Build Coastguard Worker }
58*14675a02SAndroid Build Coastguard Worker
TEST(SimulatedClockTest,GetAndUpdateNow)59*14675a02SAndroid Build Coastguard Worker TEST(SimulatedClockTest, GetAndUpdateNow) {
60*14675a02SAndroid Build Coastguard Worker absl::Time t = absl::UnixEpoch();
61*14675a02SAndroid Build Coastguard Worker SimulatedClock clock;
62*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(clock.Now(), t);
63*14675a02SAndroid Build Coastguard Worker
64*14675a02SAndroid Build Coastguard Worker absl::Time t2 = GetTestInitialTime();
65*14675a02SAndroid Build Coastguard Worker
66*14675a02SAndroid Build Coastguard Worker SimulatedClock clock2(t2);
67*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(clock2.Now(), t2);
68*14675a02SAndroid Build Coastguard Worker
69*14675a02SAndroid Build Coastguard Worker absl::Time t3 = t2 + absl::Seconds(42);
70*14675a02SAndroid Build Coastguard Worker clock2.AdvanceTime(absl::Seconds(42));
71*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(clock2.Now(), t3);
72*14675a02SAndroid Build Coastguard Worker
73*14675a02SAndroid Build Coastguard Worker absl::Time t4 = t3 + absl::Seconds(18);
74*14675a02SAndroid Build Coastguard Worker clock2.SetTime(t4);
75*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(clock2.Now(), Eq(t4));
76*14675a02SAndroid Build Coastguard Worker }
77*14675a02SAndroid Build Coastguard Worker
78*14675a02SAndroid Build Coastguard Worker // Verifies that waiters with future deadlines are not triggered unless the
79*14675a02SAndroid Build Coastguard Worker // time is advanced.
TEST(SimulatedClockTest,FutureDeadline)80*14675a02SAndroid Build Coastguard Worker TEST(SimulatedClockTest, FutureDeadline) {
81*14675a02SAndroid Build Coastguard Worker std::vector<int> output;
82*14675a02SAndroid Build Coastguard Worker absl::Time t = GetTestInitialTime();
83*14675a02SAndroid Build Coastguard Worker SimulatedClock clock(t);
84*14675a02SAndroid Build Coastguard Worker
85*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t + absl::Seconds(1),
86*14675a02SAndroid Build Coastguard Worker std::make_shared<TestWaiter>(1, &output));
87*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(output, ElementsAre());
88*14675a02SAndroid Build Coastguard Worker
89*14675a02SAndroid Build Coastguard Worker clock.AdvanceTime(absl::Seconds(1));
90*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(output, ElementsAre(1));
91*14675a02SAndroid Build Coastguard Worker
92*14675a02SAndroid Build Coastguard Worker // Advancing time again doesn't trigger the same waiter again.
93*14675a02SAndroid Build Coastguard Worker clock.AdvanceTime(absl::Seconds(1));
94*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(output, ElementsAre(1));
95*14675a02SAndroid Build Coastguard Worker }
96*14675a02SAndroid Build Coastguard Worker
97*14675a02SAndroid Build Coastguard Worker // Verifies that the order of waiters with maching deadlines is preserved
98*14675a02SAndroid Build Coastguard Worker // when their wake-up is triggered.
TEST(SimulatedClockTest,MatchingDeadlines)99*14675a02SAndroid Build Coastguard Worker TEST(SimulatedClockTest, MatchingDeadlines) {
100*14675a02SAndroid Build Coastguard Worker std::vector<int> output;
101*14675a02SAndroid Build Coastguard Worker absl::Time t = GetTestInitialTime();
102*14675a02SAndroid Build Coastguard Worker SimulatedClock clock(t);
103*14675a02SAndroid Build Coastguard Worker
104*14675a02SAndroid Build Coastguard Worker absl::Time t1 = t + absl::Seconds(1);
105*14675a02SAndroid Build Coastguard Worker absl::Time t2 = t + absl::Seconds(2);
106*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t1, std::make_shared<TestWaiter>(1, &output));
107*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t2, std::make_shared<TestWaiter>(2, &output));
108*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t1, std::make_shared<TestWaiter>(3, &output));
109*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t2, std::make_shared<TestWaiter>(4, &output));
110*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t1, std::make_shared<TestWaiter>(5, &output));
111*14675a02SAndroid Build Coastguard Worker
112*14675a02SAndroid Build Coastguard Worker // Trigger all waiters.
113*14675a02SAndroid Build Coastguard Worker clock.AdvanceTime(absl::Seconds(2));
114*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(output, ElementsAre(1, 3, 5, 2, 4));
115*14675a02SAndroid Build Coastguard Worker }
116*14675a02SAndroid Build Coastguard Worker
117*14675a02SAndroid Build Coastguard Worker // Verifies that waiters with current or past deadlines are triggered promptly.
TEST(SimulatedClockTest,PastAndCurrentDeadlines)118*14675a02SAndroid Build Coastguard Worker TEST(SimulatedClockTest, PastAndCurrentDeadlines) {
119*14675a02SAndroid Build Coastguard Worker std::vector<int> output;
120*14675a02SAndroid Build Coastguard Worker absl::Time t =
121*14675a02SAndroid Build Coastguard Worker absl::FromCivil(absl::CivilDay(2020, 1, 1), absl::LocalTimeZone());
122*14675a02SAndroid Build Coastguard Worker SimulatedClock clock(t);
123*14675a02SAndroid Build Coastguard Worker
124*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t, std::make_shared<TestWaiter>(1, &output));
125*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t - absl::Seconds(1),
126*14675a02SAndroid Build Coastguard Worker std::make_shared<TestWaiter>(2, &output));
127*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(output, ElementsAre(1, 2));
128*14675a02SAndroid Build Coastguard Worker }
129*14675a02SAndroid Build Coastguard Worker
130*14675a02SAndroid Build Coastguard Worker // Verifies that only expired waiters are triggered.
TEST(SimulatedClockTest,MultipleWaiters)131*14675a02SAndroid Build Coastguard Worker TEST(SimulatedClockTest, MultipleWaiters) {
132*14675a02SAndroid Build Coastguard Worker std::vector<int> output;
133*14675a02SAndroid Build Coastguard Worker absl::Time t = GetTestInitialTime();
134*14675a02SAndroid Build Coastguard Worker SimulatedClock clock(t);
135*14675a02SAndroid Build Coastguard Worker
136*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t + absl::Seconds(30),
137*14675a02SAndroid Build Coastguard Worker std::make_shared<TestWaiter>(1, &output));
138*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t + absl::Seconds(20),
139*14675a02SAndroid Build Coastguard Worker std::make_shared<TestWaiter>(2, &output));
140*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t + absl::Seconds(10),
141*14675a02SAndroid Build Coastguard Worker std::make_shared<TestWaiter>(3, &output));
142*14675a02SAndroid Build Coastguard Worker // Advance by 15 seconds
143*14675a02SAndroid Build Coastguard Worker clock.AdvanceTime(absl::Seconds(15));
144*14675a02SAndroid Build Coastguard Worker // Advance by another 5 seconds
145*14675a02SAndroid Build Coastguard Worker clock.AdvanceTime(absl::Seconds(5));
146*14675a02SAndroid Build Coastguard Worker // Only waiters 3 and 2 should be triggered.
147*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(output, ElementsAre(3, 2));
148*14675a02SAndroid Build Coastguard Worker }
149*14675a02SAndroid Build Coastguard Worker
150*14675a02SAndroid Build Coastguard Worker // Verifies that a new timer can be scheduled when anoter timer is triggered.
TEST(SimulatedClockTest,RecursiveWakeup)151*14675a02SAndroid Build Coastguard Worker TEST(SimulatedClockTest, RecursiveWakeup) {
152*14675a02SAndroid Build Coastguard Worker std::vector<int> output;
153*14675a02SAndroid Build Coastguard Worker absl::Time t = GetTestInitialTime();
154*14675a02SAndroid Build Coastguard Worker SimulatedClock clock(t);
155*14675a02SAndroid Build Coastguard Worker
156*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t + absl::Seconds(20),
157*14675a02SAndroid Build Coastguard Worker std::make_shared<TestWaiter>(1, &output));
158*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(
159*14675a02SAndroid Build Coastguard Worker t + absl::Seconds(20), std::make_shared<CallbackWaiter>([&]() {
160*14675a02SAndroid Build Coastguard Worker output.push_back(2);
161*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t + absl::Seconds(15),
162*14675a02SAndroid Build Coastguard Worker std::make_shared<TestWaiter>(3, &output));
163*14675a02SAndroid Build Coastguard Worker }));
164*14675a02SAndroid Build Coastguard Worker clock.AdvanceTime(absl::Seconds(20));
165*14675a02SAndroid Build Coastguard Worker // Both waiters are triggered because the #3 one is already expired when
166*14675a02SAndroid Build Coastguard Worker // inserted recursively by waiter #2.
167*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(output, ElementsAre(1, 2, 3));
168*14675a02SAndroid Build Coastguard Worker }
169*14675a02SAndroid Build Coastguard Worker
170*14675a02SAndroid Build Coastguard Worker // Verifies that a long taking Wakeup notification results in triggering
171*14675a02SAndroid Build Coastguard Worker // other waiters that expire later.
TEST(SimulatedClockTest,LongRunningWakeup)172*14675a02SAndroid Build Coastguard Worker TEST(SimulatedClockTest, LongRunningWakeup) {
173*14675a02SAndroid Build Coastguard Worker std::vector<int> output;
174*14675a02SAndroid Build Coastguard Worker absl::Time t = GetTestInitialTime();
175*14675a02SAndroid Build Coastguard Worker SimulatedClock clock(t);
176*14675a02SAndroid Build Coastguard Worker
177*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t + absl::Seconds(10),
178*14675a02SAndroid Build Coastguard Worker std::make_shared<TestWaiter>(1, &output));
179*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(
180*14675a02SAndroid Build Coastguard Worker t + absl::Seconds(20), std::make_shared<CallbackWaiter>([&]() {
181*14675a02SAndroid Build Coastguard Worker output.push_back(2);
182*14675a02SAndroid Build Coastguard Worker clock.AdvanceTime(absl::Seconds(10));
183*14675a02SAndroid Build Coastguard Worker }));
184*14675a02SAndroid Build Coastguard Worker clock.WakeupWithDeadline(t + absl::Seconds(30),
185*14675a02SAndroid Build Coastguard Worker std::make_shared<TestWaiter>(3, &output));
186*14675a02SAndroid Build Coastguard Worker // Advance time by 20 second, which will advance time by another 10 seconds
187*14675a02SAndroid Build Coastguard Worker // when waking up waiter #2.
188*14675a02SAndroid Build Coastguard Worker clock.AdvanceTime(absl::Seconds(20));
189*14675a02SAndroid Build Coastguard Worker EXPECT_THAT(output, ElementsAre(1, 2, 3));
190*14675a02SAndroid Build Coastguard Worker }
191*14675a02SAndroid Build Coastguard Worker
192*14675a02SAndroid Build Coastguard Worker } // namespace
193*14675a02SAndroid Build Coastguard Worker } // namespace fcp
194