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 27static int fd, fd_root, fd_nonblock, fd_maxint = INT_MAX - 1, fd_invalid = -1; 28static struct timespec ts; 29 30#include "mq_timed.h" 31 32static 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 139static 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 (TEST_RETURN < 0) { 165 if (tc->err != TEST_ERRNO) 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 (TEST_RETURN < 0) { 184 if (tc->err != TEST_ERRNO) { 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 TEST_RETURN, tc->ret); 194 return; 195 } 196 } 197 198 if (tc->len != TEST_RETURN) { 199 tst_res(TFAIL, "mq_timedreceive wrong length %ld, expected %d", 200 TEST_RETURN, 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 TEST_RETURN, prio, len); 221} 222 223static 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