1 /*
2 * Copyright 2024 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 <cctype>
20 #include <chrono>
21 #include <future>
22 #include <memory>
23
24 #include "common/bind.h"
25 #include "gtest/gtest.h"
26
27
28 namespace bluetooth::common {
29
30 struct IsSpace {
operator ()bluetooth::common::IsSpace31 bool operator()(std::string::value_type v) {
32 return isspace(static_cast<int>(v));
33 }
34 };
35
StringTrim(std::string str)36 std::string StringTrim(std::string str) {
37 str.erase(str.begin(), std::find_if_not(str.begin(), str.end(), IsSpace{}));
38 str.erase(std::find_if_not(str.rbegin(), str.rend(), IsSpace{}).base(), str.end());
39 return str;
40 }
41 } // namespace bluetooth::common
42
43 namespace bluetooth::os {
44
45 using common::BindOnce;
46 using std::chrono::milliseconds;
47 using std::chrono::seconds;
48
49 static constexpr seconds kForever = seconds(1);
50 static constexpr milliseconds kShortWait = milliseconds(10);
51
52 class AlarmOnTimerFdTest : public ::testing::Test {
53 protected:
SetUp()54 void SetUp() override {
55 thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
56 handler_ = new Handler(thread_);
57 alarm_ = std::make_shared<Alarm>(handler_);
58 }
59
TearDown()60 void TearDown() override {
61 alarm_.reset();
62 handler_->Clear();
63 delete handler_;
64 delete thread_;
65 }
66
get_new_alarm()67 std::shared_ptr<Alarm> get_new_alarm() {
68 return std::make_shared<Alarm>(handler_);
69 }
70
71 std::shared_ptr<Alarm> alarm_;
72
73 private:
74 Handler* handler_;
75 Thread* thread_;
76 };
77
TEST_F(AlarmOnTimerFdTest,cancel_while_not_armed)78 TEST_F(AlarmOnTimerFdTest, cancel_while_not_armed) {
79 alarm_->Cancel();
80 }
81
TEST_F(AlarmOnTimerFdTest,schedule)82 TEST_F(AlarmOnTimerFdTest, schedule) {
83 auto promise = std::make_unique<std::promise<void>>();
84 auto future = promise->get_future();
85 alarm_->Schedule(BindOnce(&std::promise<void>::set_value, std::move(promise)), kShortWait);
86 ASSERT_EQ(std::future_status::ready, future.wait_for(kForever));
87 }
88
TEST_F(AlarmOnTimerFdTest,cancel_alarm)89 TEST_F(AlarmOnTimerFdTest, cancel_alarm) {
90 auto promise = std::make_unique<std::promise<void>>();
91 auto future = promise->get_future();
92 alarm_->Schedule(BindOnce([]() { FAIL(); }), kForever);
93 alarm_->Cancel();
94 ASSERT_NE(std::future_status::ready, future.wait_for(kShortWait));
95 }
96
TEST_F(AlarmOnTimerFdTest,cancel_alarm_from_callback)97 TEST_F(AlarmOnTimerFdTest, cancel_alarm_from_callback) {
98 auto promise = std::promise<void>();
99 auto future = promise.get_future();
100 alarm_->Schedule(
101 BindOnce(
102 [](std::shared_ptr<Alarm> alarm, std::promise<void> promise) {
103 alarm->Cancel();
104 alarm.reset(); // Allow alarm to be freed by Teardown
105 promise.set_value();
106 },
107 alarm_,
108 std::move(promise)),
109 kShortWait);
110 ASSERT_EQ(std::future_status::ready, future.wait_for(kForever));
111 }
112
TEST_F(AlarmOnTimerFdTest,schedule_while_alarm_armed)113 TEST_F(AlarmOnTimerFdTest, schedule_while_alarm_armed) {
114 auto promise = std::make_unique<std::promise<void>>();
115 auto future = promise->get_future();
116 alarm_->Schedule(BindOnce([]() { FAIL(); }), kForever);
117 alarm_->Schedule(BindOnce(&std::promise<void>::set_value, std::move(promise)), kShortWait);
118 ASSERT_EQ(std::future_status::ready, future.wait_for(kForever));
119 }
120
TEST_F(AlarmOnTimerFdTest,delete_while_alarm_armed)121 TEST_F(AlarmOnTimerFdTest, delete_while_alarm_armed) {
122 auto promise = std::make_unique<std::promise<void>>();
123 auto future = promise->get_future();
124 alarm_->Schedule(BindOnce([]() { FAIL(); }), kForever);
125 alarm_.reset();
126 ASSERT_NE(std::future_status::ready, future.wait_for(kShortWait));
127 }
128
129 class TwoAlarmOnTimerFdTest : public AlarmOnTimerFdTest {
130 protected:
SetUp()131 void SetUp() override {
132 AlarmOnTimerFdTest::SetUp();
133 alarm2 = get_new_alarm();
134 }
135
TearDown()136 void TearDown() override {
137 alarm2.reset();
138 AlarmOnTimerFdTest::TearDown();
139 }
140
141 std::shared_ptr<Alarm> alarm2;
142 };
143
TEST_F(TwoAlarmOnTimerFdTest,schedule_from_alarm)144 TEST_F(TwoAlarmOnTimerFdTest, schedule_from_alarm) {
145 auto promise = std::make_unique<std::promise<void>>();
146 auto future = promise->get_future();
147 alarm_->Schedule(
148 BindOnce(
149 [](std::shared_ptr<Alarm> alarm2, std::unique_ptr<std::promise<void>> promise) {
150 alarm2->Schedule(
151 BindOnce(&std::promise<void>::set_value, std::move(promise)), kShortWait);
152 },
153 alarm2,
154 std::move(promise)),
155 kShortWait);
156 EXPECT_EQ(std::future_status::ready, future.wait_for(kForever));
157 }
158
159 } // namespace bluetooth::os
160