xref: /aosp_15_r20/external/federated-compute/fcp/base/simulated_clock_test.cc (revision 14675a029014e728ec732f129a32e299b2da0601)
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