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