]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/netbsd-tests/lib/libc/sys/t_msgrcv.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / netbsd-tests / lib / libc / sys / t_msgrcv.c
1 /* $NetBSD: t_msgrcv.c,v 1.3 2013/07/24 11:44:10 skrll Exp $ */
2
3 /*-
4  * Copyright (c) 2011 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jukka Ruohonen.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_msgrcv.c,v 1.3 2013/07/24 11:44:10 skrll Exp $");
33
34 #include <sys/msg.h>
35 #include <sys/stat.h>
36 #include <sys/sysctl.h>
37 #include <sys/wait.h>
38
39 #include <atf-c.h>
40 #include <errno.h>
41 #include <pwd.h>
42 #include <signal.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <sysexits.h>
47 #include <time.h>
48 #include <unistd.h>
49
50 #ifdef __FreeBSD__
51 #include <limits.h>
52 #endif
53
54 #define MSG_KEY         1234
55 #define MSG_MTYPE_1     0x41
56 #define MSG_MTYPE_2     0x42
57 #define MSG_MTYPE_3     0x43
58 #define MSG_LEN         3
59
60 struct msg {
61         long             mtype;
62         char             buf[MSG_LEN];
63 };
64
65 static void             clean(void);
66
67 static void
68 clean(void)
69 {
70         int id;
71
72         if ((id = msgget(MSG_KEY, 0)) != -1)
73                 (void)msgctl(id, IPC_RMID, 0);
74 }
75
76 ATF_TC_WITH_CLEANUP(msgrcv_basic);
77 ATF_TC_HEAD(msgrcv_basic, tc)
78 {
79         atf_tc_set_md_var(tc, "descr", "A basic test of msgrcv(2)");
80 }
81
82 ATF_TC_BODY(msgrcv_basic, tc)
83 {
84         struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
85         struct msg msg2 = { MSG_MTYPE_1, { 'x', 'y', 'z' } };
86         int id;
87
88         id = msgget(MSG_KEY, IPC_CREAT | 0600);
89         ATF_REQUIRE(id != -1);
90
91         (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
92         (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
93
94         ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
95         ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
96         ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
97
98         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
99 }
100
101 ATF_TC_CLEANUP(msgrcv_basic, tc)
102 {
103         clean();
104 }
105
106 ATF_TC_WITH_CLEANUP(msgrcv_block);
107 ATF_TC_HEAD(msgrcv_block, tc)
108 {
109         atf_tc_set_md_var(tc, "descr", "Test that msgrcv(2) blocks");
110 }
111
112 ATF_TC_BODY(msgrcv_block, tc)
113 {
114         struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
115         int id, sta;
116         pid_t pid;
117
118         id = msgget(MSG_KEY, IPC_CREAT | 0600);
119         ATF_REQUIRE(id != -1);
120
121         pid = fork();
122         ATF_REQUIRE(pid >= 0);
123
124         if (pid == 0) {
125
126                 if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1, 0) < 0)
127                         _exit(EXIT_FAILURE);
128
129                 _exit(EXIT_SUCCESS);
130         }
131
132         /*
133          * Below msgsnd(2) should unblock the child,
134          * and hence kill(2) should fail with ESRCH.
135          */
136         (void)sleep(1);
137         (void)msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT);
138         (void)sleep(1);
139         (void)kill(pid, SIGKILL);
140         (void)wait(&sta);
141
142         if (WIFEXITED(sta) == 0 || WIFSIGNALED(sta) != 0)
143                 atf_tc_fail("msgrcv(2) did not block");
144
145         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
146 }
147
148 ATF_TC_CLEANUP(msgrcv_block, tc)
149 {
150         clean();
151 }
152
153 ATF_TC_WITH_CLEANUP(msgrcv_err);
154 ATF_TC_HEAD(msgrcv_err, tc)
155 {
156         atf_tc_set_md_var(tc, "descr", "Test errors from msgrcv(2)");
157 }
158
159 ATF_TC_BODY(msgrcv_err, tc)
160 {
161         struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
162         int id, r = 0;
163
164         id = msgget(MSG_KEY, IPC_CREAT | 0600);
165         ATF_REQUIRE(id != -1);
166
167         errno = 0;
168
169         ATF_REQUIRE_ERRNO(ENOMSG, msgrcv(id, &msg,
170                 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
171
172         ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
173
174         errno = 0;
175
176         ATF_REQUIRE_ERRNO(EFAULT, msgrcv(id, (void *)-1,
177                 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
178
179         errno = 0;
180
181         ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
182                 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
183
184         errno = 0;
185
186         ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
187                 SSIZE_MAX, MSG_MTYPE_1, IPC_NOWAIT) == -1);
188
189         ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
190
191         errno = 0;
192
193         ATF_REQUIRE_ERRNO(E2BIG, msgrcv(id, &r,
194                 MSG_LEN - 1, MSG_MTYPE_1, IPC_NOWAIT) == -1);
195
196         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
197 }
198
199 ATF_TC_CLEANUP(msgrcv_err, tc)
200 {
201         clean();
202 }
203
204
205 ATF_TC_WITH_CLEANUP(msgrcv_mtype);
206 ATF_TC_HEAD(msgrcv_mtype, tc)
207 {
208         atf_tc_set_md_var(tc, "descr", "Test message types with msgrcv(2)");
209 }
210
211 ATF_TC_BODY(msgrcv_mtype, tc)
212 {
213         struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
214         struct msg msg2 = { MSG_MTYPE_3, { 'x', 'y', 'z' } };
215         int id;
216
217         id = msgget(MSG_KEY, IPC_CREAT | 0600);
218         ATF_REQUIRE(id != -1);
219
220         (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
221         (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_2, IPC_NOWAIT);
222
223         ATF_CHECK(msg1.buf[0] != msg2.buf[0]);  /* Different mtype. */
224         ATF_CHECK(msg1.buf[1] != msg2.buf[1]);
225         ATF_CHECK(msg1.buf[2] != msg2.buf[2]);
226
227         (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
228
229         ATF_CHECK(msg1.buf[0] == msg2.buf[0]);  /* Same mtype. */
230         ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
231         ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
232
233         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
234 }
235
236 ATF_TC_CLEANUP(msgrcv_mtype, tc)
237 {
238         clean();
239 }
240
241 ATF_TC_WITH_CLEANUP(msgrcv_nonblock);
242 ATF_TC_HEAD(msgrcv_nonblock, tc)
243 {
244         atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with IPC_NOWAIT");
245         atf_tc_set_md_var(tc, "timeout", "10");
246 }
247
248 ATF_TC_BODY(msgrcv_nonblock, tc)
249 {
250         struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
251         const ssize_t n = 10;
252         int id, sta;
253         ssize_t i;
254         pid_t pid;
255
256         id = msgget(MSG_KEY, IPC_CREAT | 0600);
257         ATF_REQUIRE(id != -1);
258
259         for (i = 0; i < n; i++) {
260
261                 ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
262         }
263
264         pid = fork();
265         ATF_REQUIRE(pid >= 0);
266
267         if (pid == 0) {
268
269                 while (i != 0) {
270
271                         if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1,
272                             IPC_NOWAIT) == -1)
273                                 _exit(EXIT_FAILURE);
274
275                         i--;
276                 }
277
278                 _exit(EXIT_SUCCESS);
279         }
280
281         (void)sleep(2);
282         (void)kill(pid, SIGKILL);
283         (void)wait(&sta);
284
285         if (WIFSIGNALED(sta) != 0 || WTERMSIG(sta) == SIGKILL)
286                 atf_tc_fail("msgrcv(2) blocked with IPC_NOWAIT");
287
288         if (WIFEXITED(sta) == 0 && WEXITSTATUS(sta) != EXIT_SUCCESS)
289                 atf_tc_fail("msgrcv(2) failed");
290
291         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
292 }
293
294 ATF_TC_CLEANUP(msgrcv_nonblock, tc)
295 {
296         clean();
297 }
298
299 ATF_TC_WITH_CLEANUP(msgrcv_truncate);
300 ATF_TC_HEAD(msgrcv_truncate, tc)
301 {
302         atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with MSG_NOERROR");
303 }
304
305 ATF_TC_BODY(msgrcv_truncate, tc)
306 {
307 #define MSG_SMALLLEN    2
308         struct msgsmall {
309                 long             mtype;
310                 char             buf[MSG_SMALLLEN];
311         };
312
313         struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
314         struct msgsmall msg2 = { MSG_MTYPE_1, { 'x', 'y' } };
315         int id;
316
317         id = msgget(MSG_KEY, IPC_CREAT | 0600);
318         ATF_REQUIRE(id != -1);
319
320         (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
321         (void)msgrcv(id, &msg2, MSG_SMALLLEN,
322             MSG_MTYPE_1, IPC_NOWAIT | MSG_NOERROR);
323
324         ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
325         ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
326
327         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
328 }
329
330 ATF_TC_CLEANUP(msgrcv_truncate, tc)
331 {
332         clean();
333 }
334
335 ATF_TP_ADD_TCS(tp)
336 {
337
338         ATF_TP_ADD_TC(tp, msgrcv_basic);
339         ATF_TP_ADD_TC(tp, msgrcv_block);
340         ATF_TP_ADD_TC(tp, msgrcv_err);
341         ATF_TP_ADD_TC(tp, msgrcv_mtype);
342         ATF_TP_ADD_TC(tp, msgrcv_nonblock);
343         ATF_TP_ADD_TC(tp, msgrcv_truncate);
344
345         return atf_no_error();
346 }