From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56290) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V6dO1-0002Kf-5J for qemu-devel@nongnu.org; Tue, 06 Aug 2013 05:17:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V6dNz-0006MX-CT for qemu-devel@nongnu.org; Tue, 06 Aug 2013 05:17:01 -0400 Received: from mail.avalus.com ([2001:41c8:10:1dd::10]:57997) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V6dNz-0006ME-2b for qemu-devel@nongnu.org; Tue, 06 Aug 2013 05:16:59 -0400 From: Alex Bligh Date: Tue, 6 Aug 2013 10:16:32 +0100 Message-Id: <1375780592-22842-17-git-send-email-alex@alex.org.uk> In-Reply-To: <1375780592-22842-1-git-send-email-alex@alex.org.uk> References: <1375639805-1943-1-git-send-email-alex@alex.org.uk> <1375780592-22842-1-git-send-email-alex@alex.org.uk> Subject: [Qemu-devel] [RFC] [PATCHv6 16/16] aio / timers: Add test harness for AioContext timers List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , Anthony Liguori , Alex Bligh , liu ping fan , Stefan Hajnoczi , Paolo Bonzini , MORITA Kazutaka , rth@twiddle.net Add a test harness for AioContext timers. The g_source equivalent is unsatisfactory as it suffers from false wakeups. Signed-off-by: Alex Bligh --- tests/test-aio.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/tests/test-aio.c b/tests/test-aio.c index eedf7f8..8e2fa97 100644 --- a/tests/test-aio.c +++ b/tests/test-aio.c @@ -32,6 +32,15 @@ typedef struct { int max; } BHTestData; +typedef struct { + QEMUTimer *timer; + QEMUTimerList *tl; + int n; + int max; + int64_t ns; + AioContext *ctx; +} TimerTestData; + static void bh_test_cb(void *opaque) { BHTestData *data = opaque; @@ -40,6 +49,25 @@ static void bh_test_cb(void *opaque) } } +static void timer_test_cb(void *opaque) +{ + TimerTestData *data = opaque; + if (++data->n < data->max) { + qemu_mod_timer(data->timer, + qemu_get_clock_ns(timerlist_get_clock(data->tl)) + + data->ns); + } +} + +static void dummy_io_handler_read(void *opaque) +{ +} + +static int dummy_io_handler_flush(void *opaque) +{ + return 1; +} + static void bh_delete_cb(void *opaque) { BHTestData *data = opaque; @@ -341,6 +369,63 @@ static void test_wait_event_notifier_noflush(void) event_notifier_cleanup(&data.e); } +static void test_timer_schedule(void) +{ + TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL, + .max = 2, .tl = ctx->tlg[QEMU_CLOCK_VIRTUAL] }; + int pipefd[2]; + + /* aio_poll will not block to wait for timers to complete unless it has + * an fd to wait on. Fixing this breaks other tests. So create a dummy one. + */ + g_assert(!pipe2(pipefd, O_NONBLOCK)); + aio_set_fd_handler(ctx, pipefd[0], + dummy_io_handler_read, NULL, dummy_io_handler_flush, + NULL); + aio_poll(ctx, false); + + data.timer = timer_new(data.tl, SCALE_NS, timer_test_cb, &data); + qemu_mod_timer(data.timer, + qemu_get_clock_ns(timerlist_get_clock(data.tl)) + + data.ns); + + g_assert_cmpint(data.n, ==, 0); + + /* qemu_mod_timer may well cause an event notifer to have gone off, + * so clear that + */ + do {} while (aio_poll(ctx, false)); + + g_assert(!aio_poll(ctx, false)); + g_assert_cmpint(data.n, ==, 0); + + sleep(1); + g_assert_cmpint(data.n, ==, 0); + + g_assert(aio_poll(ctx, false)); + g_assert_cmpint(data.n, ==, 1); + + /* qemu_mod_timer called by our callback */ + do {} while (aio_poll(ctx, false)); + + g_assert(!aio_poll(ctx, false)); + g_assert_cmpint(data.n, ==, 1); + + g_assert(aio_poll(ctx, true)); + g_assert_cmpint(data.n, ==, 2); + + /* As max is now 2, an event notifier should not have gone off */ + + g_assert(!aio_poll(ctx, false)); + g_assert_cmpint(data.n, ==, 2); + + aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL, NULL); + close(pipefd[0]); + close(pipefd[1]); + + qemu_del_timer(data.timer); +} + /* Now the same tests, using the context as a GSource. They are * very similar to the ones above, with g_main_context_iteration * replacing aio_poll. However: @@ -623,6 +708,53 @@ static void test_source_wait_event_notifier_noflush(void) event_notifier_cleanup(&data.e); } +static void test_source_timer_schedule(void) +{ + TimerTestData data = { .n = 0, .ctx = ctx, .ns = SCALE_MS * 750LL, + .max = 2, .tl = ctx->tlg[QEMU_CLOCK_VIRTUAL] }; + int pipefd[2]; + int64_t expiry; + + /* aio_poll will not block to wait for timers to complete unless it has + * an fd to wait on. Fixing this breaks other tests. So create a dummy one. + */ + g_assert(!pipe2(pipefd, O_NONBLOCK)); + aio_set_fd_handler(ctx, pipefd[0], + dummy_io_handler_read, NULL, dummy_io_handler_flush, + NULL); + do {} while (g_main_context_iteration(NULL, false)); + + data.timer = timer_new(data.tl, SCALE_NS, timer_test_cb, &data); + expiry = qemu_get_clock_ns(timerlist_get_clock(data.tl)) + + data.ns; + qemu_mod_timer(data.timer, expiry); + + g_assert_cmpint(data.n, ==, 0); + + sleep(1); + g_assert_cmpint(data.n, ==, 0); + + g_assert(g_main_context_iteration(NULL, false)); + g_assert_cmpint(data.n, ==, 1); + + /* The comment above was not kidding when it said this wakes up itself */ + do { + g_assert(g_main_context_iteration(NULL, true)); + } while (qemu_get_clock_ns( + timerlist_get_clock(data.tl)) <= expiry); + sleep(1); + g_main_context_iteration(NULL, false); + + g_assert_cmpint(data.n, ==, 2); + + aio_set_fd_handler(ctx, pipefd[0], NULL, NULL, NULL, NULL); + close(pipefd[0]); + close(pipefd[1]); + + qemu_del_timer(data.timer); +} + + /* End of tests. */ int main(int argc, char **argv) @@ -651,6 +783,7 @@ int main(int argc, char **argv) g_test_add_func("/aio/event/wait", test_wait_event_notifier); g_test_add_func("/aio/event/wait/no-flush-cb", test_wait_event_notifier_noflush); g_test_add_func("/aio/event/flush", test_flush_event_notifier); + g_test_add_func("/aio/timer/schedule", test_timer_schedule); g_test_add_func("/aio-gsource/notify", test_source_notify); g_test_add_func("/aio-gsource/flush", test_source_flush); @@ -665,5 +798,6 @@ int main(int argc, char **argv) g_test_add_func("/aio-gsource/event/wait", test_source_wait_event_notifier); g_test_add_func("/aio-gsource/event/wait/no-flush-cb", test_source_wait_event_notifier_noflush); g_test_add_func("/aio-gsource/event/flush", test_source_flush_event_notifier); + g_test_add_func("/aio-gsource/timer/schedule", test_source_timer_schedule); return g_test_run(); } -- 1.7.9.5