1 #include <gtest/gtest.h>
2 #include <hardware/bluetooth.h>
3 #include <unistd.h>
4
5 extern "C" {
6 #include "alarm.h"
7 #include "osi.h"
8 #include "semaphore.h"
9 }
10
11 extern int64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS;
12
13 static semaphore_t *semaphore;
14 static int cb_counter;
15 static int lock_count;
16 static timer_t timer;
17 static alarm_cb saved_callback;
18 static void *saved_data;
19
20 static const uint64_t EPSILON_MS = 5;
21
msleep(uint64_t ms)22 static void msleep(uint64_t ms) {
23 usleep(ms * 1000);
24 }
25
timer_callback(void *)26 static void timer_callback(void *) {
27 saved_callback(saved_data);
28 }
29
30 class AlarmTest : public ::testing::Test {
31 protected:
SetUp()32 virtual void SetUp() {
33 TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 100;
34 cb_counter = 0;
35 lock_count = 0;
36
37 semaphore = semaphore_new(0);
38
39 struct sigevent sigevent;
40 memset(&sigevent, 0, sizeof(sigevent));
41 sigevent.sigev_notify = SIGEV_THREAD;
42 sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback;
43 sigevent.sigev_value.sival_ptr = NULL;
44 timer_create(CLOCK_BOOTTIME, &sigevent, &timer);
45 }
46
TearDown()47 virtual void TearDown() {
48 timer_delete(timer);
49 }
50 };
51
cb(UNUSED_ATTR void * data)52 static void cb(UNUSED_ATTR void *data) {
53 ++cb_counter;
54 semaphore_post(semaphore);
55 }
56
set_wake_alarm(uint64_t delay_millis,bool,alarm_cb cb,void * data)57 static bool set_wake_alarm(uint64_t delay_millis, bool, alarm_cb cb, void *data) {
58 saved_callback = cb;
59 saved_data = data;
60
61 struct itimerspec wakeup_time;
62 memset(&wakeup_time, 0, sizeof(wakeup_time));
63 wakeup_time.it_value.tv_sec = (delay_millis / 1000);
64 wakeup_time.it_value.tv_nsec = (delay_millis % 1000) * 1000000LL;
65 timer_settime(timer, 0, &wakeup_time, NULL);
66 return true;
67 }
68
acquire_wake_lock(const char *)69 static int acquire_wake_lock(const char *) {
70 if (!lock_count)
71 lock_count = 1;
72 return BT_STATUS_SUCCESS;
73 }
74
release_wake_lock(const char *)75 static int release_wake_lock(const char *) {
76 if (lock_count)
77 lock_count = 0;
78 return BT_STATUS_SUCCESS;
79 }
80
81 static bt_os_callouts_t stub = {
82 sizeof(bt_os_callouts_t),
83 set_wake_alarm,
84 acquire_wake_lock,
85 release_wake_lock,
86 };
87
88 bt_os_callouts_t *bt_os_callouts = &stub;
89
TEST_F(AlarmTest,test_new_simple)90 TEST_F(AlarmTest, test_new_simple) {
91 alarm_t *alarm = alarm_new();
92 ASSERT_TRUE(alarm != NULL);
93 }
94
TEST_F(AlarmTest,test_free_simple)95 TEST_F(AlarmTest, test_free_simple) {
96 alarm_t *alarm = alarm_new();
97 alarm_free(alarm);
98 }
99
TEST_F(AlarmTest,test_free_null)100 TEST_F(AlarmTest, test_free_null) {
101 alarm_free(NULL);
102 }
103
TEST_F(AlarmTest,test_simple_cancel)104 TEST_F(AlarmTest, test_simple_cancel) {
105 alarm_t *alarm = alarm_new();
106 alarm_cancel(alarm);
107 alarm_free(alarm);
108 }
109
TEST_F(AlarmTest,test_cancel)110 TEST_F(AlarmTest, test_cancel) {
111 alarm_t *alarm = alarm_new();
112 alarm_set(alarm, 10, cb, NULL);
113 alarm_cancel(alarm);
114
115 msleep(10 + EPSILON_MS);
116
117 EXPECT_EQ(cb_counter, 0);
118 EXPECT_EQ(lock_count, 0);
119 alarm_free(alarm);
120 }
121
TEST_F(AlarmTest,test_cancel_idempotent)122 TEST_F(AlarmTest, test_cancel_idempotent) {
123 alarm_t *alarm = alarm_new();
124 alarm_set(alarm, 10, cb, NULL);
125 alarm_cancel(alarm);
126 alarm_cancel(alarm);
127 alarm_cancel(alarm);
128 alarm_free(alarm);
129 }
130
TEST_F(AlarmTest,test_set_short)131 TEST_F(AlarmTest, test_set_short) {
132 alarm_t *alarm = alarm_new();
133 alarm_set(alarm, 10, cb, NULL);
134
135 EXPECT_EQ(cb_counter, 0);
136 EXPECT_EQ(lock_count, 1);
137
138 semaphore_wait(semaphore);
139
140 EXPECT_EQ(cb_counter, 1);
141 EXPECT_EQ(lock_count, 0);
142
143 alarm_free(alarm);
144 }
145
TEST_F(AlarmTest,test_set_long)146 TEST_F(AlarmTest, test_set_long) {
147 alarm_t *alarm = alarm_new();
148 alarm_set(alarm, TIMER_INTERVAL_FOR_WAKELOCK_IN_MS, cb, NULL);
149
150 EXPECT_EQ(cb_counter, 0);
151 EXPECT_EQ(lock_count, 0);
152
153 semaphore_wait(semaphore);
154
155 EXPECT_EQ(cb_counter, 1);
156 EXPECT_EQ(lock_count, 0);
157
158 alarm_free(alarm);
159 }
160
TEST_F(AlarmTest,test_set_short_short)161 TEST_F(AlarmTest, test_set_short_short) {
162 alarm_t *alarm[2] = {
163 alarm_new(),
164 alarm_new()
165 };
166
167 alarm_set(alarm[0], 10, cb, NULL);
168 alarm_set(alarm[1], 20, cb, NULL);
169
170 EXPECT_EQ(cb_counter, 0);
171 EXPECT_EQ(lock_count, 1);
172
173 semaphore_wait(semaphore);
174
175 EXPECT_EQ(cb_counter, 1);
176 EXPECT_EQ(lock_count, 1);
177
178 semaphore_wait(semaphore);
179
180 EXPECT_EQ(cb_counter, 2);
181 EXPECT_EQ(lock_count, 0);
182
183 alarm_free(alarm[0]);
184 alarm_free(alarm[1]);
185 }
186
TEST_F(AlarmTest,test_set_short_long)187 TEST_F(AlarmTest, test_set_short_long) {
188 alarm_t *alarm[2] = {
189 alarm_new(),
190 alarm_new()
191 };
192
193 alarm_set(alarm[0], 10, cb, NULL);
194 alarm_set(alarm[1], 10 + TIMER_INTERVAL_FOR_WAKELOCK_IN_MS + EPSILON_MS, cb, NULL);
195
196 EXPECT_EQ(cb_counter, 0);
197 EXPECT_EQ(lock_count, 1);
198
199 semaphore_wait(semaphore);
200
201 EXPECT_EQ(cb_counter, 1);
202 EXPECT_EQ(lock_count, 0);
203
204 semaphore_wait(semaphore);
205
206 EXPECT_EQ(cb_counter, 2);
207 EXPECT_EQ(lock_count, 0);
208
209 alarm_free(alarm[0]);
210 alarm_free(alarm[1]);
211 }
212
TEST_F(AlarmTest,test_set_long_long)213 TEST_F(AlarmTest, test_set_long_long) {
214 alarm_t *alarm[2] = {
215 alarm_new(),
216 alarm_new()
217 };
218
219 alarm_set(alarm[0], TIMER_INTERVAL_FOR_WAKELOCK_IN_MS, cb, NULL);
220 alarm_set(alarm[1], 2 * TIMER_INTERVAL_FOR_WAKELOCK_IN_MS + EPSILON_MS, cb, NULL);
221
222 EXPECT_EQ(cb_counter, 0);
223 EXPECT_EQ(lock_count, 0);
224
225 semaphore_wait(semaphore);
226
227 EXPECT_EQ(cb_counter, 1);
228 EXPECT_EQ(lock_count, 0);
229
230 semaphore_wait(semaphore);
231
232 EXPECT_EQ(cb_counter, 2);
233 EXPECT_EQ(lock_count, 0);
234
235 alarm_free(alarm[0]);
236 alarm_free(alarm[1]);
237 }
238
239 // Try to catch any race conditions between the timer callback and |alarm_free|.
TEST_F(AlarmTest,test_callback_free_race)240 TEST_F(AlarmTest, test_callback_free_race) {
241 for (int i = 0; i < 1000; ++i) {
242 alarm_t *alarm = alarm_new();
243 alarm_set(alarm, 0, cb, NULL);
244 alarm_free(alarm);
245 }
246 }
247