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