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