Sharvil Nanavati | f0e7c8b | 2014-07-01 18:42:56 -0700 | [diff] [blame] | 1 | #include <gtest/gtest.h> |
| 2 | #include <hardware/bluetooth.h> |
| 3 | #include <unistd.h> |
| 4 | |
| 5 | extern "C" { |
| 6 | #include "alarm.h" |
Sharvil Nanavati | e0cdd33 | 2014-07-17 15:45:40 -0700 | [diff] [blame] | 7 | #include "osi.h" |
Sharvil Nanavati | f0e7c8b | 2014-07-01 18:42:56 -0700 | [diff] [blame] | 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 | |
| 22 | static void msleep(uint64_t ms) { |
Sharvil Nanavati | 405b5c9 | 2016-06-17 14:15:46 -0700 | [diff] [blame] | 23 | TEMP_FAILURE_RETRY(usleep(ms * 1000)); |
Sharvil Nanavati | f0e7c8b | 2014-07-01 18:42:56 -0700 | [diff] [blame] | 24 | } |
| 25 | |
| 26 | static void timer_callback(void *) { |
| 27 | saved_callback(saved_data); |
| 28 | } |
| 29 | |
| 30 | class 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 | |
Sharvil Nanavati | e0cdd33 | 2014-07-17 15:45:40 -0700 | [diff] [blame] | 52 | static void cb(UNUSED_ATTR void *data) { |
Sharvil Nanavati | f0e7c8b | 2014-07-01 18:42:56 -0700 | [diff] [blame] | 53 | ++cb_counter; |
| 54 | semaphore_post(semaphore); |
| 55 | } |
| 56 | |
| 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 | |
| 69 | static int acquire_wake_lock(const char *) { |
| 70 | if (!lock_count) |
| 71 | lock_count = 1; |
| 72 | return BT_STATUS_SUCCESS; |
| 73 | } |
| 74 | |
| 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 | |
| 90 | TEST_F(AlarmTest, test_new_simple) { |
| 91 | alarm_t *alarm = alarm_new(); |
| 92 | ASSERT_TRUE(alarm != NULL); |
| 93 | } |
| 94 | |
| 95 | TEST_F(AlarmTest, test_free_simple) { |
| 96 | alarm_t *alarm = alarm_new(); |
| 97 | alarm_free(alarm); |
| 98 | } |
| 99 | |
| 100 | TEST_F(AlarmTest, test_free_null) { |
| 101 | alarm_free(NULL); |
| 102 | } |
| 103 | |
| 104 | TEST_F(AlarmTest, test_simple_cancel) { |
| 105 | alarm_t *alarm = alarm_new(); |
| 106 | alarm_cancel(alarm); |
| 107 | alarm_free(alarm); |
| 108 | } |
| 109 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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|. |
| 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 | } |