]> git.ozlabs.org Git - ccan/blob - ccan/coroutine/test/api-2.c
coroutine: New module
[ccan] / ccan / coroutine / test / api-2.c
1 #include <stdlib.h>
2
3 #include <ccan/coroutine/coroutine.h>
4 #include <ccan/tap/tap.h>
5
6 struct state {
7         struct coroutine_state c1, c2;
8         struct coroutine_state master;
9         int val;
10 };
11
12 static void f1(void *p)
13 {
14         struct state *state = (struct state *)p;
15
16         coroutine_switch(&state->c1, &state->c2);
17
18         ok(state->val == 17, "state->val == %d [expected 17]", state->val);
19         state->val = 23;
20
21         coroutine_switch(&state->c1, &state->c2);
22
23         ok(state->val == 24, "state->val == %d [expected 24]", state->val);
24
25         coroutine_switch(&state->c1, &state->c2);
26
27         ok(state->val == 26, "state->val == %d [expected 26]", state->val);
28
29         coroutine_switch(&state->c1, &state->c2);
30
31         ok(state->val == 29, "state->val == %d [expected 29]", state->val);
32
33         coroutine_switch(&state->c1, &state->c2);
34 }
35
36 static void f2(void *p)
37 {
38         struct state *state = (struct state *)p;
39
40         state->val = 17;
41
42         coroutine_switch(&state->c2, &state->c1);
43
44         ok(state->val == 23, "state->val == %d [expected 23]", state->val);
45         state->val += 1;
46
47         coroutine_switch(&state->c2, &state->c1);
48
49         state->val += 2;
50
51         coroutine_switch(&state->c2, &state->c1);
52
53         state->val += 3;
54
55         coroutine_switch(&state->c2, &state->c1);
56
57         coroutine_jump(&state->master);
58 }
59
60 static void test1(size_t bufsz)
61 {
62         void *buf1, *buf2;
63         struct coroutine_stack *stack1, *stack2;
64
65         buf1 = malloc(bufsz);
66         ok1(buf1 != NULL);
67         stack1 = coroutine_stack_init(buf1, bufsz, 0);
68         diag("buf1=%p stack1=%p bufsz=0x%zx overhead=0x%zx\n",
69              buf1, stack1, bufsz, COROUTINE_STK_OVERHEAD);
70         ok1(coroutine_stack_check(stack1, NULL) == stack1);
71         ok1(coroutine_stack_size(stack1) == bufsz - COROUTINE_STK_OVERHEAD);
72
73         buf2 = malloc(bufsz);
74         ok1(buf2 != NULL);
75         stack2 = coroutine_stack_init(buf2, bufsz, 0);
76         ok1(coroutine_stack_check(stack2, NULL) == stack2);
77         ok1(coroutine_stack_size(stack2) == bufsz - COROUTINE_STK_OVERHEAD);
78
79         if (COROUTINE_AVAILABLE) {
80                 struct state s;
81
82                 coroutine_init(&s.c1, f1, &s, stack1);
83                 coroutine_init(&s.c2, f2, &s, stack2);
84
85                 coroutine_switch(&s.master, &s.c1);
86         } else {
87                 skip(5, "Coroutines not available");
88         }
89
90         ok(1, "Completed test1");
91
92         coroutine_stack_release(stack1, 0);
93         ok1(coroutine_stack_check(stack1, NULL) == NULL);
94         free(buf1);
95         coroutine_stack_release(stack2, 0);
96         ok1(coroutine_stack_check(stack2, NULL) == NULL);
97         free(buf2);
98 }
99
100
101 int main(void)
102 {
103         /* This is how many tests you plan to run */
104         plan_tests(14);
105
106         test1(8192);
107
108         /* This exits depending on whether all tests passed */
109         return exit_status();
110 }