• 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 		.send = 1,
27 		.ret = 0,
28 		.err = 0,
29 	},
30 	{
31 		.fd = &fd,
32 		.len = 1,
33 		.send = 1,
34 		.ret = 0,
35 		.err = 0,
36 	},
37 	{
38 		.fd = &fd,
39 		.len = MAX_MSGSIZE,
40 		.send = 1,
41 		.ret = 0,
42 		.err = 0,
43 	},
44 	{
45 		.fd = &fd,
46 		.len = 1,
47 		.send = 1,
48 		.prio = MQ_PRIO_MAX - 1,
49 		.ret = 0,
50 		.err = 0,
51 	},
52 	{
53 		.fd = &fd,
54 		.invalid_msg = 1,
55 		.len = 0,
56 		.send = 1,
57 		.ret = -1,
58 		.err = EMSGSIZE,
59 	},
60 	{
61 		.fd = &fd_invalid,
62 		.len = 0,
63 		.ret = -1,
64 		.err = EBADF,
65 	},
66 	{
67 		.fd = &fd_maxint,
68 		.len = 0,
69 		.ret = -1,
70 		.err = EBADF,
71 	},
72 	{
73 		.fd = &fd_root,
74 		.len = 0,
75 		.ret = -1,
76 		.err = EBADF,
77 	},
78 	{
79 		.fd = &fd_nonblock,
80 		.len = 16,
81 		.ret = -1,
82 		.err = EAGAIN,
83 	},
84 	{
85 		.fd = &fd,
86 		.len = 16,
87 		.tv_sec = -1,
88 		.tv_nsec = 0,
89 		.rq = &ts,
90 		.ret = -1,
91 		.err = EINVAL,
92 	},
93 	{
94 		.fd = &fd,
95 		.len = 16,
96 		.tv_sec = 0,
97 		.tv_nsec = -1,
98 		.rq = &ts,
99 		.ret = -1,
100 		.err = EINVAL,
101 	},
102 	{
103 		.fd = &fd,
104 		.len = 16,
105 		.tv_sec = 0,
106 		.tv_nsec = 1000000000,
107 		.rq = &ts,
108 		.ret = -1,
109 		.err = EINVAL,
110 	},
111 	{
112 		.fd = &fd,
113 		.len = 16,
114 		.timeout = 1,
115 		.ret = -1,
116 		.rq = &ts,
117 		.err = ETIMEDOUT,
118 	},
119 	{
120 		.fd = &fd,
121 		.len = 16,
122 		.signal = 1,
123 		.rq = &ts,
124 		.ret = -1,
125 		.err = EINTR,
126 	},
127 	{
128 		.fd = &fd,
129 		.len = 16,
130 		.bad_ts_addr = 1,
131 		.ret = -1,
132 		.err = EFAULT,
133 	}
134 };
135 
setup(void)136 static void setup(void)
137 {
138 	struct time64_variants *tv = &variants[tst_variant];
139 
140 	tst_res(TINFO, "Testing variant: %s", tv->desc);
141 	ts.type = tv->ts_type;
142 
143 	bad_addr = tst_get_bad_addr(NULL);
144 
145 	setup_common();
146 }
147 
do_test(unsigned int i)148 static void do_test(unsigned int i)
149 {
150 	struct time64_variants *tv = &variants[tst_variant];
151 	const struct test_case *tc = &tcase[i];
152 	unsigned int j;
153 	unsigned int prio;
154 	size_t len = MAX_MSGSIZE;
155 	char rmsg[len];
156 	pid_t pid = -1;
157 	void *abs_timeout;
158 
159 	tst_ts_set_sec(&ts, tc->tv_sec);
160 	tst_ts_set_nsec(&ts, tc->tv_nsec);
161 
162 	if (tc->signal)
163 		pid = set_sig(tc->rq, tv->clock_gettime);
164 
165 	if (tc->timeout)
166 		set_timeout(tc->rq, tv->clock_gettime);
167 
168 	if (tc->send) {
169 		if (tv->mqt_send(*tc->fd, smsg, tc->len, tc->prio, NULL) < 0) {
170 			tst_res(TFAIL | TTERRNO, "mq_timedsend() failed");
171 			return;
172 		}
173 	}
174 
175 	if (tc->invalid_msg)
176 		len -= 1;
177 
178 	if (tc->bad_ts_addr)
179 		abs_timeout = bad_addr;
180 	else
181 		abs_timeout = tst_ts_get(tc->rq);
182 
183 	TEST(tv->mqt_receive(*tc->fd, rmsg, len, &prio, abs_timeout));
184 
185 	if (pid > 0)
186 		kill_pid(pid);
187 
188 	if (*tc->fd == fd)
189 		cleanup_queue(fd);
190 
191 	if (TST_RET < 0) {
192 		if (tc->err != TST_ERR)
193 			tst_res(TFAIL | TTERRNO,
194 				"mq_timedreceive() failed unexpectedly, expected %s",
195 				tst_strerrno(tc->err));
196 		else
197 			tst_res(TPASS | TTERRNO, "mq_timedreceive() failed expectedly");
198 
199 		return;
200 	}
201 
202 	if (tc->len != TST_RET) {
203 		tst_res(TFAIL, "mq_timedreceive() wrong length %ld, expected %u",
204 			TST_RET, tc->len);
205 		return;
206 	}
207 
208 	if (tc->prio != prio) {
209 		tst_res(TFAIL, "mq_timedreceive() wrong prio %d, expected %d",
210 			prio, tc->prio);
211 		return;
212 	}
213 
214 	for (j = 0; j < tc->len; j++) {
215 		if (rmsg[j] != smsg[j]) {
216 			tst_res(TFAIL,
217 				"mq_timedreceive() wrong data %d in %u, expected %d",
218 				rmsg[j], i, smsg[j]);
219 			return;
220 		}
221 	}
222 
223 	tst_res(TPASS, "mq_timedreceive() returned %ld, priority %u, length: %zu",
224 			TST_RET, prio, len);
225 }
226 
227 static struct tst_test test = {
228 	.tcnt = ARRAY_SIZE(tcase),
229 	.test = do_test,
230 	.test_variants = ARRAY_SIZE(variants),
231 	.setup = setup,
232 	.cleanup = cleanup_common,
233 	.forks_child = 1,
234 };
235