summaryrefslogtreecommitdiff
path: root/libcr_ipc/tests/test_select.c
blob: 1db645b4f30bc78fe6cd34680268b297bfa3d131 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/* 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 cr_consumer(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;
	args[0] = CR_SELECT_SEND(&fch, &send);
	args[1] = CR_SELECT_DEFAULT;
	ret_arg = cr_select_v(2, args);
	test_assert(ret_arg == 1);

	cr_end();
}

COROUTINE cr_producer(void *_n) {
	int n = *(int *)_n;
	cr_begin();

	intchan_send(&ch[n], n);

	cr_end();
}

COROUTINE cr_final(void *) {
	cr_begin();

	int ret = intchan_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", cr_producer, &i);
	coroutine_add("consumer", cr_consumer, NULL);
	coroutine_add("final", cr_final, NULL);
	coroutine_main();
	return 0;
}