alarm_test.cpp revision e0cdd3399119823e2f1ec75161c1cf67829651bf
1#include <gtest/gtest.h>
2#include <hardware/bluetooth.h>
3#include <unistd.h>
4
5extern "C" {
6#include "alarm.h"
7#include "osi.h"
8#include "semaphore.h"
9}
10
11extern int64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS;
12
13static semaphore_t *semaphore;
14static int cb_counter;
15static int lock_count;
16static timer_t timer;
17static alarm_cb saved_callback;
18static void *saved_data;
19
20static const uint64_t EPSILON_MS = 5;
21
22static void msleep(uint64_t ms) {
23  usleep(ms * 1000);
24}
25
26static void timer_callback(void *) {
27  saved_callback(saved_data);
28}
29
30class AlarmTest : public ::testing::Test {
31  protected:
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
47    virtual void TearDown() {
48      timer_delete(timer);
49    }
50};
51
52static void cb(UNUSED_ATTR void *data) {
53  ++cb_counter;
54  semaphore_post(semaphore);
55}
56
57static 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
69static int acquire_wake_lock(const char *) {
70  if (!lock_count)
71    lock_count = 1;
72  return BT_STATUS_SUCCESS;
73}
74
75static int release_wake_lock(const char *) {
76  if (lock_count)
77    lock_count = 0;
78  return BT_STATUS_SUCCESS;
79}
80
81static 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
88bt_os_callouts_t *bt_os_callouts = &stub;
89
90TEST_F(AlarmTest, test_new_simple) {
91  alarm_t *alarm = alarm_new();
92  ASSERT_TRUE(alarm != NULL);
93}
94
95TEST_F(AlarmTest, test_free_simple) {
96  alarm_t *alarm = alarm_new();
97  alarm_free(alarm);
98}
99
100TEST_F(AlarmTest, test_free_null) {
101  alarm_free(NULL);
102}
103
104TEST_F(AlarmTest, test_simple_cancel) {
105  alarm_t *alarm = alarm_new();
106  alarm_cancel(alarm);
107  alarm_free(alarm);
108}
109
110TEST_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
122TEST_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
131TEST_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
146TEST_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
161TEST_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
187TEST_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
213TEST_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|.
240TEST_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