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