235 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			235 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			C
		
	
	
	
| // SPDX-License-Identifier: GPL-2.0-or-later
 | |
| /*
 | |
|  * Copyright (c) Crackerjack Project., 2007-2008, Hitachi, Ltd
 | |
|  * Copyright (c) 2017 Petr Vorel <pvorel@suse.cz>
 | |
|  *
 | |
|  * Authors:
 | |
|  * Takahiro Yasui <takahiro.yasui.mp@hitachi.com>,
 | |
|  * Yumiko Sugita <yumiko.sugita.yf@hitachi.com>,
 | |
|  * Satoshi Fujiwara <sa-fuji@sdl.hitachi.co.jp>
 | |
|  */
 | |
| 
 | |
| #include <errno.h>
 | |
| #include <limits.h>
 | |
| 
 | |
| static int fd, fd_root, fd_nonblock, fd_maxint = INT_MAX - 1, fd_invalid = -1;
 | |
| 
 | |
| #include "mq_timed.h"
 | |
| 
 | |
| static struct tst_ts ts;
 | |
| static void *bad_addr;
 | |
| 
 | |
| static struct test_case tcase[] = {
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = 0,
 | |
| 		.send = 1,
 | |
| 		.ret = 0,
 | |
| 		.err = 0,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = 1,
 | |
| 		.send = 1,
 | |
| 		.ret = 0,
 | |
| 		.err = 0,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = MAX_MSGSIZE,
 | |
| 		.send = 1,
 | |
| 		.ret = 0,
 | |
| 		.err = 0,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = 1,
 | |
| 		.send = 1,
 | |
| 		.prio = MQ_PRIO_MAX - 1,
 | |
| 		.ret = 0,
 | |
| 		.err = 0,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.invalid_msg = 1,
 | |
| 		.len = 0,
 | |
| 		.send = 1,
 | |
| 		.ret = -1,
 | |
| 		.err = EMSGSIZE,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd_invalid,
 | |
| 		.len = 0,
 | |
| 		.ret = -1,
 | |
| 		.err = EBADF,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd_maxint,
 | |
| 		.len = 0,
 | |
| 		.ret = -1,
 | |
| 		.err = EBADF,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd_root,
 | |
| 		.len = 0,
 | |
| 		.ret = -1,
 | |
| 		.err = EBADF,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd_nonblock,
 | |
| 		.len = 16,
 | |
| 		.ret = -1,
 | |
| 		.err = EAGAIN,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = 16,
 | |
| 		.tv_sec = -1,
 | |
| 		.tv_nsec = 0,
 | |
| 		.rq = &ts,
 | |
| 		.ret = -1,
 | |
| 		.err = EINVAL,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = 16,
 | |
| 		.tv_sec = 0,
 | |
| 		.tv_nsec = -1,
 | |
| 		.rq = &ts,
 | |
| 		.ret = -1,
 | |
| 		.err = EINVAL,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = 16,
 | |
| 		.tv_sec = 0,
 | |
| 		.tv_nsec = 1000000000,
 | |
| 		.rq = &ts,
 | |
| 		.ret = -1,
 | |
| 		.err = EINVAL,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = 16,
 | |
| 		.timeout = 1,
 | |
| 		.ret = -1,
 | |
| 		.rq = &ts,
 | |
| 		.err = ETIMEDOUT,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = 16,
 | |
| 		.signal = 1,
 | |
| 		.rq = &ts,
 | |
| 		.ret = -1,
 | |
| 		.err = EINTR,
 | |
| 	},
 | |
| 	{
 | |
| 		.fd = &fd,
 | |
| 		.len = 16,
 | |
| 		.bad_ts_addr = 1,
 | |
| 		.ret = -1,
 | |
| 		.err = EFAULT,
 | |
| 	}
 | |
| };
 | |
| 
 | |
| static void setup(void)
 | |
