1 /*
2
3 Copyright (c) 2016 Martin Sustrik
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"),
7 to deal in the Software without restriction, including without limitation
8 the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 and/or sell copies of the Software, and to permit persons to whom
10 the Software is furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included
13 in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 IN THE SOFTWARE.
22
23 */
24
25 #include <sys/types.h>
26 #include <sys/wait.h>
27 #include <stdio.h>
28 #include <unistd.h>
29
30 #include "assert.h"
31 #include "../libdill.h"
32
33 struct foo {
34 int first;
35 int second;
36 };
37
sender(int ch,int doyield,int val)38 coroutine void sender(int ch, int doyield, int val) {
39 if(doyield) {
40 int rc = yield();
41 errno_assert(rc == 0);
42 }
43 int rc = chsend(ch, &val, sizeof(val), -1);
44 errno_assert(rc == 0);
45 }
46
receiver(int ch,int expected)47 coroutine void receiver(int ch, int expected) {
48 int val;
49 int rc = chrecv(ch, &val, sizeof(val), -1);
50 errno_assert(rc == 0);
51 assert(val == expected);
52 }
53
receiver2(int ch)54 coroutine void receiver2(int ch) {
55 int val;
56 int rc = chrecv(ch, &val, sizeof(val), -1);
57 errno_assert(rc == -1 && errno == EPIPE);
58 val = 0;
59 rc = chsend(ch, &val, sizeof(val), -1);
60 errno_assert(rc == 0);
61 }
62
charsender(int ch,char val)63 coroutine void charsender(int ch, char val) {
64 int rc = chsend(ch, &val, sizeof(val), -1);
65 errno_assert(rc == 0);
66 }
67
structsender(int ch,struct foo val)68 coroutine void structsender(int ch, struct foo val) {
69 int rc = chsend(ch, &val, sizeof(val), -1);
70 errno_assert(rc == 0);
71 }
72
sender2(int ch)73 coroutine void sender2(int ch) {
74 int val = 0;
75 int rc = chsend(ch, &val, sizeof(val), -1);
76 errno_assert(rc == -1 && errno == EPIPE);
77 }
78
receiver3(int ch)79 coroutine void receiver3(int ch) {
80 int val;
81 int rc = chrecv(ch, &val, sizeof(val), -1);
82 errno_assert(rc == -1 && errno == EPIPE);
83 }
84
cancel(int ch)85 coroutine void cancel(int ch) {
86 int val;
87 int rc = chrecv(ch, &val, sizeof(val), -1);
88 errno_assert(rc == -1 && errno == ECANCELED);
89 rc = chrecv(ch, &val, sizeof(val), -1);
90 errno_assert(rc == -1 && errno == ECANCELED);
91 }
92
sender3(int ch,int doyield)93 coroutine void sender3(int ch, int doyield) {
94 if(doyield) {
95 int rc = yield();
96 errno_assert(rc == 0);
97 }
98 int rc = chsend(ch, NULL, 0, -1);
99 errno_assert(rc == 0);
100 }
101
main()102 int main() {
103 int val;
104 int rc;
105
106 /* Receiver waits for sender. */
107 int ch1[2];
108 rc = chmake(ch1);
109 errno_assert(rc == 0);
110 assert(ch1[0] >= 0);
111 assert(ch1[1] >= 0);
112 int hndl1 = go(sender(ch1[0], 1, 333));
113 errno_assert(hndl1 >= 0);
114 rc = chrecv(ch1[1], &val, sizeof(val), -1);
115 errno_assert(rc == 0);
116 assert(val == 333);
117 rc = hclose(ch1[1]);
118 errno_assert(rc == 0);
119 rc = hclose(ch1[0]);
120 errno_assert(rc == 0);
121 rc = hclose(hndl1);
122 errno_assert(rc == 0);
123
124 /* Sender waits for receiver. */
125 int ch2[2];
126 rc = chmake(ch2);
127 errno_assert(rc == 0);
128 int hndl2 = go(sender(ch2[0], 0, 444));
129 errno_assert(hndl2 >= 0);
130 rc = chrecv(ch2[1], &val, sizeof(val), -1);
131 errno_assert(rc == 0);
132 assert(val == 444);
133 rc = hclose(ch2[1]);
134 errno_assert(rc == 0);
135 rc = hclose(ch2[0]);
136 errno_assert(rc == 0);
137 rc = hclose(hndl2);
138 errno_assert(rc == 0);
139
140 /* Test two simultaneous senders. */
141 int ch3[2];
142 rc = chmake(ch3);
143 errno_assert(rc == 0);
144 int hndl3[2];
145 hndl3[0] = go(sender(ch3[0], 0, 888));
146 errno_assert(hndl3[0] >= 0);
147 hndl3[1] = go(sender(ch3[0], 0, 999));
148 errno_assert(hndl3[1] >= 0);
149 rc = chrecv(ch3[1], &val, sizeof(val), -1);
150 errno_assert(rc == 0);
151 assert(val == 888);
152 rc = yield();
153 errno_assert(rc == 0);
154 rc = chrecv(ch3[1], &val, sizeof(val), -1);
155 errno_assert(rc == 0);
156 assert(val == 999);
157 rc = hclose(ch3[1]);
158 errno_assert(rc == 0);
159 rc = hclose(ch3[0]);
160 errno_assert(rc == 0);
161 rc = hclose(hndl3[0]);
162 errno_assert(rc == 0);
163 rc = hclose(hndl3[1]);
164 errno_assert(rc == 0);
165
166 /* Test two simultaneous receivers. */
167 int ch4[2];
168 rc = chmake(ch4);
169 errno_assert(rc == 0);
170 int hndl4[2];
171 hndl4[0] = go(receiver(ch4[0], 333));
172 errno_assert(hndl4[0] >= 0);
173 hndl4[1] = go(receiver(ch4[0], 444));
174 errno_assert(hndl4[1] >= 0);
175 val = 333;
176 rc = chsend(ch4[1], &val, sizeof(val), -1);
177 errno_assert(rc == 0);
178 val = 444;
179 rc = chsend(ch4[1], &val, sizeof(val), -1);
180 errno_assert(rc == 0);
181 rc = hclose(ch4[1]);
182 errno_assert(rc == 0);
183 rc = hclose(ch4[0]);
184 errno_assert(rc == 0);
185 rc = hclose(hndl4[0]);
186 errno_assert(rc == 0);
187 rc = hclose(hndl4[1]);
188 errno_assert(rc == 0);
189
190 /* Test simple chdone() scenario. */
191 int ch8[2];
192 rc = chmake(ch8);
193 errno_assert(rc == 0);
194 rc = chdone(ch8[0]);
195 errno_assert(rc == 0);
196 rc = chrecv(ch8[1], &val, sizeof(val), -1);
197 errno_assert(rc == -1 && errno == EPIPE);
198 rc = chrecv(ch8[1], &val, sizeof(val), -1);
199 errno_assert(rc == -1 && errno == EPIPE);
200 rc = chrecv(ch8[1], &val, sizeof(val), -1);
201 errno_assert(rc == -1 && errno == EPIPE);
202 rc = hclose(ch8[1]);
203 errno_assert(rc == 0);
204 rc = hclose(ch8[0]);
205 errno_assert(rc == 0);
206
207 /* Test whether chdone() unblocks all receivers. */
208 int ch12[2];
209 rc = chmake(ch12);
210 errno_assert(rc == 0);
211 int hndl6[2];
212 hndl6[0] = go(receiver2(ch12[0]));
213 errno_assert(hndl6[0] >= 0);
214 hndl6[1] = go(receiver2(ch12[0]));
215 errno_assert(hndl6[1] >= 0);
216 rc = chdone(ch12[1]);
217 errno_assert(rc == 0);
218 rc = chrecv(ch12[1], &val, sizeof(val), -1);
219 errno_assert(rc == 0);
220 assert(val == 0);
221 rc = chrecv(ch12[1], &val, sizeof(val), -1);
222 errno_assert(rc == 0);
223 assert(val == 0);
224 rc = hclose(ch12[1]);
225 errno_assert(rc == 0);
226 rc = hclose(ch12[0]);
227 errno_assert(rc == 0);
228 rc = hclose(hndl6[0]);
229 errno_assert(rc == 0);
230 rc = hclose(hndl6[1]);
231 errno_assert(rc == 0);
232
233 /* Test whether chdone() unblocks blocked senders. */
234 int ch15[2];
235 rc = chmake(ch15);
236 errno_assert(rc == 0);
237 int hndl8[3];
238 hndl8[0] = go(sender2(ch15[0]));
239 errno_assert(hndl8[0] >= 0);
240 hndl8[1] = go(sender2(ch15[0]));
241 errno_assert(hndl8[1] >= 0);
242 hndl8[2] = go(sender2(ch15[0]));
243 errno_assert(hndl8[2] >= 0);
244 rc = msleep(now() + 50);
245 errno_assert(rc == 0);
246 rc = chdone(ch15[1]);
247 errno_assert(rc == 0);
248 rc = hclose(ch15[1]);
249 errno_assert(rc == 0);
250 rc = hclose(ch15[0]);
251 errno_assert(rc == 0);
252 rc = hclose(hndl8[0]);
253 errno_assert(rc == 0);
254 rc = hclose(hndl8[1]);
255 errno_assert(rc == 0);
256 rc = hclose(hndl8[2]);
257 errno_assert(rc == 0);
258
259 /* Test whether hclose() unblocks blocked senders and receivers. */
260 int ch16[2];
261 rc = chmake(ch16);
262 errno_assert(rc == 0);
263 int hndl9[2];
264 hndl9[0] = go(receiver3(ch16[0]));
265 errno_assert(hndl9[0] >= 0);
266 hndl9[1] = go(receiver3(ch16[0]));
267 errno_assert(hndl9[1] >= 0);
268 rc = msleep(now() + 50);
269 errno_assert(rc == 0);
270 rc = hclose(ch16[1]);
271 errno_assert(rc == 0);
272 rc = hclose(ch16[0]);
273 errno_assert(rc == 0);
274 rc = hclose(hndl9[0]);
275 errno_assert(rc == 0);
276 rc = hclose(hndl9[1]);
277 errno_assert(rc == 0);
278
279 /* Test cancelation. */
280 int ch17[2];
281 rc = chmake(ch17);
282 errno_assert(rc == 0);
283 int hndl10 = go(cancel(ch17[0]));
284 errno_assert(hndl10 >= 0);
285 rc = hclose(hndl10);
286 errno_assert(rc == 0);
287 rc = hclose(ch17[1]);
288 errno_assert(rc == 0);
289 rc = hclose(ch17[0]);
290 errno_assert(rc == 0);
291
292 /* Receiver waits for sender (zero-byte message). */
293 int ch18[2];
294 rc = chmake(ch18);
295 errno_assert(rc == 0);
296 int hndl11 = go(sender3(ch18[0], 1));
297 errno_assert(hndl11 >= 0);
298 rc = chrecv(ch18[1], NULL, 0, -1);
299 errno_assert(rc == 0);
300 rc = hclose(ch18[1]);
301 errno_assert(rc == 0);
302 rc = hclose(ch18[0]);
303 errno_assert(rc == 0);
304 rc = hclose(hndl11);
305 errno_assert(rc == 0);
306
307 /* Sender waits for receiver (zero-byte message). */
308 int ch19[2];
309 rc = chmake(ch19);
310 errno_assert(rc == 0);
311 int hndl12 = go(sender3(ch19[0], 0));
312 errno_assert(hndl12 >= 0);
313 rc = chrecv(ch19[1], NULL, 0, -1);
314 errno_assert(rc == 0);
315 rc = hclose(ch19[1]);
316 errno_assert(rc == 0);
317 rc = hclose(ch19[0]);
318 errno_assert(rc == 0);
319 rc = hclose(hndl12);
320 errno_assert(rc == 0);
321
322 /* Channel with user-supplied storage. */
323 struct chstorage mem;
324 int ch20[2];
325 rc = chmake_mem(&mem, ch20);
326 errno_assert(rc == 0);
327 rc = chrecv(ch20[0], NULL, 0, now() + 50);
328 errno_assert(rc == -1 && errno == ETIMEDOUT);
329 rc = hclose(ch20[1]);
330 errno_assert(rc == 0);
331 rc = hclose(ch20[0]);
332 errno_assert(rc == 0);
333
334 return 0;
335 }
336
337