]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/netbsd-tests/lib/libc/sys/t_msgrcv.c
MFC r314450,r313439:
[FreeBSD/stable/10.git] / contrib / netbsd-tests / lib / libc / sys / t_msgrcv.c
1 /* $NetBSD: t_msgrcv.c,v 1.4 2017/01/13 20:44:45 christos 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.4 2017/01/13 20:44:45 christos 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 <limits.h>
42 #include <pwd.h>
43 #include <signal.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <sysexits.h>
48 #include <time.h>
49 #include <unistd.h>
50
51 #define MSG_KEY         1234
52 #define MSG_MTYPE_1     0x41
53 #define MSG_MTYPE_2     0x42
54 #define MSG_MTYPE_3     0x43
55 #define MSG_LEN         3
56
57 struct msg {
58         long             mtype;
59         char             buf[MSG_LEN];
60 };
61
62 static void             clean(void);
63
64 static void
65 clean(void)
66 {
67         int id;
68
69         if ((id = msgget(MSG_KEY, 0)) != -1)
70                 (void)msgctl(id, IPC_RMID, 0);
71 }
72
73 ATF_TC_WITH_CLEANUP(msgrcv_basic);
74 ATF_TC_HEAD(msgrcv_basic, tc)
75 {
76         atf_tc_set_md_var(tc, "descr", "A basic test of msgrcv(2)");
77 }
78
79 ATF_TC_BODY(msgrcv_basic, tc)
80 {
81         struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
82         struct msg msg2 = { MSG_MTYPE_1, { 'x', 'y', 'z' } };
83         int id;
84
85         id = msgget(MSG_KEY, IPC_CREAT | 0600);
86         ATF_REQUIRE(id != -1);
87
88         (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
89         (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
90
91         ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
92         ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
93         ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
94
95         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
96 }
97
98 ATF_TC_CLEANUP(msgrcv_basic, tc)
99 {
100         clean();
101 }
102
103 ATF_TC_WITH_CLEANUP(msgrcv_block);
104 ATF_TC_HEAD(msgrcv_block, tc)
105 {
106         atf_tc_set_md_var(tc, "descr", "Test that msgrcv(2) blocks");
107 }
108
109 ATF_TC_BODY(msgrcv_block, tc)
110 {
111         struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
112         int id, sta;
113         pid_t pid;
114
115         id = msgget(MSG_KEY, IPC_CREAT | 0600);
116         ATF_REQUIRE(id != -1);
117
118         pid = fork();
119         ATF_REQUIRE(pid >= 0);
120
121         if (pid == 0) {
122
123                 if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1, 0) < 0)
124                         _exit(EXIT_FAILURE);
125
126                 _exit(EXIT_SUCCESS);
127         }
128
129         /*
130          * Below msgsnd(2) should unblock the child,
131          * and hence kill(2) should fail with ESRCH.
132          */
133         (void)sleep(1);
134         (void)msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT);
135         (void)sleep(1);
136         (void)kill(pid, SIGKILL);
137         (void)wait(&sta);
138
139         if (WIFEXITED(sta) == 0 || WIFSIGNALED(sta) != 0)
140                 atf_tc_fail("msgrcv(2) did not block");
141
142         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
143 }
144
145 ATF_TC_CLEANUP(msgrcv_block, tc)
146 {
147         clean();
148 }
149
150 ATF_TC_WITH_CLEANUP(msgrcv_err);
151 ATF_TC_HEAD(msgrcv_err, tc)
152 {
153         atf_tc_set_md_var(tc, "descr", "Test errors from msgrcv(2)");
154 }
155
156 ATF_TC_BODY(msgrcv_err, tc)
157 {
158         struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
159         int id, r = 0;
160
161         id = msgget(MSG_KEY, IPC_CREAT | 0600);
162         ATF_REQUIRE(id != -1);
163
164         errno = 0;
165
166         ATF_REQUIRE_ERRNO(ENOMSG, msgrcv(id, &msg,
167                 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
168
169         ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
170
171         errno = 0;
172
173         ATF_REQUIRE_ERRNO(EFAULT, msgrcv(id, (void *)-1,
174                 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
175
176         errno = 0;
177
178         ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
179                 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
180
181         errno = 0;
182
183         ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
184                 SSIZE_MAX, MSG_MTYPE_1, IPC_NOWAIT) == -1);
185
186         ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
187
188         errno = 0;
189
190         ATF_REQUIRE_ERRNO(E2BIG, msgrcv(id, &r,
191                 MSG_LEN - 1, MSG_MTYPE_1, IPC_NOWAIT) == -1);
192
193         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
194 }
195
196 ATF_TC_CLEANUP(msgrcv_err, tc)
197 {
198         clean();
199 }
200
201
202 ATF_TC_WITH_CLEANUP(msgrcv_mtype);
203 ATF_TC_HEAD(msgrcv_mtype, tc)
204 {
205         atf_tc_set_md_var(tc, "descr", "Test message types with msgrcv(2)");
206 }
207
208 ATF_TC_BODY(msgrcv_mtype, tc)
209 {
210         struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
211         struct msg msg2 = { MSG_MTYPE_3, { 'x', 'y', 'z' } };
212         int id;
213
214         id = msgget(MSG_KEY, IPC_CREAT | 0600);
215         ATF_REQUIRE(id != -1);
216
217         (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
218         (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_2, IPC_NOWAIT);
219
220         ATF_CHECK(msg1.buf[0] != msg2.buf[0]);  /* Different mtype. */
221         ATF_CHECK(msg1.buf[1] != msg2.buf[1]);
222         ATF_CHECK(msg1.buf[2] != msg2.buf[2]);
223
224         (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
225
226         ATF_CHECK(msg1.buf[0] == msg2.buf[0]);  /* Same mtype. */
227         ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
228         ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
229
230         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
231 }
232
233 ATF_TC_CLEANUP(msgrcv_mtype, tc)
234 {
235         clean();
236 }
237
238 ATF_TC_WITH_CLEANUP(msgrcv_nonblock);
239 ATF_TC_HEAD(msgrcv_nonblock, tc)
240 {
241         atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with IPC_NOWAIT");
242         atf_tc_set_md_var(tc, "timeout", "10");
243 }
244
245 ATF_TC_BODY(msgrcv_nonblock, tc)
246 {
247         struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
248         const ssize_t n = 10;
249         int id, sta;
250         ssize_t i;
251         pid_t pid;
252
253         id = msgget(MSG_KEY, IPC_CREAT | 0600);
254         ATF_REQUIRE(id != -1);
255
256         for (i = 0; i < n; i++) {
257
258                 ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
259         }
260
261         pid = fork();
262         ATF_REQUIRE(pid >= 0);
263
264         if (pid == 0) {
265
266                 while (i != 0) {
267
268                         if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1,
269                             IPC_NOWAIT) == -1)
270                                 _exit(EXIT_FAILURE);
271
272                         i--;
273                 }
274
275                 _exit(EXIT_SUCCESS);
276         }
277
278         (void)sleep(2);
279         (void)kill(pid, SIGKILL);
280         (void)wait(&sta);
281
282         if (WIFSIGNALED(sta) != 0 || WTERMSIG(sta) == SIGKILL)
283                 atf_tc_fail("msgrcv(2) blocked with IPC_NOWAIT");
284
285         if (WIFEXITED(sta) == 0 && WEXITSTATUS(sta) != EXIT_SUCCESS)
286                 atf_tc_fail("msgrcv(2) failed");
287
288         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
289 }
290
291 ATF_TC_CLEANUP(msgrcv_nonblock, tc)
292 {
293         clean();
294 }
295
296 ATF_TC_WITH_CLEANUP(msgrcv_truncate);
297 ATF_TC_HEAD(msgrcv_truncate, tc)
298 {
299         atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with MSG_NOERROR");
300 }
301
302 ATF_TC_BODY(msgrcv_truncate, tc)
303 {
304 #define MSG_SMALLLEN    2
305         struct msgsmall {
306                 long             mtype;
307                 char             buf[MSG_SMALLLEN];
308         };
309
310         struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
311         struct msgsmall msg2 = { MSG_MTYPE_1, { 'x', 'y' } };
312         int id;
313
314         id = msgget(MSG_KEY, IPC_CREAT | 0600);
315         ATF_REQUIRE(id != -1);
316
317         (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
318         (void)msgrcv(id, &msg2, MSG_SMALLLEN,
319             MSG_MTYPE_1, IPC_NOWAIT | MSG_NOERROR);
320
321         ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
322         ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
323
324         ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
325 }
326
327 ATF_TC_CLEANUP(msgrcv_truncate, tc)
328 {
329         clean();
330 }
331
332 ATF_TP_ADD_TCS(tp)
333 {
334
335         ATF_TP_ADD_TC(tp, msgrcv_basic);
336         ATF_TP_ADD_TC(tp, msgrcv_block);
337         ATF_TP_ADD_TC(tp, msgrcv_err);
338         ATF_TP_ADD_TC(tp, msgrcv_mtype);
339         ATF_TP_ADD_TC(tp, msgrcv_nonblock);
340         ATF_TP_ADD_TC(tp, msgrcv_truncate);
341
342         return atf_no_error();
343 }