diff --git a/test/test-loop.c b/test/test-loop.c index 9b360fc7b..89e2d063a 100644 --- a/test/test-loop.c +++ b/test/test-loop.c @@ -280,12 +280,93 @@ PWTEST(destroy_managed_source_before_dispatch) return PWTEST_PASS; } +struct dmsbd_recurse_data { + struct pw_loop *l; + struct pw_main_loop *ml; + struct spa_source *a, *b; + struct spa_hook hook; + bool first; +}; + +static void dmsbd_recurse_on_event(void *data, int fd, uint32_t mask) +{ + struct dmsbd_recurse_data *d = data; + + pwtest_errno_ok(read(fd, &(uint64_t){0}, sizeof(uint64_t))); + + pw_loop_enter(d->l); + pw_loop_iterate(d->l, 0); + pw_loop_leave(d->l); + + pw_main_loop_quit(d->ml); +} + +static void dmswp_recurse_before(void *data) +{ + struct dmsbd_recurse_data *d = data; + + if (d->first) { + pwtest_errno_ok(write(d->a->fd, &(uint64_t){1}, sizeof(uint64_t))); + pwtest_errno_ok(write(d->b->fd, &(uint64_t){1}, sizeof(uint64_t))); + } +} + +static void dmsbd_recurse_after(void *data) +{ + struct dmsbd_recurse_data *d = data; + + if (d->first) { + pw_loop_destroy_source(d->l, d->b); + + d->first = false; + } +} + +static const struct spa_loop_control_hooks dmsbd_recurse_hooks = { + SPA_VERSION_LOOP_CONTROL_HOOKS, + .before = dmswp_recurse_before, + .after = dmsbd_recurse_after, +}; + +PWTEST(destroy_managed_source_before_dispatch_recurse) +{ + pw_init(NULL, NULL); + + struct dmsbd_recurse_data data = { + .first = true, + }; + + data.ml = pw_main_loop_new(NULL); + pwtest_ptr_notnull(data.ml); + + data.l = pw_main_loop_get_loop(data.ml); + pwtest_ptr_notnull(data.l); + + data.l = pw_main_loop_get_loop(data.ml); + pwtest_ptr_notnull(data.l); + + data.a = pw_loop_add_io(data.l, eventfd(0, 0), SPA_IO_IN, true, dmsbd_recurse_on_event, &data); + data.b = pw_loop_add_io(data.l, eventfd(0, 0), SPA_IO_IN, true, on_event_fail_if_called, NULL); + pwtest_ptr_notnull(data.a); + pwtest_ptr_notnull(data.b); + + pw_loop_add_hook(data.l, &data.hook, &dmsbd_recurse_hooks, &data); + + pw_main_loop_run(data.ml); + pw_main_loop_destroy(data.ml); + + pw_deinit(); + + return PWTEST_PASS; +} + PWTEST_SUITE(support) { pwtest_add(pwtest_loop_destroy2, PWTEST_NOARG); pwtest_add(pwtest_loop_recurse1, PWTEST_NOARG); pwtest_add(pwtest_loop_recurse2, PWTEST_NOARG); pwtest_add(destroy_managed_source_before_dispatch, PWTEST_NOARG); + pwtest_add(destroy_managed_source_before_dispatch_recurse, PWTEST_NOARG); return PWTEST_PASS; }