qemu/tests/test-aio.c
<<
>>
Prefs
   1/*
   2 * AioContext tests
   3 *
   4 * Copyright Red Hat, Inc. 2012
   5 *
   6 * Authors:
   7 *  Paolo Bonzini    <pbonzini@redhat.com>
   8 *
   9 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
  10 * See the COPYING.LIB file in the top-level directory.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include <glib.h>
  15#include "block/aio.h"
  16#include "qapi/error.h"
  17#include "qemu/timer.h"
  18#include "qemu/sockets.h"
  19#include "qemu/error-report.h"
  20
  21static AioContext *ctx;
  22
  23typedef struct {
  24    EventNotifier e;
  25    int n;
  26    int active;
  27    bool auto_set;
  28} EventNotifierTestData;
  29
  30/* Wait until event notifier becomes inactive */
  31static void wait_until_inactive(EventNotifierTestData *data)
  32{
  33    while (data->active > 0) {
  34        aio_poll(ctx, true);
  35    }
  36}
  37
  38/* Simple callbacks for testing.  */
  39
  40typedef struct {
  41    QEMUBH *bh;
  42    int n;
  43    int max;
  44} BHTestData;
  45
  46typedef struct {
  47    QEMUTimer timer;
  48    QEMUClockType clock_type;
  49    int n;
  50    int max;
  51    int64_t ns;
  52    AioContext *ctx;
  53} TimerTestData;
  54
  55static void bh_test_cb(void *opaque)
  56{
  57    BHTestData *data = opaque;
  58    if (++data->n < data->max) {
  59        qemu_bh_schedule(data->bh);
  60    }
  61}
  62
  63static void timer_test_cb(void *opaque)
  64{
  65    TimerTestData *data = opaque;
  66    if (++data->n < data->max) {
  67        timer_mod(&data->timer,
  68                  qemu_clock_get_ns(data->clock_type) + data->ns);
  69    }
  70}
  71
  72static void dummy_io_handler_read(EventNotifier *e)
  73{
  74}
  75
  76static void bh_delete_cb(void *opaque)
  77{
  78    BHTestData *data = opaque;
  79    if (++data->n < data->max) {
  80        qemu_bh_schedule(data->bh);
  81    } else {
  82        qemu_bh_delete(data->bh);
  83        data->bh = NULL;
  84    }
  85}
  86
  87static void event_ready_cb(EventNotifier *e)
  88{
  89    EventNotifierTestData *data = container_of(e, EventNotifierTestData, e);
  90    g_assert(event_notifier_test_and_clear(e));
  91    data->n++;
  92    if (data->active > 0) {
  93        data->active--;
  94    }
  95    if (data->auto_set && data->active) {
  96        event_notifier_set(e);
  97    }
  98}
  99
 100/* Tests using aio_*.  */
 101
 102typedef struct {
 103    QemuMutex start_lock;
 104    bool thread_acquired;
 105} AcquireTestData;
 106
 107static void *test_acquire_thread(void *opaque)
 108{
 109    AcquireTestData *data = opaque;
 110
 111    /* Wait for other thread to let us start */
 112    qemu_mutex_lock(&data->start_lock);
 113    qemu_mutex_unlock(&data->start_lock);
 114
 115    aio_context_acquire(ctx);
 116    aio_context_release(ctx);
 117
 118    data->thread_acquired = true; /* success, we got here */
 119
 120    return NULL;
 121}
 122
 123static void set_event_notifier(AioContext *ctx, EventNotifier *notifier,
 124                               EventNotifierHandler *handler)
 125{
 126    aio_set_event_notifier(ctx, notifier, false, handler);
 127}
 128
 129static void dummy_notifier_read(EventNotifier *unused)
 130{
 131    g_assert(false); /* should never be invoked */
 132}
 133
 134static void test_acquire(void)
 135{
 136    QemuThread thread;
 137    EventNotifier notifier;
 138    AcquireTestData data;
 139
 140    /* Dummy event notifier ensures aio_poll() will block */
 141    event_notifier_init(&notifier, false);
 142    set_event_notifier(ctx, &notifier, dummy_notifier_read);
 143    g_assert(!aio_poll(ctx, false)); /* consume aio_notify() */
 144
 145    qemu_mutex_init(&data.start_lock);
 146    qemu_mutex_lock(&data.start_lock);
 147    data.thread_acquired = false;
 148
 149    qemu_thread_create(&thread, "test_acquire_thread",
 150                       test_acquire_thread,
 151                       &data, QEMU_THREAD_JOINABLE);
 152
 153    /* Block in aio_poll(), let other thread kick us and acquire context */
 154    aio_context_acquire(ctx);
 155    qemu_mutex_unlock(&data.start_lock); /* let the thread run */
 156    g_assert(!aio_poll(ctx, true));
 157    aio_context_release(ctx);
 158
 159    qemu_thread_join(&thread);
 160    set_event_notifier(ctx, &notifier, NULL);
 161    event_notifier_cleanup(&notifier);
 162
 163    g_assert(data.thread_acquired);
 164}
 165
 166static void test_bh_schedule(void)
 167{
 168    BHTestData data = { .n = 0 };
 169    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 170
 171    qemu_bh_schedule(data.bh);
 172    g_assert_cmpint(data.n, ==, 0);
 173
 174    g_assert(aio_poll(ctx, true));
 175    g_assert_cmpint(data.n, ==, 1);
 176
 177    g_assert(!aio_poll(ctx, false));
 178    g_assert_cmpint(data.n, ==, 1);
 179    qemu_bh_delete(data.bh);
 180}
 181
 182static void test_bh_schedule10(void)
 183{
 184    BHTestData data = { .n = 0, .max = 10 };
 185    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 186
 187    qemu_bh_schedule(data.bh);
 188    g_assert_cmpint(data.n, ==, 0);
 189
 190    g_assert(aio_poll(ctx, false));
 191    g_assert_cmpint(data.n, ==, 1);
 192
 193    g_assert(aio_poll(ctx, true));
 194    g_assert_cmpint(data.n, ==, 2);
 195
 196    while (data.n < 10) {
 197        aio_poll(ctx, true);
 198    }
 199    g_assert_cmpint(data.n, ==, 10);
 200
 201    g_assert(!aio_poll(ctx, false));
 202    g_assert_cmpint(data.n, ==, 10);
 203    qemu_bh_delete(data.bh);
 204}
 205
 206static void test_bh_cancel(void)
 207{
 208    BHTestData data = { .n = 0 };
 209    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 210
 211    qemu_bh_schedule(data.bh);
 212    g_assert_cmpint(data.n, ==, 0);
 213
 214    qemu_bh_cancel(data.bh);
 215    g_assert_cmpint(data.n, ==, 0);
 216
 217    g_assert(!aio_poll(ctx, false));
 218    g_assert_cmpint(data.n, ==, 0);
 219    qemu_bh_delete(data.bh);
 220}
 221
 222static void test_bh_delete(void)
 223{
 224    BHTestData data = { .n = 0 };
 225    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 226
 227    qemu_bh_schedule(data.bh);
 228    g_assert_cmpint(data.n, ==, 0);
 229
 230    qemu_bh_delete(data.bh);
 231    g_assert_cmpint(data.n, ==, 0);
 232
 233    g_assert(!aio_poll(ctx, false));
 234    g_assert_cmpint(data.n, ==, 0);
 235}
 236
 237static void test_bh_delete_from_cb(void)
 238{
 239    BHTestData data1 = { .n = 0, .max = 1 };
 240
 241    data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
 242
 243    qemu_bh_schedule(data1.bh);
 244    g_assert_cmpint(data1.n, ==, 0);
 245
 246    while (data1.n < data1.max) {
 247        aio_poll(ctx, true);
 248    }
 249    g_assert_cmpint(data1.n, ==, data1.max);
 250    g_assert(data1.bh == NULL);
 251
 252    g_assert(!aio_poll(ctx, false));
 253}
 254
 255static void test_bh_delete_from_cb_many(void)
 256{
 257    BHTestData data1 = { .n = 0, .max = 1 };
 258    BHTestData data2 = { .n = 0, .max = 3 };
 259    BHTestData data3 = { .n = 0, .max = 2 };
 260    BHTestData data4 = { .n = 0, .max = 4 };
 261
 262    data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
 263    data2.bh = aio_bh_new(ctx, bh_delete_cb, &data2);
 264    data3.bh = aio_bh_new(ctx, bh_delete_cb, &data3);
 265    data4.bh = aio_bh_new(ctx, bh_delete_cb, &data4);
 266
 267    qemu_bh_schedule(data1.bh);
 268    qemu_bh_schedule(data2.bh);
 269    qemu_bh_schedule(data3.bh);
 270    qemu_bh_schedule(data4.bh);
 271    g_assert_cmpint(data1.n, ==, 0);
 272    g_assert_cmpint(data2.n, ==, 0);
 273    g_assert_cmpint(data3.n, ==, 0);
 274    g_assert_cmpint(data4.n, ==, 0);
 275
 276    g_assert(aio_poll(ctx, false));
 277    g_assert_cmpint(data1.n, ==, 1);
 278    g_assert_cmpint(data2.n, ==, 1);
 279    g_assert_cmpint(data3.n, ==, 1);
 280    g_assert_cmpint(data4.n, ==, 1);
 281    g_assert(data1.bh == NULL);
 282
 283    while (data1.n < data1.max ||
 284           data2.n < data2.max ||
 285           data3.n < data3.max ||
 286           data4.n < data4.max) {
 287        aio_poll(ctx, true);
 288    }
 289    g_assert_cmpint(data1.n, ==, data1.max);
 290    g_assert_cmpint(data2.n, ==, data2.max);
 291    g_assert_cmpint(data3.n, ==, data3.max);
 292    g_assert_cmpint(data4.n, ==, data4.max);
 293    g_assert(data1.bh == NULL);
 294    g_assert(data2.bh == NULL);
 295    g_assert(data3.bh == NULL);
 296    g_assert(data4.bh == NULL);
 297}
 298
 299static void test_bh_flush(void)
 300{
 301    BHTestData data = { .n = 0 };
 302    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 303
 304    qemu_bh_schedule(data.bh);
 305    g_assert_cmpint(data.n, ==, 0);
 306
 307    g_assert(aio_poll(ctx, true));
 308    g_assert_cmpint(data.n, ==, 1);
 309
 310    g_assert(!aio_poll(ctx, false));
 311    g_assert_cmpint(data.n, ==, 1);
 312    qemu_bh_delete(data.bh);
 313}
 314
 315static void test_set_event_notifier(void)
 316{
 317    EventNotifierTestData data = { .n = 0, .active = 0 };
 318    event_notifier_init(&data.e, false);
 319    set_event_notifier(ctx, &data.e, event_ready_cb);
 320    g_assert(!aio_poll(ctx, false));
 321    g_assert_cmpint(data.n, ==, 0);
 322
 323    set_event_notifier(ctx, &data.e, NULL);
 324    g_assert(!aio_poll(ctx, false));
 325    g_assert_cmpint(data.n, ==, 0);
 326    event_notifier_cleanup(&data.e);
 327}
 328
 329static void test_wait_event_notifier(void)
 330{
 331    EventNotifierTestData data = { .n = 0, .active = 1 };
 332    event_notifier_init(&data.e, false);
 333    set_event_notifier(ctx, &data.e, event_ready_cb);
 334    while (aio_poll(ctx, false));
 335    g_assert_cmpint(data.n, ==, 0);
 336    g_assert_cmpint(data.active, ==, 1);
 337
 338    event_notifier_set(&data.e);
 339    g_assert(aio_poll(ctx, false));
 340    g_assert_cmpint(data.n, ==, 1);
 341    g_assert_cmpint(data.active, ==, 0);
 342
 343    g_assert(!aio_poll(ctx, false));
 344    g_assert_cmpint(data.n, ==, 1);
 345    g_assert_cmpint(data.active, ==, 0);
 346
 347    set_event_notifier(ctx, &data.e, NULL);
 348    g_assert(!aio_poll(ctx, false));
 349    g_assert_cmpint(data.n, ==, 1);
 350
 351    event_notifier_cleanup(&data.e);
 352}
 353
 354static void test_flush_event_notifier(void)
 355{
 356    EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
 357    event_notifier_init(&data.e, false);
 358    set_event_notifier(ctx, &data.e, event_ready_cb);
 359    while (aio_poll(ctx, false));
 360    g_assert_cmpint(data.n, ==, 0);
 361    g_assert_cmpint(data.active, ==, 10);
 362
 363    event_notifier_set(&data.e);
 364    g_assert(aio_poll(ctx, false));
 365    g_assert_cmpint(data.n, ==, 1);
 366    g_assert_cmpint(data.active, ==, 9);
 367    g_assert(aio_poll(ctx, false));
 368
 369    wait_until_inactive(&data);
 370    g_assert_cmpint(data.n, ==, 10);
 371    g_assert_cmpint(data.active, ==, 0);
 372    g_assert(!aio_poll(ctx, false));
 373
 374    set_event_notifier(ctx, &data.e, NULL);
 375    g_assert(!aio_poll(ctx, false));
 376    event_notifier_cleanup(&data.e);
 377}
 378
 379static void test_aio_external_client(void)
 380{
 381    int i, j;
 382
 383    for (i = 1; i < 3; i++) {
 384        EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
 385        event_notifier_init(&data.e, false);
 386        aio_set_event_notifier(ctx, &data.e, true, event_ready_cb);
 387        event_notifier_set(&data.e);
 388        for (j = 0; j < i; j++) {
 389            aio_disable_external(ctx);
 390        }
 391        for (j = 0; j < i; j++) {
 392            assert(!aio_poll(ctx, false));
 393            assert(event_notifier_test_and_clear(&data.e));
 394            event_notifier_set(&data.e);
 395            aio_enable_external(ctx);
 396        }
 397        assert(aio_poll(ctx, false));
 398        set_event_notifier(ctx, &data.e, NULL);
 399        event_notifier_cleanup(&data.e);
 400    }
 401}
 402
 403static void test_wait_event_notifier_noflush(void)
 404{
 405    EventNotifierTestData data = { .n = 0 };
 406    EventNotifierTestData dummy = { .n = 0, .active = 1 };
 407
 408    event_notifier_init(&data.e, false);
 409    set_event_notifier(ctx, &data.e, event_ready_cb);
 410
 411    g_assert(!aio_poll(ctx, false));
 412    g_assert_cmpint(data.n, ==, 0);
 413
 414    /* Until there is an active descriptor, aio_poll may or may not call
 415     * event_ready_cb.  Still, it must not block.  */
 416    event_notifier_set(&data.e);
 417    g_assert(aio_poll(ctx, true));
 418    data.n = 0;
 419
 420    /* An active event notifier forces aio_poll to look at EventNotifiers.  */
 421    event_notifier_init(&dummy.e, false);
 422    set_event_notifier(ctx, &dummy.e, event_ready_cb);
 423
 424    event_notifier_set(&data.e);
 425    g_assert(aio_poll(ctx, false));
 426    g_assert_cmpint(data.n, ==, 1);
 427    g_assert(!aio_poll(ctx, false));
 428    g_assert_cmpint(data.n, ==, 1);
 429
 430    event_notifier_set(&data.e);
 431    g_assert(aio_poll(ctx, false));
 432    g_assert_cmpint(data.n, ==, 2);
 433    g_assert(!aio_poll(ctx, false));
 434    g_assert_cmpint(data.n, ==, 2);
 435
 436    event_notifier_set(&dummy.e);
 437    wait_until_inactive(&dummy);
 438    g_assert_cmpint(data.n, ==, 2);
 439    g_assert_cmpint(dummy.n, ==, 1);
 440    g_assert_cmpint(dummy.active, ==, 0);
 441
 442    set_event_notifier(ctx, &dummy.e, NULL);
 443    event_notifier_cleanup(&dummy.e);
 444
 445    set_event_notifier(ctx, &data.e, NULL);
 446    g_assert(!aio_poll(ctx, false));
 447    g_assert_cmpint(data.n, ==, 2);
 448
 449    event_notifier_cleanup(&data.e);
 450}
 451
 452static void test_timer_schedule(void)
 453{
 454    TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
 455                           .max = 2,
 456                           .clock_type = QEMU_CLOCK_VIRTUAL };
 457    EventNotifier e;
 458
 459    /* aio_poll will not block to wait for timers to complete unless it has
 460     * an fd to wait on. Fixing this breaks other tests. So create a dummy one.
 461     */
 462    event_notifier_init(&e, false);
 463    set_event_notifier(ctx, &e, dummy_io_handler_read);
 464    aio_poll(ctx, false);
 465
 466    aio_timer_init(ctx, &data.timer, data.clock_type,
 467                   SCALE_NS, timer_test_cb, &data);
 468    timer_mod(&data.timer,
 469              qemu_clock_get_ns(data.clock_type) +
 470              data.ns);
 471
 472    g_assert_cmpint(data.n, ==, 0);
 473
 474    /* timer_mod may well cause an event notifer to have gone off,
 475     * so clear that
 476     */
 477    do {} while (aio_poll(ctx, false));
 478
 479    g_assert(!aio_poll(ctx, false));
 480    g_assert_cmpint(data.n, ==, 0);
 481
 482    g_usleep(1 * G_USEC_PER_SEC);
 483    g_assert_cmpint(data.n, ==, 0);
 484
 485    g_assert(aio_poll(ctx, false));
 486    g_assert_cmpint(data.n, ==, 1);
 487
 488    /* timer_mod called by our callback */
 489    do {} while (aio_poll(ctx, false));
 490
 491    g_assert(!aio_poll(ctx, false));
 492    g_assert_cmpint(data.n, ==, 1);
 493
 494    g_assert(aio_poll(ctx, true));
 495    g_assert_cmpint(data.n, ==, 2);
 496
 497    /* As max is now 2, an event notifier should not have gone off */
 498
 499    g_assert(!aio_poll(ctx, false));
 500    g_assert_cmpint(data.n, ==, 2);
 501
 502    set_event_notifier(ctx, &e, NULL);
 503    event_notifier_cleanup(&e);
 504
 505    timer_del(&data.timer);
 506}
 507
 508/* Now the same tests, using the context as a GSource.  They are
 509 * very similar to the ones above, with g_main_context_iteration
 510 * replacing aio_poll.  However:
 511 * - sometimes both the AioContext and the glib main loop wake
 512 *   themselves up.  Hence, some "g_assert(!aio_poll(ctx, false));"
 513 *   are replaced by "while (g_main_context_iteration(NULL, false));".
 514 * - there is no exact replacement for a blocking wait.
 515 *   "while (g_main_context_iteration(NULL, true)" seems to work,
 516 *   but it is not documented _why_ it works.  For these tests a
 517 *   non-blocking loop like "while (g_main_context_iteration(NULL, false)"
 518 *   works well, and that's what I am using.
 519 */
 520
 521static void test_source_flush(void)
 522{
 523    g_assert(!g_main_context_iteration(NULL, false));
 524    aio_notify(ctx);
 525    while (g_main_context_iteration(NULL, false));
 526    g_assert(!g_main_context_iteration(NULL, false));
 527}
 528
 529static void test_source_bh_schedule(void)
 530{
 531    BHTestData data = { .n = 0 };
 532    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 533
 534    qemu_bh_schedule(data.bh);
 535    g_assert_cmpint(data.n, ==, 0);
 536
 537    g_assert(g_main_context_iteration(NULL, true));
 538    g_assert_cmpint(data.n, ==, 1);
 539
 540    g_assert(!g_main_context_iteration(NULL, false));
 541    g_assert_cmpint(data.n, ==, 1);
 542    qemu_bh_delete(data.bh);
 543}
 544
 545static void test_source_bh_schedule10(void)
 546{
 547    BHTestData data = { .n = 0, .max = 10 };
 548    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 549
 550    qemu_bh_schedule(data.bh);
 551    g_assert_cmpint(data.n, ==, 0);
 552
 553    g_assert(g_main_context_iteration(NULL, false));
 554    g_assert_cmpint(data.n, ==, 1);
 555
 556    g_assert(g_main_context_iteration(NULL, true));
 557    g_assert_cmpint(data.n, ==, 2);
 558
 559    while (g_main_context_iteration(NULL, false));
 560    g_assert_cmpint(data.n, ==, 10);
 561
 562    g_assert(!g_main_context_iteration(NULL, false));
 563    g_assert_cmpint(data.n, ==, 10);
 564    qemu_bh_delete(data.bh);
 565}
 566
 567static void test_source_bh_cancel(void)
 568{
 569    BHTestData data = { .n = 0 };
 570    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 571
 572    qemu_bh_schedule(data.bh);
 573    g_assert_cmpint(data.n, ==, 0);
 574
 575    qemu_bh_cancel(data.bh);
 576    g_assert_cmpint(data.n, ==, 0);
 577
 578    while (g_main_context_iteration(NULL, false));
 579    g_assert_cmpint(data.n, ==, 0);
 580    qemu_bh_delete(data.bh);
 581}
 582
 583static void test_source_bh_delete(void)
 584{
 585    BHTestData data = { .n = 0 };
 586    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 587
 588    qemu_bh_schedule(data.bh);
 589    g_assert_cmpint(data.n, ==, 0);
 590
 591    qemu_bh_delete(data.bh);
 592    g_assert_cmpint(data.n, ==, 0);
 593
 594    while (g_main_context_iteration(NULL, false));
 595    g_assert_cmpint(data.n, ==, 0);
 596}
 597
 598static void test_source_bh_delete_from_cb(void)
 599{
 600    BHTestData data1 = { .n = 0, .max = 1 };
 601
 602    data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
 603
 604    qemu_bh_schedule(data1.bh);
 605    g_assert_cmpint(data1.n, ==, 0);
 606
 607    g_main_context_iteration(NULL, true);
 608    g_assert_cmpint(data1.n, ==, data1.max);
 609    g_assert(data1.bh == NULL);
 610
 611    g_assert(!g_main_context_iteration(NULL, false));
 612}
 613
 614static void test_source_bh_delete_from_cb_many(void)
 615{
 616    BHTestData data1 = { .n = 0, .max = 1 };
 617    BHTestData data2 = { .n = 0, .max = 3 };
 618    BHTestData data3 = { .n = 0, .max = 2 };
 619    BHTestData data4 = { .n = 0, .max = 4 };
 620
 621    data1.bh = aio_bh_new(ctx, bh_delete_cb, &data1);
 622    data2.bh = aio_bh_new(ctx, bh_delete_cb, &data2);
 623    data3.bh = aio_bh_new(ctx, bh_delete_cb, &data3);
 624    data4.bh = aio_bh_new(ctx, bh_delete_cb, &data4);
 625
 626    qemu_bh_schedule(data1.bh);
 627    qemu_bh_schedule(data2.bh);
 628    qemu_bh_schedule(data3.bh);
 629    qemu_bh_schedule(data4.bh);
 630    g_assert_cmpint(data1.n, ==, 0);
 631    g_assert_cmpint(data2.n, ==, 0);
 632    g_assert_cmpint(data3.n, ==, 0);
 633    g_assert_cmpint(data4.n, ==, 0);
 634
 635    g_assert(g_main_context_iteration(NULL, false));
 636    g_assert_cmpint(data1.n, ==, 1);
 637    g_assert_cmpint(data2.n, ==, 1);
 638    g_assert_cmpint(data3.n, ==, 1);
 639    g_assert_cmpint(data4.n, ==, 1);
 640    g_assert(data1.bh == NULL);
 641
 642    while (g_main_context_iteration(NULL, false));
 643    g_assert_cmpint(data1.n, ==, data1.max);
 644    g_assert_cmpint(data2.n, ==, data2.max);
 645    g_assert_cmpint(data3.n, ==, data3.max);
 646    g_assert_cmpint(data4.n, ==, data4.max);
 647    g_assert(data1.bh == NULL);
 648    g_assert(data2.bh == NULL);
 649    g_assert(data3.bh == NULL);
 650    g_assert(data4.bh == NULL);
 651}
 652
 653static void test_source_bh_flush(void)
 654{
 655    BHTestData data = { .n = 0 };
 656    data.bh = aio_bh_new(ctx, bh_test_cb, &data);
 657
 658    qemu_bh_schedule(data.bh);
 659    g_assert_cmpint(data.n, ==, 0);
 660
 661    g_assert(g_main_context_iteration(NULL, true));
 662    g_assert_cmpint(data.n, ==, 1);
 663
 664    g_assert(!g_main_context_iteration(NULL, false));
 665    g_assert_cmpint(data.n, ==, 1);
 666    qemu_bh_delete(data.bh);
 667}
 668
 669static void test_source_set_event_notifier(void)
 670{
 671    EventNotifierTestData data = { .n = 0, .active = 0 };
 672    event_notifier_init(&data.e, false);
 673    set_event_notifier(ctx, &data.e, event_ready_cb);
 674    while (g_main_context_iteration(NULL, false));
 675    g_assert_cmpint(data.n, ==, 0);
 676
 677    set_event_notifier(ctx, &data.e, NULL);
 678    while (g_main_context_iteration(NULL, false));
 679    g_assert_cmpint(data.n, ==, 0);
 680    event_notifier_cleanup(&data.e);
 681}
 682
 683static void test_source_wait_event_notifier(void)
 684{
 685    EventNotifierTestData data = { .n = 0, .active = 1 };
 686    event_notifier_init(&data.e, false);
 687    set_event_notifier(ctx, &data.e, event_ready_cb);
 688    while (g_main_context_iteration(NULL, false));
 689    g_assert_cmpint(data.n, ==, 0);
 690    g_assert_cmpint(data.active, ==, 1);
 691
 692    event_notifier_set(&data.e);
 693    g_assert(g_main_context_iteration(NULL, false));
 694    g_assert_cmpint(data.n, ==, 1);
 695    g_assert_cmpint(data.active, ==, 0);
 696
 697    while (g_main_context_iteration(NULL, false));
 698    g_assert_cmpint(data.n, ==, 1);
 699    g_assert_cmpint(data.active, ==, 0);
 700
 701    set_event_notifier(ctx, &data.e, NULL);
 702    while (g_main_context_iteration(NULL, false));
 703    g_assert_cmpint(data.n, ==, 1);
 704
 705    event_notifier_cleanup(&data.e);
 706}
 707
 708static void test_source_flush_event_notifier(void)
 709{
 710    EventNotifierTestData data = { .n = 0, .active = 10, .auto_set = true };
 711    event_notifier_init(&data.e, false);
 712    set_event_notifier(ctx, &data.e, event_ready_cb);
 713    while (g_main_context_iteration(NULL, false));
 714    g_assert_cmpint(data.n, ==, 0);
 715    g_assert_cmpint(data.active, ==, 10);
 716
 717    event_notifier_set(&data.e);
 718    g_assert(g_main_context_iteration(NULL, false));
 719    g_assert_cmpint(data.n, ==, 1);
 720    g_assert_cmpint(data.active, ==, 9);
 721    g_assert(g_main_context_iteration(NULL, false));
 722
 723    while (g_main_context_iteration(NULL, false));
 724    g_assert_cmpint(data.n, ==, 10);
 725    g_assert_cmpint(data.active, ==, 0);
 726    g_assert(!g_main_context_iteration(NULL, false));
 727
 728    set_event_notifier(ctx, &data.e, NULL);
 729    while (g_main_context_iteration(NULL, false));
 730    event_notifier_cleanup(&data.e);
 731}
 732
 733static void test_source_wait_event_notifier_noflush(void)
 734{
 735    EventNotifierTestData data = { .n = 0 };
 736    EventNotifierTestData dummy = { .n = 0, .active = 1 };
 737
 738    event_notifier_init(&data.e, false);
 739    set_event_notifier(ctx, &data.e, event_ready_cb);
 740
 741    while (g_main_context_iteration(NULL, false));
 742    g_assert_cmpint(data.n, ==, 0);
 743
 744    /* Until there is an active descriptor, glib may or may not call
 745     * event_ready_cb.  Still, it must not block.  */
 746    event_notifier_set(&data.e);
 747    g_main_context_iteration(NULL, true);
 748    data.n = 0;
 749
 750    /* An active event notifier forces aio_poll to look at EventNotifiers.  */
 751    event_notifier_init(&dummy.e, false);
 752    set_event_notifier(ctx, &dummy.e, event_ready_cb);
 753
 754    event_notifier_set(&data.e);
 755    g_assert(g_main_context_iteration(NULL, false));
 756    g_assert_cmpint(data.n, ==, 1);
 757    g_assert(!g_main_context_iteration(NULL, false));
 758    g_assert_cmpint(data.n, ==, 1);
 759
 760    event_notifier_set(&data.e);
 761    g_assert(g_main_context_iteration(NULL, false));
 762    g_assert_cmpint(data.n, ==, 2);
 763    g_assert(!g_main_context_iteration(NULL, false));
 764    g_assert_cmpint(data.n, ==, 2);
 765
 766    event_notifier_set(&dummy.e);
 767    while (g_main_context_iteration(NULL, false));
 768    g_assert_cmpint(data.n, ==, 2);
 769    g_assert_cmpint(dummy.n, ==, 1);
 770    g_assert_cmpint(dummy.active, ==, 0);
 771
 772    set_event_notifier(ctx, &dummy.e, NULL);
 773    event_notifier_cleanup(&dummy.e);
 774
 775    set_event_notifier(ctx, &data.e, NULL);
 776    while (g_main_context_iteration(NULL, false));
 777    g_assert_cmpint(data.n, ==, 2);
 778
 779    event_notifier_cleanup(&data.e);
 780}
 781
 782static void test_source_timer_schedule(void)
 783{
 784    TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL,
 785                           .max = 2,
 786                           .clock_type = QEMU_CLOCK_VIRTUAL };
 787    EventNotifier e;
 788    int64_t expiry;
 789
 790    /* aio_poll will not block to wait for timers to complete unless it has
 791     * an fd to wait on. Fixing this breaks other tests. So create a dummy one.
 792     */
 793    event_notifier_init(&e, false);
 794    set_event_notifier(ctx, &e, dummy_io_handler_read);
 795    do {} while (g_main_context_iteration(NULL, false));
 796
 797    aio_timer_init(ctx, &data.timer, data.clock_type,
 798                   SCALE_NS, timer_test_cb, &data);
 799    expiry = qemu_clock_get_ns(data.clock_type) +
 800        data.ns;
 801    timer_mod(&data.timer, expiry);
 802
 803    g_assert_cmpint(data.n, ==, 0);
 804
 805    g_usleep(1 * G_USEC_PER_SEC);
 806    g_assert_cmpint(data.n, ==, 0);
 807
 808    g_assert(g_main_context_iteration(NULL, true));
 809    g_assert_cmpint(data.n, ==, 1);
 810    expiry += data.ns;
 811
 812    while (data.n < 2) {
 813        g_main_context_iteration(NULL, true);
 814    }
 815
 816    g_assert_cmpint(data.n, ==, 2);
 817    g_assert(qemu_clock_get_ns(data.clock_type) > expiry);
 818
 819    set_event_notifier(ctx, &e, NULL);
 820    event_notifier_cleanup(&e);
 821
 822    timer_del(&data.timer);
 823}
 824
 825
 826/* End of tests.  */
 827
 828int main(int argc, char **argv)
 829{
 830    Error *local_error = NULL;
 831    GSource *src;
 832
 833    init_clocks();
 834
 835    ctx = aio_context_new(&local_error);
 836    if (!ctx) {
 837        error_reportf_err(local_error, "Failed to create AIO Context: ");
 838        exit(1);
 839    }
 840    src = aio_get_g_source(ctx);
 841    g_source_attach(src, NULL);
 842    g_source_unref(src);
 843
 844    while (g_main_context_iteration(NULL, false));
 845
 846    g_test_init(&argc, &argv, NULL);
 847    g_test_add_func("/aio/acquire",                 test_acquire);
 848    g_test_add_func("/aio/bh/schedule",             test_bh_schedule);
 849    g_test_add_func("/aio/bh/schedule10",           test_bh_schedule10);
 850    g_test_add_func("/aio/bh/cancel",               test_bh_cancel);
 851    g_test_add_func("/aio/bh/delete",               test_bh_delete);
 852    g_test_add_func("/aio/bh/callback-delete/one",  test_bh_delete_from_cb);
 853    g_test_add_func("/aio/bh/callback-delete/many", test_bh_delete_from_cb_many);
 854    g_test_add_func("/aio/bh/flush",                test_bh_flush);
 855    g_test_add_func("/aio/event/add-remove",        test_set_event_notifier);
 856    g_test_add_func("/aio/event/wait",              test_wait_event_notifier);
 857    g_test_add_func("/aio/event/wait/no-flush-cb",  test_wait_event_notifier_noflush);
 858    g_test_add_func("/aio/event/flush",             test_flush_event_notifier);
 859    g_test_add_func("/aio/external-client",         test_aio_external_client);
 860    g_test_add_func("/aio/timer/schedule",          test_timer_schedule);
 861
 862    g_test_add_func("/aio-gsource/flush",                   test_source_flush);
 863    g_test_add_func("/aio-gsource/bh/schedule",             test_source_bh_schedule);
 864    g_test_add_func("/aio-gsource/bh/schedule10",           test_source_bh_schedule10);
 865    g_test_add_func("/aio-gsource/bh/cancel",               test_source_bh_cancel);
 866    g_test_add_func("/aio-gsource/bh/delete",               test_source_bh_delete);
 867    g_test_add_func("/aio-gsource/bh/callback-delete/one",  test_source_bh_delete_from_cb);
 868    g_test_add_func("/aio-gsource/bh/callback-delete/many", test_source_bh_delete_from_cb_many);
 869    g_test_add_func("/aio-gsource/bh/flush",                test_source_bh_flush);
 870    g_test_add_func("/aio-gsource/event/add-remove",        test_source_set_event_notifier);
 871    g_test_add_func("/aio-gsource/event/wait",              test_source_wait_event_notifier);
 872    g_test_add_func("/aio-gsource/event/wait/no-flush-cb",  test_source_wait_event_notifier_noflush);
 873    g_test_add_func("/aio-gsource/event/flush",             test_source_flush_event_notifier);
 874    g_test_add_func("/aio-gsource/timer/schedule",          test_source_timer_schedule);
 875    return g_test_run();
 876}
 877