1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "os/repeating_alarm.h"
18 
19 #include <future>
20 
21 #include "common/bind.h"
22 #include "gtest/gtest.h"
23 #include "os/fake_timer/fake_timerfd.h"
24 
25 namespace bluetooth {
26 namespace os {
27 namespace {
28 
29 using common::BindOnce;
30 using fake_timer::fake_timerfd_advance;
31 using fake_timer::fake_timerfd_reset;
32 
33 class RepeatingAlarmTest : public ::testing::Test {
34  protected:
SetUp()35   void SetUp() override {
36     thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
37     handler_ = new Handler(thread_);
38     alarm_ = new RepeatingAlarm(handler_);
39   }
40 
TearDown()41   void TearDown() override {
42     delete alarm_;
43     handler_->Clear();
44     delete handler_;
45     delete thread_;
46     fake_timerfd_reset();
47   }
48 
VerifyMultipleDelayedTasks(int scheduled_tasks,int task_length_ms,int interval_between_tasks_ms)49   void VerifyMultipleDelayedTasks(int scheduled_tasks, int task_length_ms, int interval_between_tasks_ms) {
50     std::promise<void> promise;
51     auto future = promise.get_future();
52     auto start_time = std::chrono::steady_clock::now();
53     int counter = 0;
54     alarm_->Schedule(
55         common::Bind(
56             &RepeatingAlarmTest::verify_delayed_tasks,
57             common::Unretained(this),
58             common::Unretained(&counter),
59             start_time,
60             scheduled_tasks,
61             common::Unretained(&promise),
62             task_length_ms,
63             interval_between_tasks_ms),
64         std::chrono::milliseconds(interval_between_tasks_ms));
65     fake_timer_advance(interval_between_tasks_ms * scheduled_tasks);
66     future.get();
67     alarm_->Cancel();
68   }
69 
verify_delayed_tasks(int * counter,std::chrono::steady_clock::time_point,int scheduled_tasks,std::promise<void> * promise,int,int)70   void verify_delayed_tasks(
71       int* counter,
72       std::chrono::steady_clock::time_point /* start_time */,
73       int scheduled_tasks,
74       std::promise<void>* promise,
75       int /* task_length_ms */,
76       int /* interval_between_tasks_ms */) {
77     *counter = *counter + 1;
78     if (*counter == scheduled_tasks) {
79       promise->set_value();
80     }
81   }
82 
fake_timer_advance(uint64_t ms)83   void fake_timer_advance(uint64_t ms) {
84     handler_->Post(common::BindOnce(fake_timerfd_advance, ms));
85   }
86 
87   RepeatingAlarm* alarm_;
88 
__anon482b86720202() 89   common::Closure should_not_happen_ = common::Bind([]() { FAIL(); });
90 
91  private:
92   Thread* thread_;
93   Handler* handler_;
94 };
95 
TEST_F(RepeatingAlarmTest,cancel_while_not_armed)96 TEST_F(RepeatingAlarmTest, cancel_while_not_armed) {
97   alarm_->Cancel();
98 }
99 
TEST_F(RepeatingAlarmTest,schedule)100 TEST_F(RepeatingAlarmTest, schedule) {
101   std::promise<void> promise;
102   auto future = promise.get_future();
103   int period_ms = 10;
104   alarm_->Schedule(
105       common::Bind(&std::promise<void>::set_value, common::Unretained(&promise)), std::chrono::milliseconds(period_ms));
106   fake_timer_advance(period_ms);
107   future.get();
108   alarm_->Cancel();
109   ASSERT_FALSE(future.valid());
110 }
111 
TEST_F(RepeatingAlarmTest,cancel_alarm)112 TEST_F(RepeatingAlarmTest, cancel_alarm) {
113   alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(10));
114   alarm_->Cancel();
115   fake_timer_advance(10);
116 }
117 
TEST_F(RepeatingAlarmTest,cancel_alarm_from_callback)118 TEST_F(RepeatingAlarmTest, cancel_alarm_from_callback) {
119   std::promise<void> promise;
120   auto future = promise.get_future();
121   alarm_->Schedule(
122       common::Bind(
123           [](RepeatingAlarm* alarm, std::promise<void>* promise) {
124             alarm->Cancel();
125             promise->set_value();
126           },
127           common::Unretained(this->alarm_),
128           common::Unretained(&promise)),
129       std::chrono::milliseconds(1));
130   fake_timer_advance(1);
131   ASSERT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(1)));
132 }
133 
TEST_F(RepeatingAlarmTest,schedule_while_alarm_armed)134 TEST_F(RepeatingAlarmTest, schedule_while_alarm_armed) {
135   alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(1));
136   std::promise<void> promise;
137   auto future = promise.get_future();
138   alarm_->Schedule(
139       common::Bind(&std::promise<void>::set_value, common::Unretained(&promise)), std::chrono::milliseconds(10));
140   fake_timer_advance(10);
141   ASSERT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(1)));
142   alarm_->Cancel();
143 }
144 
TEST_F(RepeatingAlarmTest,delete_while_alarm_armed)145 TEST_F(RepeatingAlarmTest, delete_while_alarm_armed) {
146   alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(1));
147   delete alarm_;
148   alarm_ = nullptr;
149   fake_timer_advance(10);
150 }
151 
TEST_F(RepeatingAlarmTest,verify_small)152 TEST_F(RepeatingAlarmTest, verify_small) {
153   VerifyMultipleDelayedTasks(100, 1, 10);
154 }
155 
TEST_F(RepeatingAlarmTest,verify_large)156 TEST_F(RepeatingAlarmTest, verify_large) {
157   VerifyMultipleDelayedTasks(100, 3, 10);
158 }
159 
160 }  // namespace
161 }  // namespace os
162 }  // namespace bluetooth
163