spice-gtk/tests/coroutine.c
Frediano Ziglio 9def63a7a4 coroutine_gthread: Fix recursive yield
Signed-off-by: Frediano Ziglio <freddy77@gmail.com>
Acked-by: Marc-André Lureau <marcandre.lureau@redhat.com>
2020-08-12 16:17:15 +01:00

165 lines
3.9 KiB
C

#include <glib.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "coroutine.h"
static gpointer co_entry_check_self(gpointer data)
{
g_assert(data == coroutine_self());
g_assert(!coroutine_self_is_main());
return NULL;
}
static gpointer co_entry_42(gpointer data)
{
g_assert(GPOINTER_TO_INT(data) == 42);
g_assert(!coroutine_self_is_main());
return GINT_TO_POINTER(0x42);
}
static void test_coroutine_simple(void)
{
struct coroutine *self = coroutine_self();
struct coroutine co = {
.stack_size = 16 << 20,
.entry = co_entry_42,
};
gpointer result;
g_assert(coroutine_self_is_main());
coroutine_init(&co);
result = coroutine_yieldto(&co, GINT_TO_POINTER(42));
g_assert_cmpint(GPOINTER_TO_INT(result), ==, 0x42);
g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*!to->exited*");
coroutine_yieldto(&co, GINT_TO_POINTER(42));
g_test_assert_expected_messages();
g_assert(self == coroutine_self());
g_assert(coroutine_self_is_main());
}
static gpointer co_entry_two(gpointer data G_GNUC_UNUSED)
{
struct coroutine *self = coroutine_self();
struct coroutine co = {
.stack_size = 16 << 20,
.entry = co_entry_check_self,
};
g_assert(!coroutine_self_is_main());
coroutine_init(&co);
coroutine_yieldto(&co, &co);
g_assert(self == coroutine_self());
return NULL;
}
static void test_coroutine_two(void)
{
struct coroutine *self = coroutine_self();
struct coroutine co = {
.stack_size = 16 << 20,
.entry = co_entry_two,
};
coroutine_init(&co);
coroutine_yieldto(&co, NULL);
g_assert(self == coroutine_self());
}
static gpointer co_entry_yield2(gpointer data)
{
struct coroutine *self = coroutine_self();
gpointer val;
g_assert(data == GINT_TO_POINTER(12));
val = coroutine_yield(GINT_TO_POINTER(23));
g_assert_cmpint(GPOINTER_TO_INT(val), ==, 34);
g_assert(self == coroutine_self());
g_assert(!coroutine_self_is_main());
return NULL;
}
static gpointer co_entry_yield(gpointer data)
{
struct coroutine *self = coroutine_self();
struct coroutine co = {
.stack_size = 1 << 20,
.entry = co_entry_yield2,
};
gpointer val;
coroutine_init(&co);
val = coroutine_yieldto(&co, GINT_TO_POINTER(12));
g_assert(self == coroutine_self());
g_assert_cmpint(GPOINTER_TO_INT(val), ==, 23);
coroutine_yieldto(&co, GINT_TO_POINTER(34));
g_assert(self == coroutine_self());
g_assert(data == NULL);
val = coroutine_yield(GINT_TO_POINTER(1));
g_assert_cmpint(GPOINTER_TO_INT(val), ==, 2);
g_assert(self == coroutine_self());
g_assert(!coroutine_self_is_main());
val = coroutine_yield(GINT_TO_POINTER(3));
g_assert_cmpint(GPOINTER_TO_INT(val), ==, 4);
g_assert(self == coroutine_self());
return NULL;
}
static void test_coroutine_yield(void)
{
struct coroutine *self = coroutine_self();
struct coroutine co = {
.stack_size = 16 << 20,
.entry = co_entry_yield,
};
gpointer val;
coroutine_init(&co);
val = coroutine_yieldto(&co, NULL);
g_assert(self == coroutine_self());
g_assert_cmpint(GPOINTER_TO_INT(val), ==, 1);
val = coroutine_yieldto(&co, GINT_TO_POINTER(2));
g_assert(self == coroutine_self());
g_assert_cmpint(GPOINTER_TO_INT(val), ==, 3);
val = coroutine_yieldto(&co, GINT_TO_POINTER(4));
g_assert(self == coroutine_self());
g_assert(val == NULL);
g_test_expect_message(G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, "*!to->exited*");
coroutine_yieldto(&co, GINT_TO_POINTER(42));
g_test_assert_expected_messages();
}
int main(int argc, char* argv[])
{
g_test_init(&argc, &argv, NULL);
g_test_add_func("/coroutine/simple", test_coroutine_simple);
g_test_add_func("/coroutine/two", test_coroutine_two);
g_test_add_func("/coroutine/yield", test_coroutine_yield);
return g_test_run ();
}