• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Crackerjack Project., 2007-2008, Hitachi, Ltd
3  * Copyright (c) 2017 Petr Vorel <pvorel@suse.cz>
4  *
5  * Authors:
6  * Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
7  * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
8  * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of
13  * the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it would be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program. If not, see <http://www.gnu.org/licenses/>.
22  */
23 
24 #include <errno.h>
25 #include <limits.h>
26 
27 static int fd, fd_root, fd_nonblock, fd_maxint = INT_MAX - 1, fd_invalid = -1;
28 static struct timespec ts;
29 
30 #include "mq_timed.h"
31 
32 static struct test_case tcase[] = {
33 	{
34 		.fd = &fd,
35 		.len = 0,
36 		.ret = 0,
37 		.err = 0,
38 	},
39 	{
40 		.fd = &fd,
41 		.len = 1,
42 		.ret = 0,
43 		.err = 0,
44 	},
45 	{
46 		.fd = &fd,
47 		.len = MAX_MSGSIZE,
48 		.ret = 0,
49 		.err = 0,
50 	},
51 	{
52 		.fd = &fd,
53 		.len = 1,
54 		.prio = MQ_PRIO_MAX - 1,
55 		.ret = 0,
56 		.err = 0,
57 	},
58 	{
59 		.fd = &fd,
60 		.len = MAX_MSGSIZE + 1,
61 		.ret = -1,
62 		.err = EMSGSIZE,
63 	},
64 	{
65 		.fd = &fd_invalid,
66 		.len = 0,
67 		.ret = -1,
68 		.err = EBADF,
69 	},
70 	{
71 		.fd = &fd_maxint,
72 		.len = 0,
73 		.ret = -1,
74 		.err = EBADF,
75 	},
76 	{
77 		.fd = &fd_root,
78 		.len = 0,
79 		.ret = -1,
80 		.err = EBADF,
81 	},
82 	{
83 		.fd = &fd_nonblock,
84 		.len = 16,
85 		.ret = -1,
86 		.err = EAGAIN,
87 	},
88 	{
89 		.fd = &fd,
90 		.len = 1,
91 		.prio = MQ_PRIO_MAX,
92 		.ret = -1,
93 		.err = EINVAL,
94 	},
95 	{
96 		.fd = &fd,
97 		.len = 16,
98 		.rq = &(struct timespec) {.tv_sec = -1, .tv_nsec = 0},
99 		.send = 1,
100 		.ret = -1,
101 		.err = EINVAL,
102 	},
103 	{
104 		.fd = &fd,
105 		.len = 16,
106 		.rq = &(struct timespec) {.tv_sec = 0, .tv_nsec = -1},
107 		.send = 1,
108 		.ret = -1,
109 		.err = EINVAL,
110 	},
111 	{
112 		.fd = &fd,
113 		.len = 16,
114 		.rq = &(struct timespec) {.tv_sec = 0, .tv_nsec = 1000000000},
115 		.send = 1,
116 		.ret = -1,
117 		.err = EINVAL,
118 	},
119 	{
120 		.fd = &fd,
121 		.len = 16,
122 		.rq = &ts,
123 		.send = 1,
124 		.timeout = 1,
125 		.ret = -1,
126 		.err = ETIMEDOUT,
127 	},
128 	{
129 		.fd = &fd,
130 		.len = 16,
131 		.send = 1,
132 		.signal = 1,
133 		.rq = &ts,
134 		.ret = -1,
135 		.err = EINTR,
136 	},
137 };
138 
do_test(unsigned int i)139 static void do_test(unsigned int i)
140 {
141 	const struct test_case *tc = &tcase[i];
142 	unsigned int j;
143 	unsigned int prio;
144 	size_t len = MAX_MSGSIZE;
145 	char rmsg[len];
146 	pid_t pid = -1;
147 
148 	if (tc->signal)
149 		pid = set_sig(tc->rq);
150 
151 	if (tc->timeout)
152 		set_timeout(tc->rq);
153 
154 	if (tc->send) {
155 		for (j = 0; j < MSG_LENGTH; j++)
156 			send_msg(*tc->fd, tc->len, tc->prio);
157 	}
158 
159 	TEST(mq_timedsend(*tc->fd, smsg, tc->len, tc->prio, tc->rq));
160 
161 	if (pid > 0)
162 		kill_pid(pid);
163 
164 	if (TST_RET < 0) {
165 		if (tc->err != TST_ERR)
166 			tst_res(TFAIL | TTERRNO,
167 				"mq_timedsend failed unexpectedly, expected %s",
168 				tst_strerrno(tc->err));
169 		else
170 			tst_res(TPASS | TTERRNO, "mq_timedreceive failed expectedly");
171 
172 		if (*tc->fd == fd)
173 			cleanup_queue(fd);
174 
175 		return;
176 	}
177 
178 	TEST(mq_timedreceive(*tc->fd, rmsg, len, &prio, tc->rq));
179 
180 	if (*tc->fd == fd)
181 		cleanup_queue(fd);
182 
183 	if (TST_RET < 0) {
184 		if (tc->err != TST_ERR) {
185 			tst_res(TFAIL | TTERRNO,
186 				"mq_timedreceive failed unexpectedly, expected %s",
187 				tst_strerrno(tc->err));
188 			return;
189 		}
190 
191 		if (tc->ret >= 0) {
192 			tst_res(TFAIL | TTERRNO, "mq_timedreceive returned %ld, expected %d",
193 					TST_RET, tc->ret);
194 			return;
195 		}
196 	}
197 
198 	if (tc->len != TST_RET) {
199 		tst_res(TFAIL, "mq_timedreceive wrong length %ld, expected %d",
200 			TST_RET, tc->len);
201 		return;
202 	}
203 
204 	if (tc->prio != prio) {
205 		tst_res(TFAIL, "mq_timedreceive wrong prio %d, expected %d",
206 			prio, tc->prio);
207 		return;
208 	}
209 
210 	for (j = 0; j < tc->len; j++) {
211 		if (rmsg[j] != smsg[j]) {
212 			tst_res(TFAIL,
213 				"mq_timedreceive wrong data %d in %u, expected %d",
214 				rmsg[j], i, smsg[j]);
215 			return;
216 		}
217 	}
218 
219 	tst_res(TPASS, "mq_timedreceive returned %ld, priority %u, length: %zu",
220 			TST_RET, prio, len);
221 }
222 
223 static struct tst_test test = {
224 	.tcnt = ARRAY_SIZE(tcase),
225 	.test = do_test,
226 	.setup = setup_common,
227 	.cleanup = cleanup_common,
228 	.forks_child = 1,
229 };
230