• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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