summaryrefslogtreecommitdiff
path: root/src/regress/lib/libc/sys/t_msgrcv.c
diff options
context:
space:
mode:
authorbluhm <>2019-11-19 19:57:04 +0000
committerbluhm <>2019-11-19 19:57:04 +0000
commit9185f840eda265016178aeb0dcdba964f8f6f3e2 (patch)
treeda100b3712514c566fe948116f7926ad7f725401 /src/regress/lib/libc/sys/t_msgrcv.c
parent6a6fe688152b422f3d65c970dad56e7d9d28b1ee (diff)
downloadopenbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.gz
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.tar.bz2
openbsd-9185f840eda265016178aeb0dcdba964f8f6f3e2.zip
Import NetBSD system call regression tests. They were written with
ATF (Automated Testing Framework), so we use a small wrapper to map it to our bsd.regress.mk framework. Only half of the 80 NetBSD tests have been taken, the others need more work to adapt. Of them 34 syscall tests pass. Moritz Buhl ported the tests to OpenBSD.
Diffstat (limited to 'src/regress/lib/libc/sys/t_msgrcv.c')
-rw-r--r--src/regress/lib/libc/sys/t_msgrcv.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/src/regress/lib/libc/sys/t_msgrcv.c b/src/regress/lib/libc/sys/t_msgrcv.c
new file mode 100644
index 0000000000..1fbcd41695
--- /dev/null
+++ b/src/regress/lib/libc/sys/t_msgrcv.c
@@ -0,0 +1,388 @@
1/* $OpenBSD: t_msgrcv.c,v 1.1.1.1 2019/11/19 19:57:04 bluhm Exp $ */
2/* $NetBSD: t_msgrcv.c,v 1.5 2017/10/08 08:31:05 kre Exp $ */
3
4/*-
5 * Copyright (c) 2011 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Jukka Ruohonen.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "macros.h"
34
35#include <sys/cdefs.h>
36__RCSID("$NetBSD: t_msgrcv.c,v 1.5 2017/10/08 08:31:05 kre Exp $");
37
38#include <sys/msg.h>
39#include <sys/stat.h>
40#include <sys/sysctl.h>
41#include <sys/wait.h>
42
43#include "atf-c.h"
44#include <errno.h>
45#include <limits.h>
46#include <pwd.h>
47#include <signal.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <sysexits.h>
52#include <time.h>
53#include <unistd.h>
54
55#define MSG_KEY 1234
56#define MSG_MTYPE_1 0x41
57#define MSG_MTYPE_2 0x42
58#define MSG_MTYPE_3 0x43
59#define MSG_LEN 3
60
61struct msg {
62 long mtype;
63 char buf[MSG_LEN];
64};
65
66static void clean(void);
67
68static void
69clean(void)
70{
71 int id;
72
73 if ((id = msgget(MSG_KEY, 0)) != -1)
74 (void)msgctl(id, IPC_RMID, 0);
75}
76
77ATF_TC_WITH_CLEANUP(msgrcv_basic);
78ATF_TC_HEAD(msgrcv_basic, tc)
79{
80 atf_tc_set_md_var(tc, "descr", "A basic test of msgrcv(2)");
81}
82
83ATF_TC_BODY(msgrcv_basic, tc)
84{
85 struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
86 struct msg msg2 = { MSG_MTYPE_1, { 'x', 'y', 'z' } };
87 int id;
88
89 id = msgget(MSG_KEY, IPC_CREAT | 0600);
90 ATF_REQUIRE(id != -1);
91
92 (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
93 (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
94
95 ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
96 ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
97 ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
98
99 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
100}
101
102ATF_TC_CLEANUP(msgrcv_basic, tc)
103{
104 clean();
105}
106
107ATF_TC_WITH_CLEANUP(msgrcv_block);
108ATF_TC_HEAD(msgrcv_block, tc)
109{
110 atf_tc_set_md_var(tc, "descr", "Test that msgrcv(2) blocks");
111}
112
113ATF_TC_BODY(msgrcv_block, tc)
114{
115 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
116 int id, sta;
117 pid_t pid;
118
119 id = msgget(MSG_KEY, IPC_CREAT | 0600);
120 ATF_REQUIRE(id != -1);
121
122 pid = fork();
123 ATF_REQUIRE(pid >= 0);
124
125 if (pid == 0) {
126
127 if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1, 0) < 0)
128 _exit(EXIT_FAILURE);
129
130 _exit(EXIT_SUCCESS);
131 }
132
133 /*
134 * Below msgsnd(2) should unblock the child,
135 * and hence kill(2) should fail with ESRCH.
136 */
137 (void)sleep(1);
138 (void)msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT);
139 (void)sleep(1);
140 (void)kill(pid, SIGKILL);
141 (void)wait(&sta);
142
143 if (WIFEXITED(sta) == 0 || WIFSIGNALED(sta) != 0)
144 atf_tc_fail("msgrcv(2) did not block");
145
146 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
147}
148
149ATF_TC_CLEANUP(msgrcv_block, tc)
150{
151 clean();
152}
153
154ATF_TC_WITH_CLEANUP(msgrcv_err);
155ATF_TC_HEAD(msgrcv_err, tc)
156{
157 atf_tc_set_md_var(tc, "descr", "Test errors from msgrcv(2)");
158}
159
160ATF_TC_BODY(msgrcv_err, tc)
161{
162 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
163 int id, r = 0;
164
165 id = msgget(MSG_KEY, IPC_CREAT | 0600);
166 ATF_REQUIRE(id != -1);
167
168 errno = 0;
169
170 ATF_REQUIRE_ERRNO(ENOMSG, msgrcv(id, &msg,
171 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
172
173 ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
174
175 errno = 0;
176
177 ATF_REQUIRE_ERRNO(EFAULT, msgrcv(id, (void *)-1,
178 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
179
180 errno = 0;
181
182 ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
183 MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT) == -1);
184
185 errno = 0;
186
187 ATF_REQUIRE_ERRNO(EINVAL, msgrcv(-1, &msg,
188 SSIZE_MAX, MSG_MTYPE_1, IPC_NOWAIT) == -1);
189
190 ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
191
192 errno = 0;
193
194 ATF_REQUIRE_ERRNO(E2BIG, msgrcv(id, &r,
195 MSG_LEN - 1, MSG_MTYPE_1, IPC_NOWAIT) == -1);
196
197 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
198}
199
200ATF_TC_CLEANUP(msgrcv_err, tc)
201{
202 clean();
203}
204
205
206ATF_TC_WITH_CLEANUP(msgrcv_mtype);
207ATF_TC_HEAD(msgrcv_mtype, tc)
208{
209 atf_tc_set_md_var(tc, "descr", "Test message types with msgrcv(2)");
210}
211
212ATF_TC_BODY(msgrcv_mtype, tc)
213{
214 struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
215 struct msg msg2 = { MSG_MTYPE_3, { 'x', 'y', 'z' } };
216 int id;
217
218 id = msgget(MSG_KEY, IPC_CREAT | 0600);
219 ATF_REQUIRE(id != -1);
220
221 (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
222 (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_2, IPC_NOWAIT);
223
224 ATF_CHECK(msg1.buf[0] != msg2.buf[0]); /* Different mtype. */
225 ATF_CHECK(msg1.buf[1] != msg2.buf[1]);
226 ATF_CHECK(msg1.buf[2] != msg2.buf[2]);
227
228 (void)msgrcv(id, &msg2, MSG_LEN, MSG_MTYPE_1, IPC_NOWAIT);
229
230 ATF_CHECK(msg1.buf[0] == msg2.buf[0]); /* Same mtype. */
231 ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
232 ATF_CHECK(msg1.buf[2] == msg2.buf[2]);
233
234 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
235}
236
237ATF_TC_CLEANUP(msgrcv_mtype, tc)
238{
239 clean();
240}
241
242ATF_TC_WITH_CLEANUP(msgrcv_nonblock);
243ATF_TC_HEAD(msgrcv_nonblock, tc)
244{
245 atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with IPC_NOWAIT");
246 atf_tc_set_md_var(tc, "timeout", "10");
247}
248
249ATF_TC_BODY(msgrcv_nonblock, tc)
250{
251 struct msg msg = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
252 const ssize_t n = 10;
253 int id, sta;
254 ssize_t i;
255 pid_t pid;
256
257 id = msgget(MSG_KEY, IPC_CREAT | 0600);
258 ATF_REQUIRE(id != -1);
259
260 for (i = 0; i < n; i++) {
261
262 ATF_REQUIRE(msgsnd(id, &msg, MSG_LEN, IPC_NOWAIT) == 0);
263 }
264
265 pid = fork();
266 ATF_REQUIRE(pid >= 0);
267
268 if (pid == 0) {
269
270 while (i != 0) {
271
272 if (msgrcv(id, &msg, MSG_LEN, MSG_MTYPE_1,
273 IPC_NOWAIT) == -1)
274 _exit(EXIT_FAILURE);
275
276 i--;
277 }
278
279 _exit(EXIT_SUCCESS);
280 }
281
282 (void)sleep(2);
283 (void)kill(pid, SIGKILL);
284 (void)wait(&sta);
285
286 if (WIFSIGNALED(sta) != 0 || WTERMSIG(sta) == SIGKILL)
287 atf_tc_fail("msgrcv(2) blocked with IPC_NOWAIT");
288
289 if (WIFEXITED(sta) == 0 && WEXITSTATUS(sta) != EXIT_SUCCESS)
290 atf_tc_fail("msgrcv(2) failed");
291
292 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
293}
294
295ATF_TC_CLEANUP(msgrcv_nonblock, tc)
296{
297 clean();
298}
299
300ATF_TC_WITH_CLEANUP(msgrcv_truncate);
301ATF_TC_HEAD(msgrcv_truncate, tc)
302{
303 atf_tc_set_md_var(tc, "descr", "Test msgrcv(2) with MSG_NOERROR");
304}
305
306ATF_TC_BODY(msgrcv_truncate, tc)
307{
308#define MSG_SMALLLEN 2
309 struct msgsmall {
310 long mtype;
311 char buf[MSG_SMALLLEN];
312 };
313
314 struct msg msg1 = { MSG_MTYPE_1, { 'a', 'b', 'c' } };
315 struct msgsmall msg2 = { MSG_MTYPE_1, { 'x', 'y' } };
316 int id;
317
318 id = msgget(MSG_KEY, IPC_CREAT | 0600);
319 ATF_REQUIRE(id != -1);
320
321 (void)msgsnd(id, &msg1, MSG_LEN, IPC_NOWAIT);
322 (void)msgrcv(id, &msg2, MSG_SMALLLEN,
323 MSG_MTYPE_1, IPC_NOWAIT | MSG_NOERROR);
324
325 ATF_CHECK(msg1.buf[0] == msg2.buf[0]);
326 ATF_CHECK(msg1.buf[1] == msg2.buf[1]);
327
328 ATF_REQUIRE(msgctl(id, IPC_RMID, 0) == 0);
329}
330
331ATF_TC_CLEANUP(msgrcv_truncate, tc)
332{
333 clean();
334}
335
336static volatile int sig_caught;
337
338static void
339sigsys_handler(int signum)
340{
341
342 sig_caught = signum;
343}
344
345static int
346no_kernel_sysvmsg(void)
347{
348 int id;
349 void (*osig)(int);
350
351 sig_caught = 0;
352 osig = signal(SIGSYS, sigsys_handler);
353 id = msgget(MSG_KEY, IPC_CREAT | 0600);
354 if (sig_caught || id == -1)
355 return 1;
356
357 (void)msgctl(id, IPC_RMID, 0);
358 (void)signal(SIGSYS, osig);
359
360 return 0;
361}
362
363ATF_TC(msgrcv_query);
364ATF_TC_HEAD(msgrcv_query, tc)
365{
366 atf_tc_set_md_var(tc, "descr", "Skip msgrcv_* tests - no SYSVMSG");
367}
368ATF_TC_BODY(msgrcv_query, tc)
369{
370 atf_tc_skip("No SYSVMSG in kernel");
371}
372
373ATF_TP_ADD_TCS(tp)
374{
375
376 if (no_kernel_sysvmsg()) {
377 ATF_TP_ADD_TC(tp, msgrcv_query);
378 } else {
379 ATF_TP_ADD_TC(tp, msgrcv_basic);
380 ATF_TP_ADD_TC(tp, msgrcv_block);
381 ATF_TP_ADD_TC(tp, msgrcv_err);
382 ATF_TP_ADD_TC(tp, msgrcv_mtype);
383 ATF_TP_ADD_TC(tp, msgrcv_nonblock);
384 ATF_TP_ADD_TC(tp, msgrcv_truncate);
385 }
386
387 return atf_no_error();
388}