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/alarm.h"
18
19 #include <future>
20 #include <memory>
21
22 #include "common/bind.h"
23 #include "gtest/gtest.h"
24 #include "os/fake_timer/fake_timerfd.h"
25
26 namespace bluetooth {
27 namespace os {
28 namespace {
29
30 using common::BindOnce;
31 using fake_timer::fake_timerfd_advance;
32 using fake_timer::fake_timerfd_reset;
33
34 class AlarmTest : public ::testing::Test {
35 protected:
SetUp()36 void SetUp() override {
37 thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
38 handler_ = new Handler(thread_);
39 alarm_ = std::make_shared<Alarm>(handler_);
40 }
41
TearDown()42 void TearDown() override {
43 alarm_.reset();
44 handler_->Clear();
45 delete handler_;
46 delete thread_;
47 fake_timerfd_reset();
48 }
49
fake_timer_advance(uint64_t ms)50 void fake_timer_advance(uint64_t ms) {
51 handler_->Post(common::BindOnce(fake_timerfd_advance, ms));
52 }
53
get_new_alarm()54 std::shared_ptr<Alarm> get_new_alarm() {
55 return std::make_shared<Alarm>(handler_);
56 }
57
58 std::shared_ptr<Alarm> alarm_;
59
60 private:
61 Handler* handler_;
62 Thread* thread_;
63 };
64
TEST_F(AlarmTest,cancel_while_not_armed)65 TEST_F(AlarmTest, cancel_while_not_armed) {
66 alarm_->Cancel();
67 }
68
TEST_F(AlarmTest,schedule)69 TEST_F(AlarmTest, schedule) {
70 std::promise<void> promise;
71 auto future = promise.get_future();
72 int delay_ms = 10;
73 alarm_->Schedule(
74 BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)), std::chrono::milliseconds(delay_ms));
75 fake_timer_advance(10);
76 future.get();
77 ASSERT_FALSE(future.valid());
78 }
79
TEST_F(AlarmTest,cancel_alarm)80 TEST_F(AlarmTest, cancel_alarm) {
81 alarm_->Schedule(BindOnce([]() { ASSERT_TRUE(false) << "Should not happen"; }), std::chrono::milliseconds(3));
82 alarm_->Cancel();
83 std::this_thread::sleep_for(std::chrono::milliseconds(5));
84 }
85
TEST_F(AlarmTest,cancel_alarm_from_callback)86 TEST_F(AlarmTest, cancel_alarm_from_callback) {
87 std::promise<void> promise;
88 auto future = promise.get_future();
89 alarm_->Schedule(
90 BindOnce(
91 [](std::shared_ptr<Alarm> alarm, std::promise<void> promise) {
92 alarm->Cancel();
93 alarm.reset(); // Allow alarm to be freed by Teardown
94 promise.set_value();
95 },
96 alarm_,
97 std::move(promise)),
98 std::chrono::milliseconds(1));
99 fake_timer_advance(10);
100 ASSERT_EQ(std::future_status::ready, future.wait_for(std::chrono::seconds(1)));
101 ASSERT_EQ(alarm_.use_count(), 1);
102 }
103
TEST_F(AlarmTest,schedule_while_alarm_armed)104 TEST_F(AlarmTest, schedule_while_alarm_armed) {
105 alarm_->Schedule(BindOnce([]() { ASSERT_TRUE(false) << "Should not happen"; }), std::chrono::milliseconds(1));
106 std::promise<void> promise;
107 auto future = promise.get_future();
108 alarm_->Schedule(
109 BindOnce(&std::promise<void>::set_value, common::Unretained(&promise)), std::chrono::milliseconds(10));
110 fake_timer_advance(10);
111 future.get();
112 }
113
TEST_F(AlarmTest,delete_while_alarm_armed)114 TEST_F(AlarmTest, delete_while_alarm_armed) {
115 alarm_->Schedule(BindOnce([]() { ASSERT_TRUE(false) << "Should not happen"; }), std::chrono::milliseconds(1));
116 alarm_.reset();
117 std::this_thread::sleep_for(std::chrono::milliseconds(10));
118 }
119
120 class TwoAlarmTest : public AlarmTest {
121 protected:
SetUp()122 void SetUp() override {
123 AlarmTest::SetUp();
124 alarm2 = get_new_alarm();
125 }
126
TearDown()127 void TearDown() override {
128 alarm2.reset();
129 AlarmTest::TearDown();
130 }
131
132 std::shared_ptr<Alarm> alarm2;
133 };
134
TEST_F(TwoAlarmTest,schedule_from_alarm_long)135 TEST_F(TwoAlarmTest, schedule_from_alarm_long) {
136 auto promise = std::make_unique<std::promise<void>>();
137 auto future = promise->get_future();
138 auto promise2 = std::make_unique<std::promise<void>>();
139 auto future2 = promise2->get_future();
140 alarm_->Schedule(
141 BindOnce(
142 [](std::shared_ptr<Alarm> alarm2,
143 std::unique_ptr<std::promise<void>> promise,
144 std::unique_ptr<std::promise<void>> promise2) {
145 promise->set_value();
146 alarm2->Schedule(
147 BindOnce(&std::promise<void>::set_value, std::move(promise2)),
148 std::chrono::milliseconds(10));
149 },
150 alarm2,
151 std::move(promise),
152 std::move(promise2)),
153 std::chrono::milliseconds(1));
154 fake_timer_advance(10);
155 EXPECT_EQ(std::future_status::ready, future.wait_for(std::chrono::milliseconds(20)));
156 fake_timer_advance(10);
157 EXPECT_EQ(std::future_status::ready, future2.wait_for(std::chrono::milliseconds(20)));
158 }
159
160 } // namespace
161 } // namespace os
162 } // namespace bluetooth
163