]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * QTest testcase for the ptimer | |
3 | * | |
4 | * Copyright (c) 2016 Dmitry Osipenko <digetx@gmail.com> | |
5 | * | |
6 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
7 | * See the COPYING file in the top-level directory. | |
8 | * | |
9 | */ | |
10 | ||
11 | #include "qemu/osdep.h" | |
12 | #include <glib/gprintf.h> | |
13 | ||
14 | #include "qemu/main-loop.h" | |
15 | #include "hw/ptimer.h" | |
16 | ||
17 | #include "libqtest.h" | |
18 | #include "ptimer-test.h" | |
19 | ||
20 | static bool triggered; | |
21 | ||
22 | static void ptimer_trigger(void *opaque) | |
23 | { | |
24 | triggered = true; | |
25 | } | |
26 | ||
27 | static void ptimer_test_expire_qemu_timers(int64_t expire_time, | |
28 | QEMUClockType type) | |
29 | { | |
30 | QEMUTimerList *timer_list = main_loop_tlg.tl[type]; | |
31 | QEMUTimer *t = timer_list->active_timers.next; | |
32 | ||
33 | while (t != NULL) { | |
34 | if (t->expire_time == expire_time) { | |
35 | timer_del(t); | |
36 | ||
37 | if (t->cb != NULL) { | |
38 | t->cb(t->opaque); | |
39 | } | |
40 | } | |
41 | ||
42 | t = t->next; | |
43 | } | |
44 | } | |
45 | ||
46 | static void ptimer_test_set_qemu_time_ns(int64_t ns) | |
47 | { | |
48 | ptimer_test_time_ns = ns; | |
49 | } | |
50 | ||
51 | static void qemu_clock_step(uint64_t ns) | |
52 | { | |
53 | int64_t deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); | |
54 | int64_t advanced_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns; | |
55 | ||
56 | while (deadline != -1 && deadline <= advanced_time) { | |
57 | ptimer_test_set_qemu_time_ns(deadline); | |
58 | ptimer_test_expire_qemu_timers(deadline, QEMU_CLOCK_VIRTUAL); | |
59 | deadline = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); | |
60 | } | |
61 | ||
62 | ptimer_test_set_qemu_time_ns(advanced_time); | |
63 | } | |
64 | ||
65 | static void check_set_count(gconstpointer arg) | |
66 | { | |
67 | const uint8_t *policy = arg; | |
68 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
69 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
70 | ||
71 | triggered = false; | |
72 | ||
73 | ptimer_set_count(ptimer, 1000); | |
74 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 1000); | |
75 | g_assert_false(triggered); | |
76 | ptimer_free(ptimer); | |
77 | } | |
78 | ||
79 | static void check_set_limit(gconstpointer arg) | |
80 | { | |
81 | const uint8_t *policy = arg; | |
82 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
83 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
84 | ||
85 | triggered = false; | |
86 | ||
87 | ptimer_set_limit(ptimer, 1000, 0); | |
88 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
89 | g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 1000); | |
90 | g_assert_false(triggered); | |
91 | ||
92 | ptimer_set_limit(ptimer, 2000, 1); | |
93 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 2000); | |
94 | g_assert_cmpuint(ptimer_get_limit(ptimer), ==, 2000); | |
95 | g_assert_false(triggered); | |
96 | ptimer_free(ptimer); | |
97 | } | |
98 | ||
99 | static void check_oneshot(gconstpointer arg) | |
100 | { | |
101 | const uint8_t *policy = arg; | |
102 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
103 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
104 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); | |
105 | ||
106 | triggered = false; | |
107 | ||
108 | ptimer_set_period(ptimer, 2000000); | |
109 | ptimer_set_count(ptimer, 10); | |
110 | ptimer_run(ptimer, 1); | |
111 | ||
112 | qemu_clock_step(2000000 * 2 + 1); | |
113 | ||
114 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7); | |
115 | g_assert_false(triggered); | |
116 | ||
117 | ptimer_stop(ptimer); | |
118 | ||
119 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7); | |
120 | g_assert_false(triggered); | |
121 | ||
122 | qemu_clock_step(2000000 * 11); | |
123 | ||
124 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7); | |
125 | g_assert_false(triggered); | |
126 | ||
127 | ptimer_run(ptimer, 1); | |
128 | ||
129 | qemu_clock_step(2000000 * 7 + 1); | |
130 | ||
131 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); | |
132 | ||
133 | if (no_round_down) { | |
134 | g_assert_false(triggered); | |
135 | } else { | |
136 | g_assert_true(triggered); | |
137 | ||
138 | triggered = false; | |
139 | } | |
140 | ||
141 | qemu_clock_step(2000000); | |
142 | ||
143 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
144 | ||
145 | if (no_round_down) { | |
146 | g_assert_true(triggered); | |
147 | ||
148 | triggered = false; | |
149 | } else { | |
150 | g_assert_false(triggered); | |
151 | } | |
152 | ||
153 | qemu_clock_step(4000000); | |
154 | ||
155 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
156 | g_assert_false(triggered); | |
157 | ||
158 | ptimer_set_count(ptimer, 10); | |
159 | ||
160 | qemu_clock_step(20000000 + 1); | |
161 | ||
162 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10); | |
163 | g_assert_false(triggered); | |
164 | ||
165 | ptimer_set_limit(ptimer, 9, 1); | |
166 | ||
167 | qemu_clock_step(20000000 + 1); | |
168 | ||
169 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 9); | |
170 | g_assert_false(triggered); | |
171 | ||
172 | ptimer_run(ptimer, 1); | |
173 | ||
174 | qemu_clock_step(2000000 + 1); | |
175 | ||
176 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 8 : 7); | |
177 | g_assert_false(triggered); | |
178 | ||
179 | ptimer_set_count(ptimer, 20); | |
180 | ||
181 | qemu_clock_step(2000000 * 19 + 1); | |
182 | ||
183 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); | |
184 | g_assert_false(triggered); | |
185 | ||
186 | qemu_clock_step(2000000); | |
187 | ||
188 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
189 | g_assert_true(triggered); | |
190 | ||
191 | ptimer_stop(ptimer); | |
192 | ||
193 | triggered = false; | |
194 | ||
195 | qemu_clock_step(2000000 * 12 + 1); | |
196 | ||
197 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
198 | g_assert_false(triggered); | |
199 | ptimer_free(ptimer); | |
200 | } | |
201 | ||
202 | static void check_periodic(gconstpointer arg) | |
203 | { | |
204 | const uint8_t *policy = arg; | |
205 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
206 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
207 | bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD); | |
208 | bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER); | |
209 | bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD); | |
210 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); | |
211 | bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT); | |
212 | ||
213 | triggered = false; | |
214 | ||
215 | ptimer_set_period(ptimer, 2000000); | |
216 | ptimer_set_limit(ptimer, 10, 1); | |
217 | ptimer_run(ptimer, 0); | |
218 | ||
219 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 10); | |
220 | g_assert_false(triggered); | |
221 | ||
222 | qemu_clock_step(1); | |
223 | ||
224 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 10 : 9); | |
225 | g_assert_false(triggered); | |
226 | ||
227 | qemu_clock_step(2000000 * 10 - 1); | |
228 | ||
229 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, wrap_policy ? 0 : 10); | |
230 | g_assert_true(triggered); | |
231 | ||
232 | qemu_clock_step(1); | |
233 | ||
234 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
235 | wrap_policy ? 0 : (no_round_down ? 10 : 9)); | |
236 | g_assert_true(triggered); | |
237 | ||
238 | triggered = false; | |
239 | ||
240 | qemu_clock_step(2000000); | |
241 | ||
242 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
243 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
244 | g_assert_false(triggered); | |
245 | ||
246 | ptimer_set_count(ptimer, 20); | |
247 | ||
248 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 20); | |
249 | g_assert_false(triggered); | |
250 | ||
251 | qemu_clock_step(1); | |
252 | ||
253 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 20 : 19); | |
254 | g_assert_false(triggered); | |
255 | ||
256 | qemu_clock_step(2000000 * 11 + 1); | |
257 | ||
258 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 9 : 8); | |
259 | g_assert_false(triggered); | |
260 | ||
261 | qemu_clock_step(2000000 * 10); | |
262 | ||
263 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
264 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
265 | g_assert_true(triggered); | |
266 | ||
267 | triggered = false; | |
268 | ||
269 | ptimer_set_count(ptimer, 3); | |
270 | ||
271 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 3); | |
272 | g_assert_false(triggered); | |
273 | ||
274 | qemu_clock_step(1); | |
275 | ||
276 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 3 : 2); | |
277 | g_assert_false(triggered); | |
278 | ||
279 | qemu_clock_step(2000000 * 4); | |
280 | ||
281 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
282 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
283 | g_assert_true(triggered); | |
284 | ||
285 | ptimer_stop(ptimer); | |
286 | triggered = false; | |
287 | ||
288 | qemu_clock_step(2000000); | |
289 | ||
290 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
291 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
292 | g_assert_false(triggered); | |
293 | ||
294 | ptimer_set_count(ptimer, 3); | |
295 | ptimer_run(ptimer, 0); | |
296 | ||
297 | qemu_clock_step(2000000 * 3 + 1); | |
298 | ||
299 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
300 | wrap_policy ? 0 : (no_round_down ? 10 : 9)); | |
301 | g_assert_true(triggered); | |
302 | ||
303 | triggered = false; | |
304 | ||
305 | qemu_clock_step(2000000); | |
306 | ||
307 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
308 | (no_round_down ? 9 : 8) + (wrap_policy ? 1 : 0)); | |
309 | g_assert_false(triggered); | |
310 | ||
311 | ptimer_set_count(ptimer, 0); | |
312 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
313 | no_immediate_reload ? 0 : 10); | |
314 | ||
315 | if (no_immediate_trigger || trig_only_on_dec) { | |
316 | g_assert_false(triggered); | |
317 | } else { | |
318 | g_assert_true(triggered); | |
319 | } | |
320 | ||
321 | triggered = false; | |
322 | ||
323 | qemu_clock_step(1); | |
324 | ||
325 | if (no_immediate_reload) { | |
326 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
327 | g_assert_false(triggered); | |
328 | ||
329 | qemu_clock_step(2000000); | |
330 | ||
331 | if (no_immediate_trigger) { | |
332 | g_assert_true(triggered); | |
333 | } else { | |
334 | g_assert_false(triggered); | |
335 | } | |
336 | ||
337 | triggered = false; | |
338 | } | |
339 | ||
340 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 10 : 9); | |
341 | g_assert_false(triggered); | |
342 | ||
343 | qemu_clock_step(2000000 * 12); | |
344 | ||
345 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
346 | (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0)); | |
347 | g_assert_true(triggered); | |
348 | ||
349 | ptimer_stop(ptimer); | |
350 | ||
351 | triggered = false; | |
352 | ||
353 | qemu_clock_step(2000000 * 10); | |
354 | ||
355 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
356 | (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0)); | |
357 | g_assert_false(triggered); | |
358 | ||
359 | ptimer_run(ptimer, 0); | |
360 | ptimer_set_period(ptimer, 0); | |
361 | ||
362 | qemu_clock_step(2000000 + 1); | |
363 | ||
364 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
365 | (no_round_down ? 8 : 7) + (wrap_policy ? 1 : 0)); | |
366 | g_assert_false(triggered); | |
367 | ptimer_free(ptimer); | |
368 | } | |
369 | ||
370 | static void check_on_the_fly_mode_change(gconstpointer arg) | |
371 | { | |
372 | const uint8_t *policy = arg; | |
373 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
374 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
375 | bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD); | |
376 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); | |
377 | ||
378 | triggered = false; | |
379 | ||
380 | ptimer_set_period(ptimer, 2000000); | |
381 | ptimer_set_limit(ptimer, 10, 1); | |
382 | ptimer_run(ptimer, 1); | |
383 | ||
384 | qemu_clock_step(2000000 * 9 + 1); | |
385 | ||
386 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); | |
387 | g_assert_false(triggered); | |
388 | ||
389 | ptimer_run(ptimer, 0); | |
390 | ||
391 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); | |
392 | g_assert_false(triggered); | |
393 | ||
394 | qemu_clock_step(2000000); | |
395 | ||
396 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
397 | wrap_policy ? 0 : (no_round_down ? 10 : 9)); | |
398 | g_assert_true(triggered); | |
399 | ||
400 | triggered = false; | |
401 | ||
402 | qemu_clock_step(2000000 * 9); | |
403 | ||
404 | ptimer_run(ptimer, 1); | |
405 | ||
406 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
407 | (no_round_down ? 1 : 0) + (wrap_policy ? 1 : 0)); | |
408 | g_assert_false(triggered); | |
409 | ||
410 | qemu_clock_step(2000000 * 3); | |
411 | ||
412 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
413 | g_assert_true(triggered); | |
414 | ptimer_free(ptimer); | |
415 | } | |
416 | ||
417 | static void check_on_the_fly_period_change(gconstpointer arg) | |
418 | { | |
419 | const uint8_t *policy = arg; | |
420 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
421 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
422 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); | |
423 | ||
424 | triggered = false; | |
425 | ||
426 | ptimer_set_period(ptimer, 2000000); | |
427 | ptimer_set_limit(ptimer, 8, 1); | |
428 | ptimer_run(ptimer, 1); | |
429 | ||
430 | qemu_clock_step(2000000 * 4 + 1); | |
431 | ||
432 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3); | |
433 | g_assert_false(triggered); | |
434 | ||
435 | ptimer_set_period(ptimer, 4000000); | |
436 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3); | |
437 | ||
438 | qemu_clock_step(4000000 * 2 + 1); | |
439 | ||
440 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 2 : 0); | |
441 | g_assert_false(triggered); | |
442 | ||
443 | qemu_clock_step(4000000 * 2); | |
444 | ||
445 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
446 | g_assert_true(triggered); | |
447 | ptimer_free(ptimer); | |
448 | } | |
449 | ||
450 | static void check_on_the_fly_freq_change(gconstpointer arg) | |
451 | { | |
452 | const uint8_t *policy = arg; | |
453 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
454 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
455 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); | |
456 | ||
457 | triggered = false; | |
458 | ||
459 | ptimer_set_freq(ptimer, 500); | |
460 | ptimer_set_limit(ptimer, 8, 1); | |
461 | ptimer_run(ptimer, 1); | |
462 | ||
463 | qemu_clock_step(2000000 * 4 + 1); | |
464 | ||
465 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3); | |
466 | g_assert_false(triggered); | |
467 | ||
468 | ptimer_set_freq(ptimer, 250); | |
469 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 4 : 3); | |
470 | ||
471 | qemu_clock_step(2000000 * 4 + 1); | |
472 | ||
473 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 2 : 0); | |
474 | g_assert_false(triggered); | |
475 | ||
476 | qemu_clock_step(2000000 * 4); | |
477 | ||
478 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
479 | g_assert_true(triggered); | |
480 | ptimer_free(ptimer); | |
481 | } | |
482 | ||
483 | static void check_run_with_period_0(gconstpointer arg) | |
484 | { | |
485 | const uint8_t *policy = arg; | |
486 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
487 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
488 | ||
489 | triggered = false; | |
490 | ||
491 | ptimer_set_count(ptimer, 99); | |
492 | ptimer_run(ptimer, 1); | |
493 | ||
494 | qemu_clock_step(10 * NANOSECONDS_PER_SECOND); | |
495 | ||
496 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 99); | |
497 | g_assert_false(triggered); | |
498 | ptimer_free(ptimer); | |
499 | } | |
500 | ||
501 | static void check_run_with_delta_0(gconstpointer arg) | |
502 | { | |
503 | const uint8_t *policy = arg; | |
504 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
505 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
506 | bool wrap_policy = (*policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD); | |
507 | bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER); | |
508 | bool no_immediate_reload = (*policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD); | |
509 | bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN); | |
510 | bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT); | |
511 | ||
512 | triggered = false; | |
513 | ||
514 | ptimer_set_period(ptimer, 2000000); | |
515 | ptimer_set_limit(ptimer, 99, 0); | |
516 | ptimer_run(ptimer, 1); | |
517 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
518 | no_immediate_reload ? 0 : 99); | |
519 | ||
520 | if (no_immediate_trigger || trig_only_on_dec) { | |
521 | g_assert_false(triggered); | |
522 | } else { | |
523 | g_assert_true(triggered); | |
524 | } | |
525 | ||
526 | triggered = false; | |
527 | ||
528 | if (no_immediate_trigger || no_immediate_reload) { | |
529 | qemu_clock_step(2000000 + 1); | |
530 | ||
531 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
532 | no_immediate_reload ? 0 : (no_round_down ? 98 : 97)); | |
533 | ||
534 | if (no_immediate_trigger && no_immediate_reload) { | |
535 | g_assert_true(triggered); | |
536 | ||
537 | triggered = false; | |
538 | } else { | |
539 | g_assert_false(triggered); | |
540 | } | |
541 | ||
542 | ptimer_set_count(ptimer, 99); | |
543 | ptimer_run(ptimer, 1); | |
544 | } | |
545 | ||
546 | qemu_clock_step(2000000 + 1); | |
547 | ||
548 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 98 : 97); | |
549 | g_assert_false(triggered); | |
550 | ||
551 | qemu_clock_step(2000000 * 97); | |
552 | ||
553 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 1 : 0); | |
554 | g_assert_false(triggered); | |
555 | ||
556 | qemu_clock_step(2000000 * 2); | |
557 | ||
558 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
559 | g_assert_true(triggered); | |
560 | ||
561 | triggered = false; | |
562 | ||
563 | ptimer_set_count(ptimer, 0); | |
564 | ptimer_run(ptimer, 0); | |
565 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
566 | no_immediate_reload ? 0 : 99); | |
567 | ||
568 | if (no_immediate_trigger || trig_only_on_dec) { | |
569 | g_assert_false(triggered); | |
570 | } else { | |
571 | g_assert_true(triggered); | |
572 | } | |
573 | ||
574 | triggered = false; | |
575 | ||
576 | qemu_clock_step(1); | |
577 | ||
578 | if (no_immediate_reload) { | |
579 | qemu_clock_step(2000000); | |
580 | } | |
581 | ||
582 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 99 : 98); | |
583 | ||
584 | if (no_immediate_reload && no_immediate_trigger) { | |
585 | g_assert_true(triggered); | |
586 | } else { | |
587 | g_assert_false(triggered); | |
588 | } | |
589 | ||
590 | triggered = false; | |
591 | ||
592 | qemu_clock_step(2000000); | |
593 | ||
594 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 98 : 97); | |
595 | g_assert_false(triggered); | |
596 | ||
597 | qemu_clock_step(2000000 * 98); | |
598 | ||
599 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, | |
600 | wrap_policy ? 0 : (no_round_down ? 99 : 98)); | |
601 | g_assert_true(triggered); | |
602 | ||
603 | ptimer_stop(ptimer); | |
604 | ptimer_free(ptimer); | |
605 | } | |
606 | ||
607 | static void check_periodic_with_load_0(gconstpointer arg) | |
608 | { | |
609 | const uint8_t *policy = arg; | |
610 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
611 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
612 | bool continuous_trigger = (*policy & PTIMER_POLICY_CONTINUOUS_TRIGGER); | |
613 | bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER); | |
614 | bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT); | |
615 | ||
616 | triggered = false; | |
617 | ||
618 | ptimer_set_period(ptimer, 2000000); | |
619 | ptimer_run(ptimer, 0); | |
620 | ||
621 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
622 | ||
623 | if (no_immediate_trigger || trig_only_on_dec) { | |
624 | g_assert_false(triggered); | |
625 | } else { | |
626 | g_assert_true(triggered); | |
627 | } | |
628 | ||
629 | triggered = false; | |
630 | ||
631 | qemu_clock_step(2000000 + 1); | |
632 | ||
633 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
634 | ||
635 | if (continuous_trigger || no_immediate_trigger) { | |
636 | g_assert_true(triggered); | |
637 | } else { | |
638 | g_assert_false(triggered); | |
639 | } | |
640 | ||
641 | triggered = false; | |
642 | ||
643 | ptimer_set_count(ptimer, 10); | |
644 | ptimer_run(ptimer, 0); | |
645 | ||
646 | qemu_clock_step(2000000 * 10 + 1); | |
647 | ||
648 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
649 | g_assert_true(triggered); | |
650 | ||
651 | triggered = false; | |
652 | ||
653 | qemu_clock_step(2000000 + 1); | |
654 | ||
655 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
656 | ||
657 | if (continuous_trigger) { | |
658 | g_assert_true(triggered); | |
659 | } else { | |
660 | g_assert_false(triggered); | |
661 | } | |
662 | ||
663 | ptimer_stop(ptimer); | |
664 | ptimer_free(ptimer); | |
665 | } | |
666 | ||
667 | static void check_oneshot_with_load_0(gconstpointer arg) | |
668 | { | |
669 | const uint8_t *policy = arg; | |
670 | QEMUBH *bh = qemu_bh_new(ptimer_trigger, NULL); | |
671 | ptimer_state *ptimer = ptimer_init(bh, *policy); | |
672 | bool no_immediate_trigger = (*policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER); | |
673 | bool trig_only_on_dec = (*policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT); | |
674 | ||
675 | triggered = false; | |
676 | ||
677 | ptimer_set_period(ptimer, 2000000); | |
678 | ptimer_run(ptimer, 1); | |
679 | ||
680 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
681 | ||
682 | if (no_immediate_trigger || trig_only_on_dec) { | |
683 | g_assert_false(triggered); | |
684 | } else { | |
685 | g_assert_true(triggered); | |
686 | } | |
687 | ||
688 | triggered = false; | |
689 | ||
690 | qemu_clock_step(2000000 + 1); | |
691 | ||
692 | g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0); | |
693 | ||
694 | if (no_immediate_trigger) { | |
695 | g_assert_true(triggered); | |
696 | } else { | |
697 | g_assert_false(triggered); | |
698 | } | |
699 | ||
700 | ptimer_free(ptimer); | |
701 | } | |
702 | ||
703 | static void add_ptimer_tests(uint8_t policy) | |
704 | { | |
705 | char policy_name[256] = ""; | |
706 | char *tmp; | |
707 | ||
708 | if (policy == PTIMER_POLICY_DEFAULT) { | |
709 | g_sprintf(policy_name, "default"); | |
710 | } | |
711 | ||
712 | if (policy & PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD) { | |
713 | g_strlcat(policy_name, "wrap_after_one_period,", 256); | |
714 | } | |
715 | ||
716 | if (policy & PTIMER_POLICY_CONTINUOUS_TRIGGER) { | |
717 | g_strlcat(policy_name, "continuous_trigger,", 256); | |
718 | } | |
719 | ||
720 | if (policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER) { | |
721 | g_strlcat(policy_name, "no_immediate_trigger,", 256); | |
722 | } | |
723 | ||
724 | if (policy & PTIMER_POLICY_NO_IMMEDIATE_RELOAD) { | |
725 | g_strlcat(policy_name, "no_immediate_reload,", 256); | |
726 | } | |
727 | ||
728 | if (policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN) { | |
729 | g_strlcat(policy_name, "no_counter_rounddown,", 256); | |
730 | } | |
731 | ||
732 | if (policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT) { | |
733 | g_strlcat(policy_name, "trigger_only_on_decrement,", 256); | |
734 | } | |
735 | ||
736 | g_test_add_data_func_full( | |
737 | tmp = g_strdup_printf("/ptimer/set_count policy=%s", policy_name), | |
738 | g_memdup(&policy, 1), check_set_count, g_free); | |
739 | g_free(tmp); | |
740 | ||
741 | g_test_add_data_func_full( | |
742 | tmp = g_strdup_printf("/ptimer/set_limit policy=%s", policy_name), | |
743 | g_memdup(&policy, 1), check_set_limit, g_free); | |
744 | g_free(tmp); | |
745 | ||
746 | g_test_add_data_func_full( | |
747 | tmp = g_strdup_printf("/ptimer/oneshot policy=%s", policy_name), | |
748 | g_memdup(&policy, 1), check_oneshot, g_free); | |
749 | g_free(tmp); | |
750 | ||
751 | g_test_add_data_func_full( | |
752 | tmp = g_strdup_printf("/ptimer/periodic policy=%s", policy_name), | |
753 | g_memdup(&policy, 1), check_periodic, g_free); | |
754 | g_free(tmp); | |
755 | ||
756 | g_test_add_data_func_full( | |
757 | tmp = g_strdup_printf("/ptimer/on_the_fly_mode_change policy=%s", | |
758 | policy_name), | |
759 | g_memdup(&policy, 1), check_on_the_fly_mode_change, g_free); | |
760 | g_free(tmp); | |
761 | ||
762 | g_test_add_data_func_full( | |
763 | tmp = g_strdup_printf("/ptimer/on_the_fly_period_change policy=%s", | |
764 | policy_name), | |
765 | g_memdup(&policy, 1), check_on_the_fly_period_change, g_free); | |
766 | g_free(tmp); | |
767 | ||
768 | g_test_add_data_func_full( | |
769 | tmp = g_strdup_printf("/ptimer/on_the_fly_freq_change policy=%s", | |
770 | policy_name), | |
771 | g_memdup(&policy, 1), check_on_the_fly_freq_change, g_free); | |
772 | g_free(tmp); | |
773 | ||
774 | g_test_add_data_func_full( | |
775 | tmp = g_strdup_printf("/ptimer/run_with_period_0 policy=%s", | |
776 | policy_name), | |
777 | g_memdup(&policy, 1), check_run_with_period_0, g_free); | |
778 | g_free(tmp); | |
779 | ||
780 | g_test_add_data_func_full( | |
781 | tmp = g_strdup_printf("/ptimer/run_with_delta_0 policy=%s", | |
782 | policy_name), | |
783 | g_memdup(&policy, 1), check_run_with_delta_0, g_free); | |
784 | g_free(tmp); | |
785 | ||
786 | g_test_add_data_func_full( | |
787 | tmp = g_strdup_printf("/ptimer/periodic_with_load_0 policy=%s", | |
788 | policy_name), | |
789 | g_memdup(&policy, 1), check_periodic_with_load_0, g_free); | |
790 | g_free(tmp); | |
791 | ||
792 | g_test_add_data_func_full( | |
793 | tmp = g_strdup_printf("/ptimer/oneshot_with_load_0 policy=%s", | |
794 | policy_name), | |
795 | g_memdup(&policy, 1), check_oneshot_with_load_0, g_free); | |
796 | g_free(tmp); | |
797 | } | |
798 | ||
799 | static void add_all_ptimer_policies_comb_tests(void) | |
800 | { | |
801 | int last_policy = PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT; | |
802 | int policy = PTIMER_POLICY_DEFAULT; | |
803 | ||
804 | for (; policy < (last_policy << 1); policy++) { | |
805 | if ((policy & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT) && | |
806 | (policy & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)) { | |
807 | /* Incompatible policy flag settings -- don't try to test them */ | |
808 | continue; | |
809 | } | |
810 | add_ptimer_tests(policy); | |
811 | } | |
812 | } | |
813 | ||
814 | int main(int argc, char **argv) | |
815 | { | |
816 | int i; | |
817 | ||
818 | g_test_init(&argc, &argv, NULL); | |
819 | ||
820 | for (i = 0; i < QEMU_CLOCK_MAX; i++) { | |
821 | main_loop_tlg.tl[i] = g_new0(QEMUTimerList, 1); | |
822 | } | |
823 | ||
824 | add_all_ptimer_policies_comb_tests(); | |
825 | ||
826 | qtest_allowed = true; | |
827 | ||
828 | return g_test_run(); | |
829 | } |