• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 <base/bind.h>
18 #include <base/bind_helpers.h>
19 #include <base/logging.h>
20 #include <gtest/gtest.h>
21 #include <future>
22 
23 #include "message_loop_thread.h"
24 #include "once_timer.h"
25 
26 using bluetooth::common::MessageLoopThread;
27 using bluetooth::common::OnceTimer;
28 
29 // Allowed error between the expected and actual delay for DoInThreadDelayed().
30 constexpr uint32_t delay_error_ms = 3;
31 
32 /**
33  * Unit tests to verify Task Scheduler.
34  */
35 class OnceTimerTest : public ::testing::Test {
36  public:
ShouldNotHappen()37   void ShouldNotHappen() { FAIL() << "Should not happen"; }
38 
IncreaseTaskCounter(int scheduled_tasks,std::promise<void> * promise)39   void IncreaseTaskCounter(int scheduled_tasks, std::promise<void>* promise) {
40     counter_++;
41     if (counter_ == scheduled_tasks) {
42       promise->set_value();
43     }
44   }
45 
GetName(std::string * name,std::promise<void> * promise)46   void GetName(std::string* name, std::promise<void>* promise) {
47     char my_name[256];
48     pthread_getname_np(pthread_self(), my_name, sizeof(my_name));
49     name->append(my_name);
50     promise->set_value();
51   }
52 
SleepAndIncreaseCounter(std::promise<void> * promise,int sleep_ms)53   void SleepAndIncreaseCounter(std::promise<void>* promise, int sleep_ms) {
54     promise->set_value();
55     std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
56     counter_++;
57   }
58 
CancelTimerAndWait()59   void CancelTimerAndWait() { timer_->CancelAndWait(); }
60 
61  protected:
SetUp()62   void SetUp() override {
63     ::testing::Test::SetUp();
64     counter_ = 0;
65     timer_ = new OnceTimer();
66     promise_ = new std::promise<void>();
67   }
68 
TearDown()69   void TearDown() override {
70     if (promise_ != nullptr) {
71       delete promise_;
72       promise_ = nullptr;
73     }
74     if (timer_ != nullptr) {
75       delete timer_;
76       timer_ = nullptr;
77     }
78   }
79 
80   int counter_;
81   OnceTimer* timer_;
82   std::promise<void>* promise_;
83 };
84 
TEST_F(OnceTimerTest,initial_is_not_scheduled)85 TEST_F(OnceTimerTest, initial_is_not_scheduled) {
86   ASSERT_FALSE(timer_->IsScheduled());
87 }
88 
TEST_F(OnceTimerTest,schedule_task)89 TEST_F(OnceTimerTest, schedule_task) {
90   std::string name = "test_thread";
91   MessageLoopThread message_loop_thread(name);
92   message_loop_thread.StartUp();
93   auto future = promise_->get_future();
94   std::string my_name;
95   uint32_t delay_ms = 5;
96 
97   timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
98                    base::BindOnce(&OnceTimerTest::GetName,
99                                   base::Unretained(this), &my_name, promise_),
100                    base::TimeDelta::FromMilliseconds(delay_ms));
101   EXPECT_TRUE(timer_->IsScheduled());
102   future.get();
103   ASSERT_EQ(name, my_name);
104   std::this_thread::sleep_for(std::chrono::milliseconds(delay_error_ms));
105   EXPECT_FALSE(timer_->IsScheduled());
106 }
107 
TEST_F(OnceTimerTest,cancel_without_scheduling)108 TEST_F(OnceTimerTest, cancel_without_scheduling) {
109   std::string name = "test_thread";
110   MessageLoopThread message_loop_thread(name);
111   message_loop_thread.StartUp();
112 
113   EXPECT_FALSE(timer_->IsScheduled());
114   timer_->CancelAndWait();
115   EXPECT_FALSE(timer_->IsScheduled());
116 }
117 
TEST_F(OnceTimerTest,cancel_in_callback_no_deadlock)118 TEST_F(OnceTimerTest, cancel_in_callback_no_deadlock) {
119   std::string name = "test_thread";
120   MessageLoopThread message_loop_thread(name);
121   message_loop_thread.StartUp();
122   uint32_t delay_ms = 5;
123 
124   timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
125                    base::BindOnce(&OnceTimerTest::CancelTimerAndWait,
126                                   base::Unretained(this)),
127                    base::TimeDelta::FromMilliseconds(delay_ms));
128 }
129 
TEST_F(OnceTimerTest,cancel_single_task)130 TEST_F(OnceTimerTest, cancel_single_task) {
131   std::string name = "test_thread";
132   MessageLoopThread message_loop_thread(name);
133   message_loop_thread.StartUp();
134   uint32_t delay_ms = 100000000;
135   timer_->Schedule(
136       message_loop_thread.GetWeakPtr(), FROM_HERE,
137       base::BindOnce(&OnceTimerTest::ShouldNotHappen, base::Unretained(this)),
138       base::TimeDelta::FromMilliseconds(delay_ms));
139   std::this_thread::sleep_for(std::chrono::milliseconds(delay_error_ms));
140   timer_->CancelAndWait();
141 }
142 
TEST_F(OnceTimerTest,message_loop_thread_down_cancel_task)143 TEST_F(OnceTimerTest, message_loop_thread_down_cancel_task) {
144   std::string name = "test_thread";
145   {
146     MessageLoopThread message_loop_thread(name);
147     message_loop_thread.StartUp();
148     uint32_t delay_ms = 100000000;
149     timer_->Schedule(
150         message_loop_thread.GetWeakPtr(), FROM_HERE,
151         base::BindOnce(&OnceTimerTest::ShouldNotHappen, base::Unretained(this)),
152         base::TimeDelta::FromMilliseconds(delay_ms));
153     std::this_thread::sleep_for(std::chrono::milliseconds(delay_error_ms));
154   }
155 }
156 
157 // Verify that if a task is being executed, then cancelling it is no-op
TEST_F(OnceTimerTest,cancel_current_task_no_effect)158 TEST_F(OnceTimerTest, cancel_current_task_no_effect) {
159   std::string name = "test_thread";
160   MessageLoopThread message_loop_thread(name);
161   message_loop_thread.StartUp();
162   auto future = promise_->get_future();
163   uint32_t delay_ms = 5;
164 
165   timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
166                    base::BindOnce(&OnceTimerTest::SleepAndIncreaseCounter,
167                                   base::Unretained(this), promise_, delay_ms),
168                    base::TimeDelta::FromMilliseconds(delay_ms));
169   EXPECT_TRUE(timer_->IsScheduled());
170   future.get();
171   timer_->CancelAndWait();
172   ASSERT_EQ(counter_, 1);
173   EXPECT_FALSE(timer_->IsScheduled());
174 }
175 
TEST_F(OnceTimerTest,reschedule_task_dont_invoke_new_task_early)176 TEST_F(OnceTimerTest, reschedule_task_dont_invoke_new_task_early) {
177   std::string name = "test_thread";
178   MessageLoopThread message_loop_thread(name);
179   message_loop_thread.StartUp();
180   uint32_t delay_ms = 5;
181   timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
182                    base::DoNothing(),
183                    base::TimeDelta::FromMilliseconds(delay_ms));
184   std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms - 2));
185   timer_->Schedule(
186       message_loop_thread.GetWeakPtr(), FROM_HERE,
187       base::BindOnce(&OnceTimerTest::ShouldNotHappen, base::Unretained(this)),
188       base::TimeDelta::FromMilliseconds(delay_ms + 1000));
189   std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
190 }
191 
TEST_F(OnceTimerTest,reschedule_task_when_firing_dont_invoke_new_task_early)192 TEST_F(OnceTimerTest, reschedule_task_when_firing_dont_invoke_new_task_early) {
193   std::string name = "test_thread";
194   MessageLoopThread message_loop_thread(name);
195   message_loop_thread.StartUp();
196   uint32_t delay_ms = 5;
197   timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
198                    base::DoNothing(),
199                    base::TimeDelta::FromMilliseconds(delay_ms));
200   std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
201   timer_->Schedule(
202       message_loop_thread.GetWeakPtr(), FROM_HERE,
203       base::BindOnce(&OnceTimerTest::ShouldNotHappen, base::Unretained(this)),
204       base::TimeDelta::FromMilliseconds(delay_ms + 1000));
205   std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
206 }
207 
TEST_F(OnceTimerTest,reschedule_task_when_firing_must_schedule_new_task)208 TEST_F(OnceTimerTest, reschedule_task_when_firing_must_schedule_new_task) {
209   std::string name = "test_thread";
210   MessageLoopThread message_loop_thread(name);
211   message_loop_thread.StartUp();
212   uint32_t delay_ms = 5;
213   std::string my_name;
214   auto future = promise_->get_future();
215   timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
216                    base::DoNothing(),
217                    base::TimeDelta::FromMilliseconds(delay_ms));
218   std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
219   timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
220                    base::BindOnce(&OnceTimerTest::GetName,
221                                   base::Unretained(this), &my_name, promise_),
222                    base::TimeDelta::FromMilliseconds(delay_ms));
223   future.get();
224   ASSERT_EQ(name, my_name);
225 }
226