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 "gtest/gtest.h"
22
23 namespace bluetooth {
24 namespace os {
25 namespace {
26
27 constexpr int error_ms = 20;
28
29 class RepeatingAlarmTest : public ::testing::Test {
30 protected:
SetUp()31 void SetUp() override {
32 thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
33 alarm_ = new RepeatingAlarm(thread_);
34 }
35
TearDown()36 void TearDown() override {
37 delete alarm_;
38 delete thread_;
39 }
40
VerifyMultipleDelayedTasks(int scheduled_tasks,int task_length_ms,int interval_between_tasks_ms)41 void VerifyMultipleDelayedTasks(int scheduled_tasks, int task_length_ms, int interval_between_tasks_ms) {
42 std::promise<void> promise;
43 auto future = promise.get_future();
44 auto start_time = std::chrono::steady_clock::now();
45 int counter = 0;
46 alarm_->Schedule(
47 [&counter, &promise, start_time, scheduled_tasks, task_length_ms, interval_between_tasks_ms]() {
48 counter++;
49 auto time_now = std::chrono::steady_clock::now();
50 auto time_delta = time_now - start_time;
51 if (counter == scheduled_tasks) {
52 promise.set_value();
53 }
54 ASSERT_NEAR(time_delta.count(), interval_between_tasks_ms * 1000000 * counter, error_ms * 1000000);
55 std::this_thread::sleep_for(std::chrono::milliseconds(task_length_ms));
56 },
57 std::chrono::milliseconds(interval_between_tasks_ms));
58 future.get();
59 alarm_->Cancel();
60 }
61
62 RepeatingAlarm* alarm_;
63
64 private:
65 Thread* thread_;
66 };
67
TEST_F(RepeatingAlarmTest,cancel_while_not_armed)68 TEST_F(RepeatingAlarmTest, cancel_while_not_armed) {
69 alarm_->Cancel();
70 }
71
TEST_F(RepeatingAlarmTest,schedule)72 TEST_F(RepeatingAlarmTest, schedule) {
73 std::promise<void> promise;
74 auto future = promise.get_future();
75 auto before = std::chrono::steady_clock::now();
76 int period_ms = 10;
77 alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(period_ms));
78 future.get();
79 alarm_->Cancel();
80 auto after = std::chrono::steady_clock::now();
81 auto duration = after - before;
82 ASSERT_NEAR(duration.count(), period_ms * 1000000, error_ms * 1000000);
83 }
84
TEST_F(RepeatingAlarmTest,cancel_alarm)85 TEST_F(RepeatingAlarmTest, cancel_alarm) {
86 alarm_->Schedule([]() { ASSERT_TRUE(false); }, std::chrono::milliseconds(1));
87 alarm_->Cancel();
88 std::this_thread::sleep_for(std::chrono::milliseconds(5));
89 }
90
TEST_F(RepeatingAlarmTest,cancel_alarm_from_callback)91 TEST_F(RepeatingAlarmTest, cancel_alarm_from_callback) {
92 alarm_->Schedule([this]() { this->alarm_->Cancel(); }, std::chrono::milliseconds(1));
93 std::this_thread::sleep_for(std::chrono::milliseconds(5));
94 }
95
TEST_F(RepeatingAlarmTest,schedule_while_alarm_armed)96 TEST_F(RepeatingAlarmTest, schedule_while_alarm_armed) {
97 alarm_->Schedule([]() { ASSERT_TRUE(false); }, std::chrono::milliseconds(1));
98 std::promise<void> promise;
99 auto future = promise.get_future();
100 alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(10));
101 future.get();
102 alarm_->Cancel();
103 }
104
TEST_F(RepeatingAlarmTest,delete_while_alarm_armed)105 TEST_F(RepeatingAlarmTest, delete_while_alarm_armed) {
106 alarm_->Schedule([]() { ASSERT_TRUE(false); }, std::chrono::milliseconds(1));
107 delete alarm_;
108 alarm_ = nullptr;
109 std::this_thread::sleep_for(std::chrono::milliseconds(1));
110 }
111
TEST_F(RepeatingAlarmTest,verify_small)112 TEST_F(RepeatingAlarmTest, verify_small) {
113 VerifyMultipleDelayedTasks(100, 1, 10);
114 }
115
TEST_F(RepeatingAlarmTest,verify_large)116 TEST_F(RepeatingAlarmTest, verify_large) {
117 VerifyMultipleDelayedTasks(100, 3, 10);
118 }
119
120 } // namespace
121 } // namespace os
122 } // namespace bluetooth
123