1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) Crackerjack Project., 2007-2008, Hitachi, Ltd
4f08c3bdfSopenharmony_ci * Copyright (c) 2017 Petr Vorel <pvorel@suse.cz>
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * Authors:
7f08c3bdfSopenharmony_ci * Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
8f08c3bdfSopenharmony_ci * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
9f08c3bdfSopenharmony_ci * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
10f08c3bdfSopenharmony_ci */
11f08c3bdfSopenharmony_ci
12f08c3bdfSopenharmony_ci#include <errno.h>
13f08c3bdfSopenharmony_ci#include <limits.h>
14f08c3bdfSopenharmony_ci
15f08c3bdfSopenharmony_cistatic int fd, fd_root, fd_nonblock, fd_maxint = INT_MAX - 1, fd_invalid = -1;
16f08c3bdfSopenharmony_ci
17f08c3bdfSopenharmony_ci#include "mq_timed.h"
18f08c3bdfSopenharmony_ci
19f08c3bdfSopenharmony_cistatic struct tst_ts ts;
20f08c3bdfSopenharmony_cistatic void *bad_addr;
21f08c3bdfSopenharmony_ci
22f08c3bdfSopenharmony_cistatic struct test_case tcase[] = {
23f08c3bdfSopenharmony_ci	{
24f08c3bdfSopenharmony_ci		.fd = &fd,
25f08c3bdfSopenharmony_ci		.len = 0,
26f08c3bdfSopenharmony_ci		.ret = 0,
27f08c3bdfSopenharmony_ci		.err = 0,
28f08c3bdfSopenharmony_ci	},
29f08c3bdfSopenharmony_ci	{
30f08c3bdfSopenharmony_ci		.fd = &fd,
31f08c3bdfSopenharmony_ci		.len = 1,
32f08c3bdfSopenharmony_ci		.ret = 0,
33f08c3bdfSopenharmony_ci		.err = 0,
34f08c3bdfSopenharmony_ci	},
35f08c3bdfSopenharmony_ci	{
36f08c3bdfSopenharmony_ci		.fd = &fd,
37f08c3bdfSopenharmony_ci		.len = MAX_MSGSIZE,
38f08c3bdfSopenharmony_ci		.ret = 0,
39f08c3bdfSopenharmony_ci		.err = 0,
40f08c3bdfSopenharmony_ci	},
41f08c3bdfSopenharmony_ci	{
42f08c3bdfSopenharmony_ci		.fd = &fd,
43f08c3bdfSopenharmony_ci		.len = 1,
44f08c3bdfSopenharmony_ci		.prio = MQ_PRIO_MAX - 1,
45f08c3bdfSopenharmony_ci		.ret = 0,
46f08c3bdfSopenharmony_ci		.err = 0,
47f08c3bdfSopenharmony_ci	},
48f08c3bdfSopenharmony_ci	{
49f08c3bdfSopenharmony_ci		.fd = &fd,
50f08c3bdfSopenharmony_ci		.len = MAX_MSGSIZE + 1,
51f08c3bdfSopenharmony_ci		.ret = -1,
52f08c3bdfSopenharmony_ci		.err = EMSGSIZE,
53f08c3bdfSopenharmony_ci	},
54f08c3bdfSopenharmony_ci	{
55f08c3bdfSopenharmony_ci		.fd = &fd_invalid,
56f08c3bdfSopenharmony_ci		.len = 0,
57f08c3bdfSopenharmony_ci		.ret = -1,
58f08c3bdfSopenharmony_ci		.err = EBADF,
59f08c3bdfSopenharmony_ci	},
60f08c3bdfSopenharmony_ci	{
61f08c3bdfSopenharmony_ci		.fd = &fd_maxint,
62f08c3bdfSopenharmony_ci		.len = 0,
63f08c3bdfSopenharmony_ci		.ret = -1,
64f08c3bdfSopenharmony_ci		.err = EBADF,
65f08c3bdfSopenharmony_ci	},
66f08c3bdfSopenharmony_ci	{
67f08c3bdfSopenharmony_ci		.fd = &fd_root,
68f08c3bdfSopenharmony_ci		.len = 0,
69f08c3bdfSopenharmony_ci		.ret = -1,
70f08c3bdfSopenharmony_ci		.err = EBADF,
71f08c3bdfSopenharmony_ci	},
72f08c3bdfSopenharmony_ci	{
73f08c3bdfSopenharmony_ci		.fd = &fd_nonblock,
74f08c3bdfSopenharmony_ci		.len = 16,
75f08c3bdfSopenharmony_ci		.ret = -1,
76f08c3bdfSopenharmony_ci		.err = EAGAIN,
77f08c3bdfSopenharmony_ci	},
78f08c3bdfSopenharmony_ci	{
79f08c3bdfSopenharmony_ci		.fd = &fd,
80f08c3bdfSopenharmony_ci		.len = 1,
81f08c3bdfSopenharmony_ci		.prio = MQ_PRIO_MAX,
82f08c3bdfSopenharmony_ci		.ret = -1,
83f08c3bdfSopenharmony_ci		.err = EINVAL,
84f08c3bdfSopenharmony_ci	},
85f08c3bdfSopenharmony_ci	{
86f08c3bdfSopenharmony_ci		.fd = &fd,
87f08c3bdfSopenharmony_ci		.len = 16,
88f08c3bdfSopenharmony_ci		.tv_sec = -1,
89f08c3bdfSopenharmony_ci		.tv_nsec = 0,
90f08c3bdfSopenharmony_ci		.rq = &ts,
91f08c3bdfSopenharmony_ci		.send = 1,
92f08c3bdfSopenharmony_ci		.ret = -1,
93f08c3bdfSopenharmony_ci		.err = EINVAL,
94f08c3bdfSopenharmony_ci	},
95f08c3bdfSopenharmony_ci	{
96f08c3bdfSopenharmony_ci		.fd = &fd,
97f08c3bdfSopenharmony_ci		.len = 16,
98f08c3bdfSopenharmony_ci		.tv_sec = 0,
99f08c3bdfSopenharmony_ci		.tv_nsec = -1,
100f08c3bdfSopenharmony_ci		.rq = &ts,
101f08c3bdfSopenharmony_ci		.send = 1,
102f08c3bdfSopenharmony_ci		.ret = -1,
103f08c3bdfSopenharmony_ci		.err = EINVAL,
104f08c3bdfSopenharmony_ci	},
105f08c3bdfSopenharmony_ci	{
106f08c3bdfSopenharmony_ci		.fd = &fd,
107f08c3bdfSopenharmony_ci		.len = 16,
108f08c3bdfSopenharmony_ci		.tv_sec = 0,
109f08c3bdfSopenharmony_ci		.tv_nsec = 1000000000,
110f08c3bdfSopenharmony_ci		.rq = &ts,
111f08c3bdfSopenharmony_ci		.send = 1,
112f08c3bdfSopenharmony_ci		.ret = -1,
113f08c3bdfSopenharmony_ci		.err = EINVAL,
114f08c3bdfSopenharmony_ci	},
115f08c3bdfSopenharmony_ci	{
116f08c3bdfSopenharmony_ci		.fd = &fd,
117f08c3bdfSopenharmony_ci		.len = 16,
118f08c3bdfSopenharmony_ci		.rq = &ts,
119f08c3bdfSopenharmony_ci		.send = 1,
120f08c3bdfSopenharmony_ci		.timeout = 1,
121f08c3bdfSopenharmony_ci		.ret = -1,
122f08c3bdfSopenharmony_ci		.err = ETIMEDOUT,
123f08c3bdfSopenharmony_ci	},
124f08c3bdfSopenharmony_ci	{
125f08c3bdfSopenharmony_ci		.fd = &fd,
126f08c3bdfSopenharmony_ci		.len = 16,
127f08c3bdfSopenharmony_ci		.send = 1,
128f08c3bdfSopenharmony_ci		.signal = 1,
129f08c3bdfSopenharmony_ci		.rq = &ts,
130f08c3bdfSopenharmony_ci		.ret = -1,
131f08c3bdfSopenharmony_ci		.err = EINTR,
132f08c3bdfSopenharmony_ci	},
133f08c3bdfSopenharmony_ci	{
134f08c3bdfSopenharmony_ci		.fd = &fd,
135f08c3bdfSopenharmony_ci		.len = 16,
136f08c3bdfSopenharmony_ci		.bad_msg_addr = 1,
137f08c3bdfSopenharmony_ci		.ret = -1,
138f08c3bdfSopenharmony_ci		.err = EFAULT,
139f08c3bdfSopenharmony_ci	},
140f08c3bdfSopenharmony_ci	{
141f08c3bdfSopenharmony_ci		.fd = &fd,
142f08c3bdfSopenharmony_ci		.len = 16,
143f08c3bdfSopenharmony_ci		.bad_ts_addr = 1,
144f08c3bdfSopenharmony_ci		.ret = -1,
145f08c3bdfSopenharmony_ci		.err = EFAULT,
146f08c3bdfSopenharmony_ci	}
147f08c3bdfSopenharmony_ci};
148f08c3bdfSopenharmony_ci
149f08c3bdfSopenharmony_cistatic void setup(void)
150f08c3bdfSopenharmony_ci{
151f08c3bdfSopenharmony_ci	struct time64_variants *tv = &variants[tst_variant];
152f08c3bdfSopenharmony_ci
153f08c3bdfSopenharmony_ci	tst_res(TINFO, "Testing variant: %s", tv->desc);
154f08c3bdfSopenharmony_ci	ts.type = tv->ts_type;
155f08c3bdfSopenharmony_ci
156f08c3bdfSopenharmony_ci	bad_addr = tst_get_bad_addr(cleanup_common);
157f08c3bdfSopenharmony_ci
158f08c3bdfSopenharmony_ci	setup_common();
159f08c3bdfSopenharmony_ci}
160f08c3bdfSopenharmony_ci
161f08c3bdfSopenharmony_cistatic void do_test(unsigned int i)
162f08c3bdfSopenharmony_ci{
163f08c3bdfSopenharmony_ci	struct time64_variants *tv = &variants[tst_variant];
164f08c3bdfSopenharmony_ci	const struct test_case *tc = &tcase[i];
165f08c3bdfSopenharmony_ci	unsigned int j;
166f08c3bdfSopenharmony_ci	unsigned int prio;
167f08c3bdfSopenharmony_ci	size_t len = MAX_MSGSIZE;
168f08c3bdfSopenharmony_ci	char rmsg[len];
169f08c3bdfSopenharmony_ci	pid_t pid = -1;
170f08c3bdfSopenharmony_ci	void *msg_ptr, *abs_timeout;
171f08c3bdfSopenharmony_ci
172f08c3bdfSopenharmony_ci	tst_ts_set_sec(&ts, tc->tv_sec);
173f08c3bdfSopenharmony_ci	tst_ts_set_nsec(&ts, tc->tv_nsec);
174f08c3bdfSopenharmony_ci
175f08c3bdfSopenharmony_ci	if (tc->signal)
176f08c3bdfSopenharmony_ci		pid = set_sig(tc->rq, tv->clock_gettime);
177f08c3bdfSopenharmony_ci
178f08c3bdfSopenharmony_ci	if (tc->timeout)
179f08c3bdfSopenharmony_ci		set_timeout(tc->rq, tv->clock_gettime);
180f08c3bdfSopenharmony_ci
181f08c3bdfSopenharmony_ci	if (tc->send) {
182f08c3bdfSopenharmony_ci		for (j = 0; j < MSG_LENGTH; j++)
183f08c3bdfSopenharmony_ci			if (tv->mqt_send(*tc->fd, smsg, tc->len, tc->prio, NULL) < 0) {
184f08c3bdfSopenharmony_ci				tst_res(TFAIL | TTERRNO, "mq_timedsend() failed");
185f08c3bdfSopenharmony_ci				return;
186f08c3bdfSopenharmony_ci			}
187f08c3bdfSopenharmony_ci	}
188f08c3bdfSopenharmony_ci
189f08c3bdfSopenharmony_ci	if (tc->bad_msg_addr)
190f08c3bdfSopenharmony_ci		msg_ptr = bad_addr;
191f08c3bdfSopenharmony_ci	else
192f08c3bdfSopenharmony_ci		msg_ptr = smsg;
193f08c3bdfSopenharmony_ci
194f08c3bdfSopenharmony_ci	if (tc->bad_ts_addr)
195f08c3bdfSopenharmony_ci		abs_timeout = bad_addr;
196f08c3bdfSopenharmony_ci	else
197f08c3bdfSopenharmony_ci		abs_timeout = tst_ts_get(tc->rq);
198f08c3bdfSopenharmony_ci
199f08c3bdfSopenharmony_ci	TEST(tv->mqt_send(*tc->fd, msg_ptr, tc->len, tc->prio, abs_timeout));
200f08c3bdfSopenharmony_ci
201f08c3bdfSopenharmony_ci	if (pid > 0)
202f08c3bdfSopenharmony_ci		kill_pid(pid);
203f08c3bdfSopenharmony_ci
204f08c3bdfSopenharmony_ci	if (TST_RET < 0) {
205f08c3bdfSopenharmony_ci		if (tc->err != TST_ERR)
206f08c3bdfSopenharmony_ci			tst_res(TFAIL | TTERRNO,
207f08c3bdfSopenharmony_ci				"mq_timedsend() failed unexpectedly, expected %s",
208f08c3bdfSopenharmony_ci				tst_strerrno(tc->err));
209f08c3bdfSopenharmony_ci		else
210f08c3bdfSopenharmony_ci			tst_res(TPASS | TTERRNO, "mq_timedsend() failed expectedly");
211f08c3bdfSopenharmony_ci
212f08c3bdfSopenharmony_ci		if (*tc->fd == fd)
213f08c3bdfSopenharmony_ci			cleanup_queue(fd);
214f08c3bdfSopenharmony_ci
215f08c3bdfSopenharmony_ci		return;
216f08c3bdfSopenharmony_ci	}
217f08c3bdfSopenharmony_ci
218f08c3bdfSopenharmony_ci	TEST(tv->mqt_receive(*tc->fd, rmsg, len, &prio, tst_ts_get(tc->rq)));
219f08c3bdfSopenharmony_ci
220f08c3bdfSopenharmony_ci	if (*tc->fd == fd)
221f08c3bdfSopenharmony_ci		cleanup_queue(fd);
222f08c3bdfSopenharmony_ci
223f08c3bdfSopenharmony_ci	if (TST_RET < 0) {
224f08c3bdfSopenharmony_ci		if (tc->err != TST_ERR) {
225f08c3bdfSopenharmony_ci			tst_res(TFAIL | TTERRNO,
226f08c3bdfSopenharmony_ci				"mq_timedreceive() failed unexpectedly, expected %s",
227f08c3bdfSopenharmony_ci				tst_strerrno(tc->err));
228f08c3bdfSopenharmony_ci			return;
229f08c3bdfSopenharmony_ci		}
230f08c3bdfSopenharmony_ci
231f08c3bdfSopenharmony_ci		if (tc->ret >= 0) {
232f08c3bdfSopenharmony_ci			tst_res(TFAIL | TTERRNO, "mq_timedreceive() returned %ld, expected %d",
233f08c3bdfSopenharmony_ci					TST_RET, tc->ret);
234f08c3bdfSopenharmony_ci			return;
235f08c3bdfSopenharmony_ci		}
236f08c3bdfSopenharmony_ci	}
237f08c3bdfSopenharmony_ci
238f08c3bdfSopenharmony_ci	if (tc->len != TST_RET) {
239f08c3bdfSopenharmony_ci		tst_res(TFAIL, "mq_timedreceive() wrong length %ld, expected %u",
240f08c3bdfSopenharmony_ci			TST_RET, tc->len);
241f08c3bdfSopenharmony_ci		return;
242f08c3bdfSopenharmony_ci	}
243f08c3bdfSopenharmony_ci
244f08c3bdfSopenharmony_ci	if (tc->prio != prio) {
245f08c3bdfSopenharmony_ci		tst_res(TFAIL, "mq_timedreceive() wrong prio %d, expected %d",
246f08c3bdfSopenharmony_ci			prio, tc->prio);
247f08c3bdfSopenharmony_ci		return;
248f08c3bdfSopenharmony_ci	}
249f08c3bdfSopenharmony_ci
250f08c3bdfSopenharmony_ci	for (j = 0; j < tc->len; j++) {
251f08c3bdfSopenharmony_ci		if (rmsg[j] != smsg[j]) {
252f08c3bdfSopenharmony_ci			tst_res(TFAIL,
253f08c3bdfSopenharmony_ci				"mq_timedreceive() wrong data %d in %u, expected %d",
254f08c3bdfSopenharmony_ci				rmsg[j], i, smsg[j]);
255f08c3bdfSopenharmony_ci			return;
256f08c3bdfSopenharmony_ci		}
257f08c3bdfSopenharmony_ci	}
258f08c3bdfSopenharmony_ci
259f08c3bdfSopenharmony_ci	tst_res(TPASS, "mq_timedreceive() returned %ld, priority %u, length: %zu",
260f08c3bdfSopenharmony_ci			TST_RET, prio, len);
261f08c3bdfSopenharmony_ci}
262f08c3bdfSopenharmony_ci
263f08c3bdfSopenharmony_cistatic struct tst_test test = {
264f08c3bdfSopenharmony_ci	.tcnt = ARRAY_SIZE(tcase),
265f08c3bdfSopenharmony_ci	.test = do_test,
266f08c3bdfSopenharmony_ci	.test_variants = ARRAY_SIZE(variants),
267f08c3bdfSopenharmony_ci	.setup = setup,
268f08c3bdfSopenharmony_ci	.cleanup = cleanup_common,
269f08c3bdfSopenharmony_ci	.forks_child = 1,
270f08c3bdfSopenharmony_ci};
271