| {
 | |
| 	struct time64_variants *tv = &variants[tst_variant];
 | |
| 
 | |
| 	tst_res(TINFO, "Testing variant: %s", tv->desc);
 | |
| 	ts.type = tv->ts_type;
 | |
| 
 | |
| 	bad_addr = tst_get_bad_addr(NULL);
 | |
| 
 | |
| 	setup_common();
 | |
| }
 | |
| 
 | |
| static void do_test(unsigned int i)
 | |
| {
 | |
| 	struct time64_variants *tv = &variants[tst_variant];
 | |
| 	const struct test_case *tc = &tcase[i];
 | |
| 	unsigned int j;
 | |
| 	unsigned int prio;
 | |
| 	size_t len = MAX_MSGSIZE;
 | |
| 	char rmsg[len];
 | |
| 	pid_t pid = -1;
 | |
| 	void *abs_timeout;
 | |
| 
 | |
| 	tst_ts_set_sec(&ts, tc->tv_sec);
 | |
| 	tst_ts_set_nsec(&ts, tc->tv_nsec);
 | |
| 
 | |
| 	if (tc->signal)
 | |
| 		pid = set_sig(tc->rq, tv->clock_gettime);
 | |
| 
 | |
| 	if (tc->timeout)
 | |
| 		set_timeout(tc->rq, tv->clock_gettime);
 | |
| 
 | |
| 	if (tc->send) {
 | |
| 		if (tv->mqt_send(*tc->fd, smsg, tc->len, tc->prio, NULL) < 0) {
 | |
| 			tst_res(TFAIL | TTERRNO, "mq_timedsend() failed");
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (tc->invalid_msg)
 | |
| 		len -= 1;
 | |
| 
 | |
| 	if (tc->bad_ts_addr)
 | |
| 		abs_timeout = bad_addr;
 | |
| 	else
 | |
| 		abs_timeout = tst_ts_get(tc->rq);
 | |
| 
 | |
| 	TEST(tv->mqt_receive(*tc->fd, rmsg, len, &prio, abs_timeout));
 | |
| 
 | |
| 	if (pid > 0)
 | |
| 		kill_pid(pid);
 | |
| 
 | |
| 	if (*tc->fd == fd)
 | |
| 		cleanup_queue(fd);
 | |
| 
 | |
| 	if (TST_RET < 0) {
 | |
| 		if (tc->err != TST_ERR)
 | |
| 			tst_res(TFAIL | TTERRNO,
 | |
| 				"mq_timedreceive() failed unexpectedly, expected %s",
 | |
| 				tst_strerrno(tc->err));
 | |
| 		else
 | |
| 			tst_res(TPASS | TTERRNO, "mq_timedreceive() failed expectedly");
 | |
| 
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (tc->len != TST_RET) {
 | |
| 		tst_res(TFAIL, "mq_timedreceive() wrong length %ld, expected %u",
 | |
| 			TST_RET, tc->len);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	if (tc->prio != prio) {
 | |
| 		tst_res(TFAIL, "mq_timedreceive() wrong prio %d, expected %d",
 | |
| 			prio, tc->prio);
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	for (j = 0; j < tc->len; j++) {
 | |
| 		if (rmsg[j] != smsg[j]) {
 | |
| 			tst_res(TFAIL,
 | |
| 				"mq_timedreceive() wrong data %d in %u, expected %d",
 | |
| 				rmsg[j], i, smsg[j]);
 | |
| 			return;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	tst_res(TPASS, "mq_timedreceive() returned %ld, priority %u, length: %zu",
 | |
| 			TST_RET, prio, len);
 | |
| }
 | |
| 
 | |
| static struct tst_test test = {
 | |
| 	.tcnt = ARRAY_SIZE(tcase),
 | |
| 	.test = do_test,
 | |
| 	.test_variants = ARRAY_SIZE(variants),
 | |
| 	.setup = setup,
 | |
| 	.cleanup = cleanup_common,
 | |
| 	.forks_child = 1,
 | |
| };
 |