1/******************************************************************************
2 *
3 *  Copyright (C) 2014 Google, Inc.
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19#include <gtest/gtest.h>
20
21#include "AlarmTestHarness.h"
22
23extern "C" {
24#include "alarm.h"
25#include "osi.h"
26#include "semaphore.h"
27}
28
29static semaphore_t *semaphore;
30static int cb_counter;
31
32static const uint64_t EPSILON_MS = 5;
33
34static void msleep(uint64_t ms) {
35  usleep(ms * 1000);
36}
37
38class AlarmTest : public AlarmTestHarness {
39  protected:
40    virtual void SetUp() {
41      AlarmTestHarness::SetUp();
42      cb_counter = 0;
43
44      semaphore = semaphore_new(0);
45    }
46
47    virtual void TearDown() {
48      semaphore_free(semaphore);
49      AlarmTestHarness::TearDown();
50    }
51};
52
53static void cb(UNUSED_ATTR void *data) {
54  ++cb_counter;
55  semaphore_post(semaphore);
56}
57
58TEST_F(AlarmTest, test_new_free_simple) {
59  alarm_t *alarm = alarm_new();
60  ASSERT_TRUE(alarm != NULL);
61  alarm_free(alarm);
62}
63
64TEST_F(AlarmTest, test_free_null) {
65  alarm_free(NULL);
66}
67
68TEST_F(AlarmTest, test_simple_cancel) {
69  alarm_t *alarm = alarm_new();
70  alarm_cancel(alarm);
71  alarm_free(alarm);
72}
73
74TEST_F(AlarmTest, test_cancel) {
75  alarm_t *alarm = alarm_new();
76  alarm_set(alarm, 10, cb, NULL);
77  alarm_cancel(alarm);
78
79  msleep(10 + EPSILON_MS);
80
81  EXPECT_EQ(cb_counter, 0);
82  EXPECT_EQ(lock_count, 0);
83  alarm_free(alarm);
84}
85
86TEST_F(AlarmTest, test_cancel_idempotent) {
87  alarm_t *alarm = alarm_new();
88  alarm_set(alarm, 10, cb, NULL);
89  alarm_cancel(alarm);
90  alarm_cancel(alarm);
91  alarm_cancel(alarm);
92  alarm_free(alarm);
93}
94
95TEST_F(AlarmTest, test_set_short) {
96  alarm_t *alarm = alarm_new();
97  alarm_set(alarm, 10, cb, NULL);
98
99  EXPECT_EQ(cb_counter, 0);
100  EXPECT_EQ(lock_count, 1);
101
102  semaphore_wait(semaphore);
103
104  EXPECT_EQ(cb_counter, 1);
105  EXPECT_EQ(lock_count, 0);
106
107  alarm_free(alarm);
108}
109
110TEST_F(AlarmTest, test_set_long) {
111  alarm_t *alarm = alarm_new();
112  alarm_set(alarm, TIMER_INTERVAL_FOR_WAKELOCK_IN_MS, cb, NULL);
113
114  EXPECT_EQ(cb_counter, 0);
115  EXPECT_EQ(lock_count, 0);
116
117  semaphore_wait(semaphore);
118
119  EXPECT_EQ(cb_counter, 1);
120  EXPECT_EQ(lock_count, 0);
121
122  alarm_free(alarm);
123}
124
125TEST_F(AlarmTest, test_set_short_short) {
126  alarm_t *alarm[2] = {
127    alarm_new(),
128    alarm_new()
129  };
130
131  alarm_set(alarm[0], 10, cb, NULL);
132  alarm_set(alarm[1], 20, cb, NULL);
133
134  EXPECT_EQ(cb_counter, 0);
135  EXPECT_EQ(lock_count, 1);
136
137  semaphore_wait(semaphore);
138
139  EXPECT_EQ(cb_counter, 1);
140  EXPECT_EQ(lock_count, 1);
141
142  semaphore_wait(semaphore);
143
144  EXPECT_EQ(cb_counter, 2);
145  EXPECT_EQ(lock_count, 0);
146
147  alarm_free(alarm[0]);
148  alarm_free(alarm[1]);
149}
150
151TEST_F(AlarmTest, test_set_short_long) {
152  alarm_t *alarm[2] = {
153    alarm_new(),
154    alarm_new()
155  };
156
157  alarm_set(alarm[0], 10, cb, NULL);
158  alarm_set(alarm[1], 10 + TIMER_INTERVAL_FOR_WAKELOCK_IN_MS + EPSILON_MS, cb, NULL);
159
160  EXPECT_EQ(cb_counter, 0);
161  EXPECT_EQ(lock_count, 1);
162
163  semaphore_wait(semaphore);
164
165  EXPECT_EQ(cb_counter, 1);
166  EXPECT_EQ(lock_count, 0);
167
168  semaphore_wait(semaphore);
169
170  EXPECT_EQ(cb_counter, 2);
171  EXPECT_EQ(lock_count, 0);
172
173  alarm_free(alarm[0]);
174  alarm_free(alarm[1]);
175}
176
177TEST_F(AlarmTest, test_set_long_long) {
178  alarm_t *alarm[2] = {
179    alarm_new(),
180    alarm_new()
181  };
182
183  alarm_set(alarm[0], TIMER_INTERVAL_FOR_WAKELOCK_IN_MS, cb, NULL);
184  alarm_set(alarm[1], 2 * TIMER_INTERVAL_FOR_WAKELOCK_IN_MS + EPSILON_MS, cb, NULL);
185
186  EXPECT_EQ(cb_counter, 0);
187  EXPECT_EQ(lock_count, 0);
188
189  semaphore_wait(semaphore);
190
191  EXPECT_EQ(cb_counter, 1);
192  EXPECT_EQ(lock_count, 0);
193
194  semaphore_wait(semaphore);
195
196  EXPECT_EQ(cb_counter, 2);
197  EXPECT_EQ(lock_count, 0);
198
199  alarm_free(alarm[0]);
200  alarm_free(alarm[1]);
201}
202
203// Try to catch any race conditions between the timer callback and |alarm_free|.
204TEST_F(AlarmTest, test_callback_free_race) {
205  for (int i = 0; i < 1000; ++i) {
206    alarm_t *alarm = alarm_new();
207    alarm_set(alarm, 0, cb, NULL);
208    alarm_free(alarm);
209  }
210}
211