• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 #include "osi/include/alarm.h"
24 #include "osi/include/fixed_queue.h"
25 #include "osi/include/osi.h"
26 #include "osi/include/semaphore.h"
27 #include "osi/include/thread.h"
28 
29 static semaphore_t* semaphore;
30 static int cb_counter;
31 static int cb_misordered_counter;
32 
33 static const uint64_t EPSILON_MS = 50;
34 
msleep(uint64_t ms)35 static void msleep(uint64_t ms) { usleep(ms * 1000); }
36 
37 class AlarmTest : public AlarmTestHarness {
38  protected:
SetUp()39   virtual void SetUp() {
40     AlarmTestHarness::SetUp();
41     cb_counter = 0;
42     cb_misordered_counter = 0;
43 
44     semaphore = semaphore_new(0);
45   }
46 
TearDown()47   virtual void TearDown() {
48     semaphore_free(semaphore);
49     AlarmTestHarness::TearDown();
50   }
51 };
52 
cb(UNUSED_ATTR void * data)53 static void cb(UNUSED_ATTR void* data) {
54   ++cb_counter;
55   semaphore_post(semaphore);
56 }
57 
ordered_cb(void * data)58 static void ordered_cb(void* data) {
59   int i = PTR_TO_INT(data);
60   if (i != cb_counter) cb_misordered_counter++;
61   ++cb_counter;
62   semaphore_post(semaphore);
63 }
64 
TEST_F(AlarmTest,test_new_free_simple)65 TEST_F(AlarmTest, test_new_free_simple) {
66   alarm_t* alarm = alarm_new("alarm_test.test_new_free_simple");
67   ASSERT_TRUE(alarm != NULL);
68   alarm_free(alarm);
69 }
70 
TEST_F(AlarmTest,test_free_null)71 TEST_F(AlarmTest, test_free_null) { alarm_free(NULL); }
72 
TEST_F(AlarmTest,test_simple_cancel)73 TEST_F(AlarmTest, test_simple_cancel) {
74   alarm_t* alarm = alarm_new("alarm_test.test_simple_cancel");
75   alarm_cancel(alarm);
76   alarm_free(alarm);
77 }
78 
TEST_F(AlarmTest,test_cancel)79 TEST_F(AlarmTest, test_cancel) {
80   alarm_t* alarm = alarm_new("alarm_test.test_cancel");
81   alarm_set(alarm, 10, cb, NULL);
82   alarm_cancel(alarm);
83 
84   msleep(10 + EPSILON_MS);
85 
86   EXPECT_EQ(cb_counter, 0);
87   EXPECT_FALSE(WakeLockHeld());
88   alarm_free(alarm);
89 }
90 
TEST_F(AlarmTest,test_cancel_idempotent)91 TEST_F(AlarmTest, test_cancel_idempotent) {
92   alarm_t* alarm = alarm_new("alarm_test.test_cancel_idempotent");
93   alarm_set(alarm, 10, cb, NULL);
94   alarm_cancel(alarm);
95   alarm_cancel(alarm);
96   alarm_cancel(alarm);
97   alarm_free(alarm);
98 }
99 
TEST_F(AlarmTest,test_set_short)100 TEST_F(AlarmTest, test_set_short) {
101   alarm_t* alarm = alarm_new("alarm_test.test_set_short");
102 
103   alarm_set(alarm, 10, cb, NULL);
104 
105   EXPECT_EQ(cb_counter, 0);
106   EXPECT_TRUE(WakeLockHeld());
107 
108   semaphore_wait(semaphore);
109 
110   EXPECT_EQ(cb_counter, 1);
111   EXPECT_FALSE(WakeLockHeld());
112 
113   alarm_free(alarm);
114 }
115 
TEST_F(AlarmTest,test_set_short_periodic)116 TEST_F(AlarmTest, test_set_short_periodic) {
117   alarm_t* alarm = alarm_new_periodic("alarm_test.test_set_short_periodic");
118 
119   alarm_set(alarm, 10, cb, NULL);
120 
121   EXPECT_EQ(cb_counter, 0);
122   EXPECT_TRUE(WakeLockHeld());
123 
124   for (int i = 1; i <= 10; i++) {
125     semaphore_wait(semaphore);
126 
127     EXPECT_GE(cb_counter, i);
128     EXPECT_TRUE(WakeLockHeld());
129   }
130   alarm_cancel(alarm);
131   EXPECT_FALSE(WakeLockHeld());
132 
133   alarm_free(alarm);
134 }
135 
TEST_F(AlarmTest,test_set_zero_periodic)136 TEST_F(AlarmTest, test_set_zero_periodic) {
137   alarm_t* alarm = alarm_new_periodic("alarm_test.test_set_zero_periodic");
138 
139   alarm_set(alarm, 0, cb, NULL);
140 
141   EXPECT_TRUE(WakeLockHeld());
142 
143   for (int i = 1; i <= 10; i++) {
144     semaphore_wait(semaphore);
145 
146     EXPECT_GE(cb_counter, i);
147     EXPECT_TRUE(WakeLockHeld());
148   }
149   alarm_cancel(alarm);
150   EXPECT_FALSE(WakeLockHeld());
151 
152   alarm_free(alarm);
153 }
154 
TEST_F(AlarmTest,test_set_long)155 TEST_F(AlarmTest, test_set_long) {
156   alarm_t* alarm = alarm_new("alarm_test.test_set_long");
157   alarm_set(alarm, TIMER_INTERVAL_FOR_WAKELOCK_IN_MS + EPSILON_MS, cb, NULL);
158 
159   EXPECT_EQ(cb_counter, 0);
160   EXPECT_FALSE(WakeLockHeld());
161 
162   semaphore_wait(semaphore);
163 
164   EXPECT_EQ(cb_counter, 1);
165   EXPECT_FALSE(WakeLockHeld());
166 
167   alarm_free(alarm);
168 }
169 
TEST_F(AlarmTest,test_set_short_short)170 TEST_F(AlarmTest, test_set_short_short) {
171   alarm_t* alarm[2] = {alarm_new("alarm_test.test_set_short_short_0"),
172                        alarm_new("alarm_test.test_set_short_short_1")};
173 
174   alarm_set(alarm[0], 10, cb, NULL);
175   alarm_set(alarm[1], 20, cb, NULL);
176 
177   EXPECT_EQ(cb_counter, 0);
178   EXPECT_TRUE(WakeLockHeld());
179 
180   semaphore_wait(semaphore);
181 
182   EXPECT_EQ(cb_counter, 1);
183   EXPECT_TRUE(WakeLockHeld());
184 
185   semaphore_wait(semaphore);
186 
187   EXPECT_EQ(cb_counter, 2);
188   EXPECT_FALSE(WakeLockHeld());
189 
190   alarm_free(alarm[0]);
191   alarm_free(alarm[1]);
192 }
193 
TEST_F(AlarmTest,test_set_short_long)194 TEST_F(AlarmTest, test_set_short_long) {
195   alarm_t* alarm[2] = {alarm_new("alarm_test.test_set_short_long_0"),
196                        alarm_new("alarm_test.test_set_short_long_1")};
197 
198   alarm_set(alarm[0], 10, cb, NULL);
199   alarm_set(alarm[1], 10 + TIMER_INTERVAL_FOR_WAKELOCK_IN_MS + EPSILON_MS, cb,
200             NULL);
201 
202   EXPECT_EQ(cb_counter, 0);
203   EXPECT_TRUE(WakeLockHeld());
204 
205   semaphore_wait(semaphore);
206 
207   EXPECT_EQ(cb_counter, 1);
208   EXPECT_FALSE(WakeLockHeld());
209 
210   semaphore_wait(semaphore);
211 
212   EXPECT_EQ(cb_counter, 2);
213   EXPECT_FALSE(WakeLockHeld());
214 
215   alarm_free(alarm[0]);
216   alarm_free(alarm[1]);
217 }
218 
TEST_F(AlarmTest,test_set_long_long)219 TEST_F(AlarmTest, test_set_long_long) {
220   alarm_t* alarm[2] = {alarm_new("alarm_test.test_set_long_long_0"),
221                        alarm_new("alarm_test.test_set_long_long_1")};
222 
223   alarm_set(alarm[0], TIMER_INTERVAL_FOR_WAKELOCK_IN_MS + EPSILON_MS, cb, NULL);
224   alarm_set(alarm[1], 2 * (TIMER_INTERVAL_FOR_WAKELOCK_IN_MS + EPSILON_MS), cb,
225             NULL);
226 
227   EXPECT_EQ(cb_counter, 0);
228   EXPECT_FALSE(WakeLockHeld());
229 
230   semaphore_wait(semaphore);
231 
232   EXPECT_EQ(cb_counter, 1);
233   EXPECT_FALSE(WakeLockHeld());
234 
235   semaphore_wait(semaphore);
236 
237   EXPECT_EQ(cb_counter, 2);
238   EXPECT_FALSE(WakeLockHeld());
239 
240   alarm_free(alarm[0]);
241   alarm_free(alarm[1]);
242 }
243 
TEST_F(AlarmTest,test_is_scheduled)244 TEST_F(AlarmTest, test_is_scheduled) {
245   alarm_t* alarm = alarm_new("alarm_test.test_is_scheduled");
246 
247   EXPECT_FALSE(alarm_is_scheduled((alarm_t*)NULL));
248   EXPECT_FALSE(alarm_is_scheduled(alarm));
249   alarm_set(alarm, TIMER_INTERVAL_FOR_WAKELOCK_IN_MS + EPSILON_MS, cb, NULL);
250   EXPECT_TRUE(alarm_is_scheduled(alarm));
251 
252   EXPECT_EQ(cb_counter, 0);
253   EXPECT_FALSE(WakeLockHeld());
254 
255   semaphore_wait(semaphore);
256 
257   EXPECT_FALSE(alarm_is_scheduled(alarm));
258   EXPECT_EQ(cb_counter, 1);
259   EXPECT_FALSE(WakeLockHeld());
260 
261   alarm_free(alarm);
262 }
263 
264 // Test whether the callbacks are invoked in the expected order
TEST_F(AlarmTest,test_callback_ordering)265 TEST_F(AlarmTest, test_callback_ordering) {
266   alarm_t* alarms[100];
267 
268   for (int i = 0; i < 100; i++) {
269     const std::string alarm_name =
270         "alarm_test.test_callback_ordering[" + std::to_string(i) + "]";
271     alarms[i] = alarm_new(alarm_name.c_str());
272   }
273 
274   for (int i = 0; i < 100; i++) {
275     alarm_set(alarms[i], 100, ordered_cb, INT_TO_PTR(i));
276   }
277 
278   for (int i = 1; i <= 100; i++) {
279     semaphore_wait(semaphore);
280     EXPECT_GE(cb_counter, i);
281   }
282   EXPECT_EQ(cb_counter, 100);
283   EXPECT_EQ(cb_misordered_counter, 0);
284 
285   for (int i = 0; i < 100; i++) alarm_free(alarms[i]);
286 
287   EXPECT_FALSE(WakeLockHeld());
288 }
289 
290 // Test whether the callbacks are involed in the expected order on a
291 // separate queue.
TEST_F(AlarmTest,test_callback_ordering_on_queue)292 TEST_F(AlarmTest, test_callback_ordering_on_queue) {
293   alarm_t* alarms[100];
294   fixed_queue_t* queue = fixed_queue_new(SIZE_MAX);
295   thread_t* thread =
296       thread_new("timers.test_callback_ordering_on_queue.thread");
297 
298   alarm_register_processing_queue(queue, thread);
299 
300   for (int i = 0; i < 100; i++) {
301     const std::string alarm_name =
302         "alarm_test.test_callback_ordering_on_queue[" + std::to_string(i) + "]";
303     alarms[i] = alarm_new(alarm_name.c_str());
304   }
305 
306   for (int i = 0; i < 100; i++) {
307     alarm_set_on_queue(alarms[i], 100, ordered_cb, INT_TO_PTR(i), queue);
308   }
309 
310   for (int i = 1; i <= 100; i++) {
311     semaphore_wait(semaphore);
312     EXPECT_GE(cb_counter, i);
313   }
314   EXPECT_EQ(cb_counter, 100);
315   EXPECT_EQ(cb_misordered_counter, 0);
316 
317   for (int i = 0; i < 100; i++) alarm_free(alarms[i]);
318 
319   EXPECT_FALSE(WakeLockHeld());
320 
321   alarm_unregister_processing_queue(queue);
322   fixed_queue_free(queue, NULL);
323   thread_free(thread);
324 }
325 
326 // Test whether unregistering a processing queue cancels all timers using
327 // that queue.
TEST_F(AlarmTest,test_unregister_processing_queue)328 TEST_F(AlarmTest, test_unregister_processing_queue) {
329   alarm_t* alarms[100];
330   fixed_queue_t* queue = fixed_queue_new(SIZE_MAX);
331   thread_t* thread =
332       thread_new("timers.test_unregister_processing_queue.thread");
333 
334   alarm_register_processing_queue(queue, thread);
335 
336   for (int i = 0; i < 100; i++) {
337     const std::string alarm_name =
338         "alarm_test.test_unregister_processing_queue[" + std::to_string(i) +
339         "]";
340     alarms[i] = alarm_new(alarm_name.c_str());
341   }
342 
343   // Schedule half of the timers to expire soon, and the rest far in the future
344   for (int i = 0; i < 50; i++) {
345     alarm_set_on_queue(alarms[i], 100, ordered_cb, INT_TO_PTR(i), queue);
346   }
347   for (int i = 50; i < 100; i++) {
348     alarm_set_on_queue(alarms[i], 1000 * 1000, ordered_cb, INT_TO_PTR(i),
349                        queue);
350   }
351 
352   // Wait until half of the timers have expired
353   for (int i = 1; i <= 50; i++) {
354     semaphore_wait(semaphore);
355     EXPECT_GE(cb_counter, i);
356   }
357   EXPECT_EQ(cb_counter, 50);
358   EXPECT_EQ(cb_misordered_counter, 0);
359 
360   // Test that only the expired timers are not scheduled
361   for (int i = 0; i < 50; i++) {
362     EXPECT_FALSE(alarm_is_scheduled(alarms[i]));
363   }
364   for (int i = 50; i < 100; i++) {
365     EXPECT_TRUE(alarm_is_scheduled(alarms[i]));
366   }
367 
368   alarm_unregister_processing_queue(queue);
369 
370   // Test that none of the timers are scheduled
371   for (int i = 0; i < 100; i++) {
372     EXPECT_FALSE(alarm_is_scheduled(alarms[i]));
373   }
374 
375   for (int i = 0; i < 100; i++) {
376     alarm_free(alarms[i]);
377   }
378 
379   EXPECT_FALSE(WakeLockHeld());
380 
381   fixed_queue_free(queue, NULL);
382   thread_free(thread);
383 }
384 
385 // Test whether unregistering a processing queue cancels all periodic timers
386 // using that queue.
TEST_F(AlarmTest,test_periodic_unregister_processing_queue)387 TEST_F(AlarmTest, test_periodic_unregister_processing_queue) {
388   alarm_t* alarms[5];
389   fixed_queue_t* queue = fixed_queue_new(SIZE_MAX);
390   thread_t* thread =
391       thread_new("timers.test_periodic_unregister_processing_queue.thread");
392 
393   alarm_register_processing_queue(queue, thread);
394 
395   for (int i = 0; i < 5; i++) {
396     const std::string alarm_name =
397         "alarm_test.test_periodic_unregister_processing_queue[" +
398         std::to_string(i) + "]";
399     alarms[i] = alarm_new_periodic(alarm_name.c_str());
400   }
401 
402   // Schedule each of the timers with different period
403   for (int i = 0; i < 5; i++) {
404     alarm_set_on_queue(alarms[i], 20 + i, cb, INT_TO_PTR(i), queue);
405   }
406   EXPECT_TRUE(WakeLockHeld());
407 
408   for (int i = 1; i <= 20; i++) {
409     semaphore_wait(semaphore);
410 
411     EXPECT_GE(cb_counter, i);
412     EXPECT_TRUE(WakeLockHeld());
413   }
414 
415   // Test that all timers are still scheduled
416   for (int i = 0; i < 5; i++) {
417     EXPECT_TRUE(alarm_is_scheduled(alarms[i]));
418   }
419 
420   alarm_unregister_processing_queue(queue);
421 
422   int saved_cb_counter = cb_counter;
423 
424   // Test that none of the timers are scheduled
425   for (int i = 0; i < 5; i++) {
426     EXPECT_FALSE(alarm_is_scheduled(alarms[i]));
427   }
428 
429   // Sleep for 500ms and test again that the cb_counter hasn't been modified
430   usleep(500 * 1000);
431   EXPECT_TRUE(cb_counter == saved_cb_counter);
432 
433   for (int i = 0; i < 5; i++) {
434     alarm_free(alarms[i]);
435   }
436 
437   EXPECT_FALSE(WakeLockHeld());
438 
439   fixed_queue_free(queue, NULL);
440   thread_free(thread);
441 }
442 
443 // Try to catch any race conditions between the timer callback and |alarm_free|.
TEST_F(AlarmTest,test_callback_free_race)444 TEST_F(AlarmTest, test_callback_free_race) {
445   for (int i = 0; i < 1000; ++i) {
446     const std::string alarm_name =
447         "alarm_test.test_callback_free_race[" + std::to_string(i) + "]";
448     alarm_t* alarm = alarm_new(alarm_name.c_str());
449     alarm_set(alarm, 0, cb, NULL);
450     alarm_free(alarm);
451   }
452   alarm_cleanup();
453 }
454