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