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