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 fake_timer::fake_timerfd_advance;
30 using fake_timer::fake_timerfd_reset;
31
32 class RepeatingAlarmTest : public ::testing::Test {
33 protected:
SetUp()34 void SetUp() override {
35 thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
36 handler_ = new Handler(thread_);
37 alarm_ = new RepeatingAlarm(handler_);
38 }
39
TearDown()40 void TearDown() override {
41 delete alarm_;
42 handler_->Clear();
43 delete handler_;
44 delete thread_;
45 fake_timerfd_reset();
46 }
47
VerifyMultipleDelayedTasks(int scheduled_tasks,int task_length_ms,int interval_between_tasks_ms)48 void VerifyMultipleDelayedTasks(int scheduled_tasks, int task_length_ms, int interval_between_tasks_ms) {
49 std::promise<void> promise;
50 auto future = promise.get_future();
51 auto start_time = std::chrono::steady_clock::now();
52 int counter = 0;
53 alarm_->Schedule(
54 common::Bind(
55 &RepeatingAlarmTest::verify_delayed_tasks,
56 common::Unretained(this),
57 common::Unretained(&counter),
58 start_time,
59 scheduled_tasks,
60 common::Unretained(&promise),
61 task_length_ms,
62 interval_between_tasks_ms),
63 std::chrono::milliseconds(interval_between_tasks_ms));
64 fake_timer_advance(interval_between_tasks_ms * scheduled_tasks);
65 future.get();
66 alarm_->Cancel();
67 }
68
verify_delayed_tasks(int * counter,std::chrono::steady_clock::time_point start_time,int scheduled_tasks,std::promise<void> * promise,int task_length_ms,int interval_between_tasks_ms)69 void verify_delayed_tasks(
70 int* counter,
71 std::chrono::steady_clock::time_point start_time,
72 int scheduled_tasks,
73 std::promise<void>* promise,
74 int task_length_ms,
75 int interval_between_tasks_ms) {
76 *counter = *counter + 1;
77 if (*counter == scheduled_tasks) {
78 promise->set_value();
79 }
80 }
81
fake_timer_advance(uint64_t ms)82 void fake_timer_advance(uint64_t ms) {
83 handler_->Post(common::BindOnce(fake_timerfd_advance, ms));
84 }
85
86 RepeatingAlarm* alarm_;
87
__anon1028ff1e0202null88 common::Closure should_not_happen_ = common::Bind([] { ASSERT_TRUE(false); });
89
90 private:
91 Thread* thread_;
92 Handler* handler_;
93 };
94
TEST_F(RepeatingAlarmTest,cancel_while_not_armed)95 TEST_F(RepeatingAlarmTest, cancel_while_not_armed) {
96 alarm_->Cancel();
97 }
98
TEST_F(RepeatingAlarmTest,schedule)99 TEST_F(RepeatingAlarmTest, schedule) {
100 std::promise<void> promise;
101 auto future = promise.get_future();
102 int period_ms = 10;
103 alarm_->Schedule(
104 common::Bind(&std::promise<void>::set_value, common::Unretained(&promise)), std::chrono::milliseconds(period_ms));
105 fake_timer_advance(period_ms);
106 future.get();
107 alarm_->Cancel();
108 ASSERT_FALSE(future.valid());
109 }
110
TEST_F(RepeatingAlarmTest,cancel_alarm)111 TEST_F(RepeatingAlarmTest, cancel_alarm) {
112 alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(10));
113 alarm_->Cancel();
114 std::this_thread::sleep_for(std::chrono::milliseconds(50));
115 }
116
TEST_F(RepeatingAlarmTest,cancel_alarm_from_callback)117 TEST_F(RepeatingAlarmTest, cancel_alarm_from_callback) {
118 alarm_->Schedule(
119 common::Bind(&RepeatingAlarm::Cancel, common::Unretained(this->alarm_)), std::chrono::milliseconds(1));
120 std::this_thread::sleep_for(std::chrono::milliseconds(5));
121 }
122
TEST_F(RepeatingAlarmTest,schedule_while_alarm_armed)123 TEST_F(RepeatingAlarmTest, schedule_while_alarm_armed) {
124 alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(1));
125 std::promise<void> promise;
126 auto future = promise.get_future();
127 alarm_->Schedule(
128 common::Bind(&std::promise<void>::set_value, common::Unretained(&promise)), std::chrono::milliseconds(10));
129 fake_timer_advance(10);
130 future.get();
131 alarm_->Cancel();
132 }
133
TEST_F(RepeatingAlarmTest,delete_while_alarm_armed)134 TEST_F(RepeatingAlarmTest, delete_while_alarm_armed) {
135 alarm_->Schedule(should_not_happen_, std::chrono::milliseconds(1));
136 delete alarm_;
137 alarm_ = nullptr;
138 std::this_thread::sleep_for(std::chrono::milliseconds(1));
139 }
140
TEST_F(RepeatingAlarmTest,verify_small)141 TEST_F(RepeatingAlarmTest, verify_small) {
142 VerifyMultipleDelayedTasks(100, 1, 10);
143 }
144
TEST_F(RepeatingAlarmTest,verify_large)145 TEST_F(RepeatingAlarmTest, verify_large) {
146 VerifyMultipleDelayedTasks(100, 3, 10);
147 }
148
149 } // namespace
150 } // namespace os
151 } // namespace bluetooth
152