summaryrefslogtreecommitdiff
path: root/libcr_ipc/tests
diff options
context:
space:
mode:
Diffstat (limited to 'libcr_ipc/tests')
-rw-r--r--libcr_ipc/tests/config.h8
-rw-r--r--libcr_ipc/tests/test_chan.c22
-rw-r--r--libcr_ipc/tests/test_mutex.c37
-rw-r--r--libcr_ipc/tests/test_rpc.c59
-rw-r--r--libcr_ipc/tests/test_rwmutex.c88
-rw-r--r--libcr_ipc/tests/test_select.c89
-rw-r--r--libcr_ipc/tests/test_sema.c76
7 files changed, 364 insertions, 15 deletions
diff --git a/libcr_ipc/tests/config.h b/libcr_ipc/tests/config.h
index e06c876..a648589 100644
--- a/libcr_ipc/tests/config.h
+++ b/libcr_ipc/tests/config.h
@@ -1,15 +1,15 @@
-/* config.h - TODO
+/* config.h - Compile-time configuration for the libcr_ipc tests
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
#ifndef _CONFIG_H_
#define _CONFIG_H_
-#define CONFIG_COROUTINE_DEFAULT_STACK_SIZE (4*1024)
+#define CONFIG_COROUTINE_STACK_SIZE_DEFAULT (8*1024)
#define CONFIG_COROUTINE_NAME_LEN 16
-#define CONFIG_COROUTINE_NUM 8
+#define CONFIG_COROUTINE_NUM 16
#define CONFIG_COROUTINE_MEASURE_STACK 1
#define CONFIG_COROUTINE_PROTECT_STACK 1
diff --git a/libcr_ipc/tests/test_chan.c b/libcr_ipc/tests/test_chan.c
index 9d6eecf..4788dd4 100644
--- a/libcr_ipc/tests/test_chan.c
+++ b/libcr_ipc/tests/test_chan.c
@@ -1,6 +1,6 @@
/* libcr_ipc/tests/test_chan.c - Tests for <libcr_ipc/chan.h>
*
- * Copyright (C) 2024 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
@@ -9,32 +9,32 @@
#include "test.h"
-CR_CHAN_DECLARE(intchan, int)
+CR_CHAN_DECLARE(intchan, int);
-COROUTINE cr_producer(void *_ch) {
+COROUTINE producer_cr(void *_ch) {
intchan_t *ch = _ch;
cr_begin();
- intchan_send(ch, 1);
+ cr_chan_send(ch, 1);
- while (!intchan_can_send(ch))
+ while (!cr_chan_can_send(ch))
cr_yield();
- intchan_send(ch, 2);
+ cr_chan_send(ch, 2);
cr_end();
}
-COROUTINE cr_consumer(void *_ch) {
+COROUTINE consumer_cr(void *_ch) {
int x;
intchan_t *ch = _ch;
cr_begin();
- x = intchan_recv(ch);
+ x = cr_chan_recv(ch);
test_assert(x == 1);
- x = intchan_recv(ch);
+ x = cr_chan_recv(ch);
test_assert(x == 2);
cr_end();
@@ -42,8 +42,8 @@ COROUTINE cr_consumer(void *_ch) {
int main() {
intchan_t ch = {0};
- coroutine_add("producer", cr_producer, &ch);
- coroutine_add("consumer", cr_consumer, &ch);
+ coroutine_add("producer", producer_cr, &ch);
+ coroutine_add("consumer", consumer_cr, &ch);
coroutine_main();
return 0;
}
diff --git a/libcr_ipc/tests/test_mutex.c b/libcr_ipc/tests/test_mutex.c
new file mode 100644
index 0000000..d08315d
--- /dev/null
+++ b/libcr_ipc/tests/test_mutex.c
@@ -0,0 +1,37 @@
+/* libcr_ipc/tests/test_mutex.c - Tests for <libcr_ipc/mutex.h>
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libcr/coroutine.h>
+#include <libcr_ipc/mutex.h>
+
+#include "test.h"
+
+int counter = 0;
+
+COROUTINE worker_cr(void *_mu) {
+ cr_mutex_t *mu = _mu;
+ cr_begin();
+
+ for (int i = 0; i < 100; i++) {
+ cr_mutex_lock(mu);
+ int a = counter;
+ cr_yield();
+ counter = a + 1;
+ cr_mutex_unlock(mu);
+ cr_yield();
+ }
+
+ cr_end();
+}
+
+int main() {
+ cr_mutex_t mu = {};
+ coroutine_add("a", worker_cr, &mu);
+ coroutine_add("b", worker_cr, &mu);
+ coroutine_main();
+ test_assert(counter == 200);
+ return 0;
+}
diff --git a/libcr_ipc/tests/test_rpc.c b/libcr_ipc/tests/test_rpc.c
new file mode 100644
index 0000000..1461450
--- /dev/null
+++ b/libcr_ipc/tests/test_rpc.c
@@ -0,0 +1,59 @@
+/* libcr_ipc/tests/test_rpc.c - Tests for <libcr_ipc/rpc.h>
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libcr/coroutine.h>
+#include <libcr_ipc/rpc.h>
+
+#include "test.h"
+
+CR_RPC_DECLARE(intrpc, int, int);
+
+/* Test that the RPC is fair, have worker1 start waiting first, and
+ * ensure that it gets the first request. */
+
+COROUTINE caller_cr(void *_ch) {
+ intrpc_t *ch = _ch;
+ cr_begin();
+
+ int resp = cr_rpc_send_req(ch, 1);
+ test_assert(resp == 2);
+
+ resp = cr_rpc_send_req(ch, 3);
+ test_assert(resp == 4);
+
+ cr_exit();
+}
+
+COROUTINE worker1_cr(void *_ch) {
+ intrpc_t *ch = _ch;
+ cr_begin();
+
+ intrpc_req_t req = cr_rpc_recv_req(ch);
+ test_assert(req.req == 1);
+ cr_rpc_send_resp(req, 2);
+
+ cr_exit();
+}
+
+COROUTINE worker2_cr(void *_ch) {
+ intrpc_t *ch = _ch;
+ cr_begin();
+
+ intrpc_req_t req = cr_rpc_recv_req(ch);
+ test_assert(req.req == 3);
+ cr_rpc_send_resp(req, 4);
+
+ cr_exit();
+}
+
+int main() {
+ intrpc_t ch = {0};
+ coroutine_add("worker1", worker1_cr, &ch);
+ coroutine_add("caller", caller_cr, &ch);
+ coroutine_add("worker2", worker2_cr, &ch);
+ coroutine_main();
+ return 0;
+}
diff --git a/libcr_ipc/tests/test_rwmutex.c b/libcr_ipc/tests/test_rwmutex.c
new file mode 100644
index 0000000..77e8c7c
--- /dev/null
+++ b/libcr_ipc/tests/test_rwmutex.c
@@ -0,0 +1,88 @@
+/* libcr_ipc/tests/test_rwmutex.c - Tests for <libcr_ipc/rwmutex.h>
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <string.h>
+
+#include <libcr/coroutine.h>
+#include <libcr_ipc/rwmutex.h>
+
+#include "test.h"
+
+cr_rwmutex_t mu = {};
+char out[10] = {0};
+size_t len = 0;
+
+COROUTINE cr1_reader(void *_mu) {
+ cr_rwmutex_t *mu = _mu;
+ cr_begin();
+
+ cr_rwmutex_rlock(mu);
+ out[len++] = 'r';
+ cr_yield();
+ cr_rwmutex_runlock(mu);
+
+ cr_end();
+}
+
+COROUTINE cr1_writer(void *_mu) {
+ cr_rwmutex_t *mu = _mu;
+ cr_begin();
+
+ cr_rwmutex_lock(mu);
+ out[len++] = 'w';
+ cr_yield();
+ cr_rwmutex_unlock(mu);
+
+ cr_end();
+}
+
+COROUTINE cr2_waiter(void *_ch) {
+ char ch = *(char *)_ch;
+ cr_begin();
+
+ cr_rwmutex_rlock(&mu);
+ out[len++] = ch;
+ cr_rwmutex_runlock(&mu);
+
+ cr_end();
+}
+
+COROUTINE cr2_init(void *) {
+ cr_begin();
+
+ char ch;
+ cr_rwmutex_lock(&mu);
+ ch = 'a'; coroutine_add("wait-a", cr2_waiter, &ch);
+ ch = 'b'; coroutine_add("wait-b", cr2_waiter, &ch);
+ cr_yield();
+ ch = 'c'; coroutine_add("wait-c", cr2_waiter, &ch);
+ cr_rwmutex_unlock(&mu);
+
+ cr_end();
+}
+
+int main() {
+ printf("== test 1 =========================================\n");
+ coroutine_add("r1", cr1_reader, &mu);
+ coroutine_add("r2", cr1_reader, &mu);
+ coroutine_add("w", cr1_writer, &mu);
+ coroutine_add("r3", cr1_reader, &mu);
+ coroutine_add("r4", cr1_reader, &mu);
+ coroutine_main();
+ test_assert(len == 5);
+ test_assert(strcmp(out, "rrwrr") == 0);
+
+ printf("== test 2 =========================================\n");
+ mu = (cr_rwmutex_t){};
+ len = 0;
+ memset(out, 0, sizeof(out));
+ coroutine_add("init", cr2_init, NULL);
+ coroutine_main();
+ test_assert(len == 3);
+ test_assert(strcmp(out, "abc") == 0);
+
+ return 0;
+}
diff --git a/libcr_ipc/tests/test_select.c b/libcr_ipc/tests/test_select.c
new file mode 100644
index 0000000..9b5d117
--- /dev/null
+++ b/libcr_ipc/tests/test_select.c
@@ -0,0 +1,89 @@
+/* libcr_ipc/tests/test_select.c - Tests for <libcr_ipc/select.h>
+ *
+ * Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libcr/coroutine.h>
+#include <libcr_ipc/chan.h>
+
+#include "test.h"
+
+CR_CHAN_DECLARE(intchan, int);
+
+intchan_t ch[10] = {0};
+intchan_t fch = {0};
+
+COROUTINE consumer_cr(void *) {
+ cr_begin();
+
+ struct cr_select_arg args[11];
+
+ bool chdone[10] = {0};
+ int arg2ch[10];
+ for (;;) {
+ int ret_ch;
+ int i_arg = 0;
+ for (int i_ch = 0; i_ch < 10; i_ch++) {
+ if (!chdone[i_ch]) {
+ args[i_arg] = CR_SELECT_RECV(&ch[i_ch], &ret_ch);
+ arg2ch[i_arg] = i_ch;
+ i_arg++;
+ }
+ }
+ if (!i_arg)
+ break;
+ args[i_arg] = CR_SELECT_DEFAULT; /* check that default doesn't trigger */
+ test_assert(i_arg <= 10);
+ int ret_arg = cr_select_v(i_arg+1, args);
+ test_assert(ret_arg < i_arg);
+ test_assert(arg2ch[ret_arg] == ret_ch);
+ chdone[ret_ch] = true;
+ }
+ int ret_ch, ret_arg;
+ args[0] = CR_SELECT_RECV(&ch[0], &ret_ch);
+ args[1] = CR_SELECT_DEFAULT;
+ ret_arg = cr_select_v(2, args);
+ test_assert(ret_arg == 1);
+
+ int send = 567;
+ args[0] = CR_SELECT_SEND(&fch, &send);
+ args[1] = CR_SELECT_DEFAULT;
+ ret_arg = cr_select_v(2, args);
+ test_assert(ret_arg == 0);
+
+ send = 890;
+ ret_arg = cr_select_l(CR_SELECT_SEND(&fch, &send),
+ CR_SELECT_DEFAULT);
+ test_assert(ret_arg == 1);
+
+ cr_end();
+}
+
+COROUTINE producer_cr(void *_n) {
+ int n = *(int *)_n;
+ cr_begin();
+
+ cr_chan_send(&ch[n], n);
+
+ cr_end();
+}
+
+COROUTINE final_cr(void *) {
+ cr_begin();
+
+ int ret = cr_chan_recv(&fch);
+ printf("ret=%d\n", ret);
+ test_assert(ret == 567);
+
+ cr_end();
+}
+
+int main() {
+ for (int i = 0; i < 10; i++)
+ coroutine_add("producer", producer_cr, &i);
+ coroutine_add("consumer", consumer_cr, NULL);
+ coroutine_add("final", final_cr, NULL);
+ coroutine_main();
+ return 0;
+}
diff --git a/libcr_ipc/tests/test_sema.c b/libcr_ipc/tests/test_sema.c
new file mode 100644
index 0000000..435c01a
--- /dev/null
+++ b/libcr_ipc/tests/test_sema.c
@@ -0,0 +1,76 @@
+/* libcr_ipc/tests/test_sema.c - Tests for <libcr_ipc/sema.h>
+ *
+ * Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+#include <libcr/coroutine.h>
+
+#define IMPLEMENTATION_FOR_LIBCR_IPC_SEMA_H YES /* so we can access .cnt */
+#include <libcr_ipc/sema.h>
+
+#include "test.h"
+
+int counter = 0;
+
+COROUTINE first_cr(void *_sema) {
+ cr_sema_t *sema = _sema;
+ cr_begin();
+
+ cr_sema_wait(sema);
+ counter++;
+ cr_sema_signal(sema);
+
+ cr_exit();
+}
+
+COROUTINE second_cr(void *_sema) {
+ cr_sema_t *sema = _sema;
+ cr_begin();
+
+ cr_sema_signal(sema); /* should be claimed by cr_first, which has been waiting */
+ cr_sema_wait(sema); /* should block, because cr_first claimed it */
+ test_assert(counter == 1);
+
+ cr_exit();
+}
+
+COROUTINE producer_cr(void *_sema) {
+ cr_sema_t *sema = _sema;
+ cr_begin();
+
+ for (int i = 0; i < 10; i++)
+ cr_sema_signal(sema);
+
+ cr_end();
+}
+
+COROUTINE consumer_cr(void *_sema) {
+ cr_sema_t *sema = _sema;
+ cr_begin();
+
+ for (int i = 0; i < 5; i++)
+ cr_sema_wait(sema);
+
+ cr_end();
+}
+
+int main() {
+ cr_sema_t sema = {};
+
+ printf("== test 1 =========================================\n");
+ coroutine_add("first", first_cr, &sema);
+ coroutine_add("second", second_cr, &sema);
+ coroutine_main();
+ test_assert(sema.cnt == 0);
+
+ printf("== test 2 =========================================\n");
+ coroutine_add("consumer", consumer_cr, &sema);
+ coroutine_add("producer", producer_cr, &sema);
+ coroutine_main();
+ coroutine_add("consumer", consumer_cr, &sema);
+ coroutine_main();
+ test_assert(sema.cnt == 0);
+
+ return 0;
+}