qemu/tests/unit/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 "ptimer-test.h"
  18
  19static bool triggered;
  20
  21static void ptimer_trigger(void *opaque)
  22{
  23    triggered = true;
  24}
  25
  26static 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
  45static void ptimer_test_set_qemu_time_ns(int64_t ns)
  46{
  47    ptimer_test_time_ns = ns;
  48}
  49
  50static 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
  66static 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
  81static 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
 104static 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
 222static 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
 408static 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
 460static 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
 496static 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
 532static 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
 551static 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
 664static 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
 729static 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
 766static 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
 862static 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
 877int 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