1 // Copyright 2021 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://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,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <memory>
16 #include <vector>
17
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
20 #include "absl/synchronization/mutex.h"
21 #include "absl/time/time.h"
22 #include "fcp/base/clock.h"
23
24 namespace fcp {
25 namespace {
26
27 using ::testing::ElementsAre;
28 using ::testing::Test;
29
30 class RealtimeClockTest : public Test {
31 public:
RealtimeClockTest()32 RealtimeClockTest() : start_(Clock::RealClock()->Now()) {}
33
OnWakeUp(int waiter_id)34 void OnWakeUp(int waiter_id) {
35 absl::MutexLock lock(&mu_);
36 waiter_ids_.push_back(waiter_id);
37 waiter_intervals_.push_back(Clock::RealClock()->Now() - start_);
38 }
39
40 protected:
41 absl::Time start_;
42 absl::Mutex mu_;
43 std::vector<int> waiter_ids_ ABSL_GUARDED_BY(&mu_);
44 std::vector<absl::Duration> waiter_intervals_ ABSL_GUARDED_BY(&mu_);
45 };
46
47 // Simple callback waiter that records current waiter ID with the test.
48 class TestWaiter : public Clock::Waiter {
49 public:
TestWaiter(int id,RealtimeClockTest * test)50 explicit TestWaiter(int id, RealtimeClockTest* test) : id_(id), test_(test) {}
51
WakeUp()52 void WakeUp() override { test_->OnWakeUp(id_); }
53
54 private:
55 int id_;
56 RealtimeClockTest* test_;
57 };
58
TEST_F(RealtimeClockTest,MultipleTimerWakeUp)59 TEST_F(RealtimeClockTest, MultipleTimerWakeUp) {
60 // Add 4 timers at various deadlines, the last one in the past.
61 Clock::RealClock()->WakeupWithDeadline(start_ + absl::Milliseconds(200),
62 std::make_shared<TestWaiter>(1, this));
63 Clock::RealClock()->WakeupWithDeadline(start_ + absl::Milliseconds(100),
64 std::make_shared<TestWaiter>(2, this));
65 Clock::RealClock()->WakeupWithDeadline(start_ + absl::Milliseconds(101),
66 std::make_shared<TestWaiter>(3, this));
67 Clock::RealClock()->WakeupWithDeadline(start_ - absl::Milliseconds(1),
68 std::make_shared<TestWaiter>(4, this));
69
70 // End the test when all 3 timers have been triggered.
71 auto test_done = [this]() {
72 mu_.AssertHeld();
73 return waiter_ids_.size() == 4;
74 };
75
76 absl::MutexLock lock(&mu_);
77 mu_.Await(absl::Condition(&test_done));
78
79 // Verify the results
80 EXPECT_THAT(waiter_ids_, ElementsAre(4, 2, 3, 1));
81 EXPECT_GE(waiter_intervals_[0], absl::ZeroDuration());
82 EXPECT_GE(waiter_intervals_[1], absl::Milliseconds(100));
83 EXPECT_GE(waiter_intervals_[2], absl::Milliseconds(101));
84 EXPECT_GE(waiter_intervals_[3], absl::Milliseconds(200));
85 }
86
87 } // namespace
88 } // namespace fcp
89