* [LTP] [PATCH v3 0/2] testcases/kernel/syscalls: Adding new testcases for existing tests
@ 2020-08-17 10:22 Filip Bozuta
2020-08-17 10:22 ` [LTP] [PATCH v3 1/2] syscalls/clock_nanosleep: add a test case for bad timespec address Filip Bozuta
2020-08-17 10:22 ` [LTP] [PATCH v3 2/2] syscalls/{send|recv}mmsg: add a test case for timeout and errno test Filip Bozuta
0 siblings, 2 replies; 7+ messages in thread
From: Filip Bozuta @ 2020-08-17 10:22 UTC (permalink / raw)
To: ltp
This series introduces new test cases for existing tests for syscalls:
* clock_nanosleep()
* sendmmsg()
* recvmmsg()
* First patch in the series introduces bad timespec address cases
for 'clock_nanosleep()'
* Second patch in the series introduces a timeout case and an errno
test for 'sendmmsg()' and 'recvmmsg()'
More detailed descriptions of these newly added test cases and the
implementation details can be found in this series patch commit
messages.
These new test cases are part of my work of implementation for 2038
safe variants of the above mentioned syscalls in QEMU:
* clock_nanosleep_time64()
* recvmmsg_time64()
These test cases are needed to make sure that QEMU implementations of
the above mentioned time64 syscalls work properly.
These test cases are also used to fix some minor issues with already
existing implementations of regular variants of these syscalls.
v2:
* Changed bad address values from (void *)1 to using function
'tst_get_bad_addr()'
* Removed unnecessary implementation descriptions that can be
seen from the patches
v3:
* Removed first patch from the series as it got pushed
* Moved the bad adrress intilization in the test 'setup()' part
Filip Bozuta (2):
syscalls/clock_nanosleep: add a test case for bad timespec address
syscalls/{send|recv}mmsg: add a test case for timeout and errno test
runtest/syscalls | 1 +
.../clock_nanosleep/clock_nanosleep01.c | 43 +++-
testcases/kernel/syscalls/sendmmsg/.gitignore | 1 +
.../kernel/syscalls/sendmmsg/sendmmsg01.c | 68 +++--
.../kernel/syscalls/sendmmsg/sendmmsg02.c | 235 ++++++++++++++++++
5 files changed, 329 insertions(+), 19 deletions(-)
create mode 100644 testcases/kernel/syscalls/sendmmsg/sendmmsg02.c
--
2.25.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [LTP] [PATCH v3 1/2] syscalls/clock_nanosleep: add a test case for bad timespec address
2020-08-17 10:22 [LTP] [PATCH v3 0/2] testcases/kernel/syscalls: Adding new testcases for existing tests Filip Bozuta
@ 2020-08-17 10:22 ` Filip Bozuta
2020-08-18 13:37 ` Cyril Hrubis
2020-08-17 10:22 ` [LTP] [PATCH v3 2/2] syscalls/{send|recv}mmsg: add a test case for timeout and errno test Filip Bozuta
1 sibling, 1 reply; 7+ messages in thread
From: Filip Bozuta @ 2020-08-17 10:22 UTC (permalink / raw)
To: ltp
This patch introduces test cases for already existing test
for syscall 'clock_nanosleep()' (clock_nanosleep01). These test
cases are for situations when bad timespec addresses are passed
for arguments 'request' and 'remain' in which case errno
EFAULT ('Bad address') is expected to be set.
Signed-off-by: Filip Bozuta <Filip.Bozuta@syrmia.com>
---
.../clock_nanosleep/clock_nanosleep01.c | 43 +++++++++++++++++--
1 file changed, 39 insertions(+), 4 deletions(-)
diff --git a/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep01.c b/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep01.c
index 4542995f2..fe5f4d7c7 100644
--- a/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep01.c
+++ b/testcases/kernel/syscalls/clock_nanosleep/clock_nanosleep01.c
@@ -20,10 +20,14 @@ static void sighandler(int sig LTP_ATTRIBUTE_UNUSED)
enum test_type {
NORMAL,
SEND_SIGINT,
+ BAD_TS_ADDR_REQ,
+ BAD_TS_ADDR_REM,
};
#define TYPE_NAME(x) .ttype = x, .desc = #x
+static void *bad_addr;
+
struct test_case {
clockid_t clk_id; /* clock_* clock type parameter */
int ttype; /* test type (enum) */
@@ -37,8 +41,11 @@ struct test_case {
/*
* test status of errors on man page
- * EINTR v (function was interrupted by a signal)
- * EINVAL v (invalid tv_nsec, etc.)
+ * EINTR v (function was interrupted by a signal)
+ * EINVAL v (invalid tv_nsec, etc.)
+ * ENOTSUP v (sleep not supported against the specified clock_id)
+ * EFAULT v (Invalid request pointer)
+ * EFAULT V (Invalid remain pointer when interrupted by a signal)
*/
static struct test_case tcase[] = {
@@ -78,6 +85,22 @@ static struct test_case tcase[] = {
.exp_ret = -1,
.exp_err = EINTR,
},
+ {
+ TYPE_NAME(BAD_TS_ADDR_REQ),
+ .clk_id = CLOCK_REALTIME,
+ .flags = 0,
+ .exp_ret = -1,
+ .exp_err = EFAULT,
+ },
+ {
+ TYPE_NAME(BAD_TS_ADDR_REM),
+ .clk_id = CLOCK_REALTIME,
+ .flags = 0,
+ .tv_sec = 10,
+ .tv_nsec = 0,
+ .exp_ret = -1,
+ .exp_err = EFAULT,
+ },
};
static struct tst_ts *rq;
@@ -104,6 +127,7 @@ void setup(void)
rq->type = variants[tst_variant].type;
tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
SAFE_SIGNAL(SIGINT, sighandler);
+ bad_addr = tst_get_bad_addr(NULL);
}
static void do_test(unsigned int i)
@@ -111,19 +135,30 @@ static void do_test(unsigned int i)
struct test_variants *tv = &variants[tst_variant];
struct test_case *tc = &tcase[i];
pid_t pid = 0;
+ void *request, *remain;
memset(rm, 0, sizeof(*rm));
rm->type = rq->type;
tst_res(TINFO, "case %s", tc->desc);
- if (tc->ttype == SEND_SIGINT)
+ if (tc->ttype == SEND_SIGINT || tc->ttype == BAD_TS_ADDR_REM)
pid = create_sig_proc(SIGINT, 40, 500000);
tst_ts_set_sec(rq, tc->tv_sec);
tst_ts_set_nsec(rq, tc->tv_nsec);
- TEST(tv->func(tc->clk_id, tc->flags, tst_ts_get(rq), tst_ts_get(rm)));
+ if (tc->ttype == BAD_TS_ADDR_REQ)
+ request = bad_addr;
+ else
+ request = tst_ts_get(rq);
+
+ if (tc->ttype == BAD_TS_ADDR_REM)
+ remain = bad_addr;
+ else
+ remain = tst_ts_get(rm);
+
+ TEST(tv->func(tc->clk_id, tc->flags, request, remain));
if (tv->func == libc_clock_nanosleep) {
/*
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/{send|recv}mmsg: add a test case for timeout and errno test
2020-08-17 10:22 [LTP] [PATCH v3 0/2] testcases/kernel/syscalls: Adding new testcases for existing tests Filip Bozuta
2020-08-17 10:22 ` [LTP] [PATCH v3 1/2] syscalls/clock_nanosleep: add a test case for bad timespec address Filip Bozuta
@ 2020-08-17 10:22 ` Filip Bozuta
2020-08-18 14:37 ` Cyril Hrubis
1 sibling, 1 reply; 7+ messages in thread
From: Filip Bozuta @ 2020-08-17 10:22 UTC (permalink / raw)
To: ltp
This patch introduces a test case for the already existing test for
syscalls 'sendmmsg()' and 'recvmmsg()' (sendmmsg01). This test
case is meant to check whether the timeout is reached aproppriately
after the first message is received. The timeout is set to 1 nsec as to
make sure that it has to be reached. In this case the expected return
value is 1 as the second message is not supposed be received after the
timeout is reached.
* Note: No matter how small the timeout is, one message is always gonna
have to be received because the timeout is checked only after a received
message. This is an existing bug for syscall 'recvmmsg()':
https://man7.org/linux/man-pages/man2/recvmmsg.2.html#BUGS
This patch introduces a new test file for these syscalls (sendmmsg02.c).
This test file is meant to check whether the aproppriate errno is set in
some sitautions when these syscalls fail. These situations include:
bad socket file descriptor (EBADF), bad message vector address (EFAULT),
bad timeout value (EINVAL), bad timeout address (EFAULT).
Signed-off-by: Filip Bozuta <Filip.Bozuta@syrmia.com>
---
runtest/syscalls | 1 +
testcases/kernel/syscalls/sendmmsg/.gitignore | 1 +
.../kernel/syscalls/sendmmsg/sendmmsg01.c | 68 +++--
.../kernel/syscalls/sendmmsg/sendmmsg02.c | 235 ++++++++++++++++++
4 files changed, 290 insertions(+), 15 deletions(-)
create mode 100644 testcases/kernel/syscalls/sendmmsg/sendmmsg02.c
diff --git a/runtest/syscalls b/runtest/syscalls
index c2bfc6df3..7c2f71e0c 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -1200,6 +1200,7 @@ sendmsg02 sendmsg02
sendmsg03 sendmsg03
sendmmsg01 sendmmsg01
+sendmmsg02 sendmmsg02
sendto01 sendto01
sendto02 sendto02
diff --git a/testcases/kernel/syscalls/sendmmsg/.gitignore b/testcases/kernel/syscalls/sendmmsg/.gitignore
index b703ececd..42693c44d 100644
--- a/testcases/kernel/syscalls/sendmmsg/.gitignore
+++ b/testcases/kernel/syscalls/sendmmsg/.gitignore
@@ -1 +1,2 @@
sendmmsg01
+sendmmsg02
diff --git a/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c b/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c
index 54febf661..d7d5d33cc 100644
--- a/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c
+++ b/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c
@@ -24,6 +24,36 @@ static int receive_sockfd;
static struct mmsghdr *snd_msg, *rcv_msg;
static struct iovec *snd1, *snd2, *rcv1, *rcv2;
+enum test_type {
+ NORMAL,
+ TIMEOUT,
+};
+
+#define TYPE_NAME(x) .ttype = x, .desc = #x
+
+struct test_case {
+ int ttype;
+ const char *desc;
+ long tv_sec;
+ long tv_nsec;
+ int exp_ret;
+};
+
+static struct test_case tcase[] = {
+ {
+ TYPE_NAME(NORMAL),
+ .tv_sec = 1,
+ .tv_nsec = 0,
+ .exp_ret = 2,
+ },
+ {
+ TYPE_NAME(TIMEOUT),
+ .tv_sec = 0,
+ .tv_nsec = 1,
+ .exp_ret = 1,
+ },
+};
+
static struct test_variants {
int (*receive)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
unsigned int flags, void *timeout);
@@ -43,14 +73,17 @@ static struct test_variants {
#endif
};
-static void run(void)
+static void do_test(unsigned int i)
{
struct test_variants *tv = &variants[tst_variant];
+ struct test_case *tc = &tcase[i];
struct tst_ts timeout;
- int retval;
- retval = tv->send(send_sockfd, snd_msg, VLEN, 0);
- if (retval < 0 || snd_msg[0].msg_len != 6 || snd_msg[1].msg_len != 6) {
+ tst_res(TINFO, "case %s", tc->desc);
+
+ TEST(tv->send(send_sockfd, snd_msg, VLEN, 0));
+
+ if (TST_RET < 0 || snd_msg[0].msg_len != 6 || snd_msg[1].msg_len != 6) {
tst_res(TFAIL | TERRNO, "sendmmsg() failed");
return;
}
@@ -59,18 +92,18 @@ static void run(void)
memset(rcv2->iov_base, 0, rcv2->iov_len);
timeout.type = tv->type;
- tst_ts_set_sec(&timeout, 1);
- tst_ts_set_nsec(&timeout, 0);
+ tst_ts_set_sec(&timeout, tc->tv_sec);
+ tst_ts_set_nsec(&timeout, tc->tv_nsec);
- retval = tv->receive(receive_sockfd, rcv_msg, VLEN, 0, tst_ts_get(&timeout));
+ TEST(tv->receive(receive_sockfd, rcv_msg, VLEN, 0, tst_ts_get(&timeout)));
- if (retval == -1) {
+ if (TST_RET == -1) {
tst_res(TFAIL | TERRNO, "recvmmsg() failed");
return;
}
- if (retval != 2) {
+ if (tc->exp_ret != TST_RET) {
tst_res(TFAIL, "Received unexpected number of messages (%d)",
- retval);
+ TST_RET);
return;
}
@@ -79,10 +112,14 @@ static void run(void)
else
tst_res(TPASS, "First message received successfully");
- if (memcmp(rcv2->iov_base, "three", 5))
- tst_res(TFAIL, "Error in second received message");
- else
- tst_res(TPASS, "Second message received successfully");
+ if (tc->ttype == NORMAL) {
+ if (memcmp(rcv2->iov_base, "three", 5))
+ tst_res(TFAIL, "Error in second received message");
+ else
+ tst_res(TPASS, "Second message received successfully");
+ } else {
+ tst_res(TPASS, "Timeout successfully reached before second message");
+ }
}
static void setup(void)
@@ -128,7 +165,8 @@ static void cleanup(void)
}
static struct tst_test test = {
- .test_all = run,
+ .tcnt = ARRAY_SIZE(tcase),
+ .test = do_test,
.setup = setup,
.cleanup = cleanup,
.test_variants = ARRAY_SIZE(variants),
diff --git a/testcases/kernel/syscalls/sendmmsg/sendmmsg02.c b/testcases/kernel/syscalls/sendmmsg/sendmmsg02.c
new file mode 100644
index 000000000..37e6ea66e
--- /dev/null
+++ b/testcases/kernel/syscalls/sendmmsg/sendmmsg02.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#define _GNU_SOURCE
+#include <netinet/ip.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "tst_test.h"
+#include "lapi/socket.h"
+#include "tst_safe_macros.h"
+#include "sendmmsg_var.h"
+
+#define BUFSIZE 16
+#define VLEN 2
+
+static int send_sockfd;
+static int receive_sockfd;
+static struct mmsghdr *snd_msg, *rcv_msg;
+static struct iovec *snd1, *snd2, *rcv1, *rcv2;
+static struct tst_ts ts;
+
+enum test_type {
+ BAD_SEND_FD,
+ BAD_RECV_FD,
+ BAD_SEND_MSGVEC,
+ BAD_RECV_MSGVEC,
+ BAD_TS_VALUE_1,
+ BAD_TS_VALUE_2,
+ BAD_TS_ADDR,
+};
+
+#define TYPE_NAME(x) .ttype = x, .desc = #x
+
+static void *bad_addr;
+
+struct test_case {
+ int ttype;
+ const char *desc;
+ int send_fd;
+ int recv_fd;
+ long tv_sec;
+ long tv_nsec;
+ int exp_send_ret;
+ int exp_send_errno;
+ int exp_recv_errno;
+};
+
+static struct test_case tcase[] = {
+ {
+ TYPE_NAME(BAD_SEND_FD),
+ .send_fd = -1,
+ .exp_send_ret = -1,
+ .exp_send_errno = EBADF,
+ },
+ {
+ TYPE_NAME(BAD_RECV_FD),
+ .exp_send_ret = VLEN,
+ .recv_fd = -1,
+ .exp_recv_errno = EBADF,
+ },
+ {
+ TYPE_NAME(BAD_SEND_MSGVEC),
+ .exp_send_ret = -1,
+ .exp_send_errno = EFAULT,
+ },
+ {
+ TYPE_NAME(BAD_RECV_MSGVEC),
+ .exp_send_ret = VLEN,
+ .exp_recv_errno = EFAULT,
+ },
+ {
+ TYPE_NAME(BAD_TS_VALUE_1),
+ .exp_send_ret = VLEN,
+ .tv_sec = -1,
+ .tv_nsec = 0,
+ .exp_recv_errno = EINVAL,
+ },
+ {
+ TYPE_NAME(BAD_TS_VALUE_2),
+ .exp_send_ret = VLEN,
+ .tv_sec = 1,
+ .tv_nsec = 1000000001,
+ .exp_recv_errno = EINVAL,
+ },
+ {
+ TYPE_NAME(BAD_TS_ADDR),
+ .exp_send_ret = VLEN,
+ .exp_recv_errno = EFAULT,
+ }
+};
+
+static struct test_variants {
+ int (*receive)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
+ unsigned int flags, void *timeout);
+ int (*send)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
+ unsigned int flags);
+ enum tst_ts_type type;
+ char *desc;
+} variants[] = {
+ { .receive = libc_recvmmsg, .send = libc_sendmmsg, .type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
+
+#if (__NR_recvmmsg != __LTP__NR_INVALID_SYSCALL)
+ { .receive = sys_recvmmsg, .send = sys_sendmmsg, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
+#endif
+
+#if (__NR_recvmmsg_time64 != __LTP__NR_INVALID_SYSCALL)
+ { .receive = sys_recvmmsg64, .send = sys_sendmmsg, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
+#endif
+};
+
+static void cleanup(void)
+{
+ if (send_sockfd > 0)
+ SAFE_CLOSE(send_sockfd);
+ if (receive_sockfd > 0)
+ SAFE_CLOSE(receive_sockfd);
+}
+
+static void do_test(unsigned int i)
+{
+ struct test_variants *tv = &variants[tst_variant];
+ struct test_case *tc = &tcase[i];
+ void *snd_msgvec, *rcv_msgvec, *timeout;
+
+ tst_res(TINFO, "case %s", tc->desc);
+
+ if (tc->ttype != BAD_SEND_FD)
+ tc->send_fd = send_sockfd;
+ if (tc->ttype != BAD_RECV_FD)
+ tc->recv_fd = receive_sockfd;
+
+ if (tc->ttype == BAD_SEND_MSGVEC)
+ snd_msgvec = bad_addr;
+ else
+ snd_msgvec = snd_msg;
+
+ TEST(tv->send(tc->send_fd, snd_msgvec, VLEN, 0));
+
+ if (TST_RET < 0) {
+ if (tc->exp_send_ret != TST_RET || errno != tc->exp_send_errno)
+ tst_res(TFAIL | TERRNO, "sendmmsg() failed unexpectedly");
+ else
+ tst_res(TPASS | TERRNO, "sendmmg() failed successfully");
+ return;
+ }
+
+ if (tc->exp_send_ret != TST_RET || snd_msg[0].msg_len != 6 ||
+ snd_msg[1].msg_len != 6) {
+ tst_res(TFAIL | TERRNO, "sendmmsg() failed");
+ return;
+ }
+
+ memset(rcv1->iov_base, 0, rcv1->iov_len);
+ memset(rcv2->iov_base, 0, rcv2->iov_len);
+
+ ts.type = tv->type;
+ tst_ts_set_sec(&ts, tc->tv_sec);
+ tst_ts_set_nsec(&ts, tc->tv_nsec);
+
+ if (tc->ttype == BAD_RECV_MSGVEC)
+ rcv_msgvec = bad_addr;
+ else
+ rcv_msgvec = rcv_msg;
+
+ if (tc->ttype == BAD_TS_ADDR)
+ timeout = bad_addr;
+ else
+ timeout = tst_ts_get(&ts);
+
+ TEST(tv->receive(tc->recv_fd, rcv_msgvec, VLEN, 0, timeout));
+
+ if (TST_RET < 0) {
+ if (tc->exp_recv_errno == errno)
+ tst_res(TPASS | TERRNO, "receivemmsg() failed successfully");
+ else
+ tst_res(TFAIL | TERRNO, "receivemmsg() failed unexpectedly");
+ } else {
+ tst_res(TFAIL | TERRNO, "receivemmsg() succeded unexpectedly");
+ }
+}
+
+static void setup(void)
+{
+ struct sockaddr_in addr;
+ unsigned int port = TST_GET_UNUSED_PORT(AF_INET, SOCK_DGRAM);
+
+ send_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0);
+ receive_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0);
+
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ addr.sin_port = port;
+
+ SAFE_BIND(receive_sockfd, (struct sockaddr *)&addr, sizeof(addr));
+ SAFE_CONNECT(send_sockfd, (struct sockaddr *)&addr, sizeof(addr));
+
+ memcpy(snd1[0].iov_base, "one", snd1[0].iov_len);
+ memcpy(snd1[1].iov_base, "two", snd1[1].iov_len);
+ memcpy(snd2->iov_base, "three3", snd2->iov_len);
+
+ memset(snd_msg, 0, VLEN * sizeof(*snd_msg));
+ snd_msg[0].msg_hdr.msg_iov = snd1;
+ snd_msg[0].msg_hdr.msg_iovlen = 2;
+ snd_msg[1].msg_hdr.msg_iov = snd2;
+ snd_msg[1].msg_hdr.msg_iovlen = 1;
+
+ memset(rcv_msg, 0, VLEN * sizeof(*rcv_msg));
+ rcv_msg[0].msg_hdr.msg_iov = rcv1;
+ rcv_msg[0].msg_hdr.msg_iovlen = 1;
+ rcv_msg[1].msg_hdr.msg_iov = rcv2;
+ rcv_msg[1].msg_hdr.msg_iovlen = 1;
+
+ bad_addr = tst_get_bad_addr(cleanup);
+
+ tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
+}
+
+static struct tst_test test = {
+ .tcnt = ARRAY_SIZE(tcase),
+ .test = do_test,
+ .setup = setup,
+ .cleanup = cleanup,
+ .test_variants = ARRAY_SIZE(variants),
+ .bufs = (struct tst_buffers []) {
+ {&snd1, .iov_sizes = (int[]){3, 3, -1}},
+ {&snd2, .iov_sizes = (int[]){6, -1}},
+ {&rcv1, .iov_sizes = (int[]){6, -1}},
+ {&rcv2, .iov_sizes = (int[]){5, -1}},
+ {&snd_msg, .size = VLEN * sizeof(*snd_msg)},
+ {&rcv_msg, .size = VLEN * sizeof(*rcv_msg)},
+ {},
+ }
+};
--
2.25.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [LTP] [PATCH v3 1/2] syscalls/clock_nanosleep: add a test case for bad timespec address
2020-08-17 10:22 ` [LTP] [PATCH v3 1/2] syscalls/clock_nanosleep: add a test case for bad timespec address Filip Bozuta
@ 2020-08-18 13:37 ` Cyril Hrubis
0 siblings, 0 replies; 7+ messages in thread
From: Cyril Hrubis @ 2020-08-18 13:37 UTC (permalink / raw)
To: ltp
Hi!
I've moved the comment about covered errors to the top of the source
code (just after copyrights) so that we are consistent with the rest of
the testcases and pushed, thanks.
--
Cyril Hrubis
chrubis@suse.cz
^ permalink raw reply [flat|nested] 7+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/{send|recv}mmsg: add a test case for timeout and errno test
2020-08-17 10:22 ` [LTP] [PATCH v3 2/2] syscalls/{send|recv}mmsg: add a test case for timeout and errno test Filip Bozuta
@ 2020-08-18 14:37 ` Cyril Hrubis
2020-09-08 15:12 ` Cyril Hrubis
0 siblings, 1 reply; 7+ messages in thread
From: Cyril Hrubis @ 2020-08-18 14:37 UTC (permalink / raw)
To: ltp
Hi!
> diff --git a/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c b/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c
> index 54febf661..d7d5d33cc 100644
> --- a/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c
> +++ b/testcases/kernel/syscalls/sendmmsg/sendmmsg01.c
> @@ -24,6 +24,36 @@ static int receive_sockfd;
> static struct mmsghdr *snd_msg, *rcv_msg;
> static struct iovec *snd1, *snd2, *rcv1, *rcv2;
>
> +enum test_type {
> + NORMAL,
> + TIMEOUT,
> +};
> +
> +#define TYPE_NAME(x) .ttype = x, .desc = #x
> +
> +struct test_case {
> + int ttype;
> + const char *desc;
> + long tv_sec;
> + long tv_nsec;
> + int exp_ret;
> +};
> +
> +static struct test_case tcase[] = {
> + {
> + TYPE_NAME(NORMAL),
> + .tv_sec = 1,
> + .tv_nsec = 0,
> + .exp_ret = 2,
> + },
> + {
> + TYPE_NAME(TIMEOUT),
> + .tv_sec = 0,
> + .tv_nsec = 1,
> + .exp_ret = 1,
The manual states that the timeout is checked after each datagram is
received so I guess that we can as well set the timeout here to both sec
and nsec to zero which would be a bit more clear than nsec = 1.
> + },
> +};
> +
> static struct test_variants {
> int (*receive)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
> unsigned int flags, void *timeout);
> @@ -43,14 +73,17 @@ static struct test_variants {
> #endif
> };
>
> -static void run(void)
> +static void do_test(unsigned int i)
> {
> struct test_variants *tv = &variants[tst_variant];
> + struct test_case *tc = &tcase[i];
> struct tst_ts timeout;
> - int retval;
>
> - retval = tv->send(send_sockfd, snd_msg, VLEN, 0);
> - if (retval < 0 || snd_msg[0].msg_len != 6 || snd_msg[1].msg_len != 6) {
> + tst_res(TINFO, "case %s", tc->desc);
> +
> + TEST(tv->send(send_sockfd, snd_msg, VLEN, 0));
> +
> + if (TST_RET < 0 || snd_msg[0].msg_len != 6 || snd_msg[1].msg_len != 6) {
> tst_res(TFAIL | TERRNO, "sendmmsg() failed");
> return;
> }
> @@ -59,18 +92,18 @@ static void run(void)
> memset(rcv2->iov_base, 0, rcv2->iov_len);
>
> timeout.type = tv->type;
> - tst_ts_set_sec(&timeout, 1);
> - tst_ts_set_nsec(&timeout, 0);
> + tst_ts_set_sec(&timeout, tc->tv_sec);
> + tst_ts_set_nsec(&timeout, tc->tv_nsec);
>
> - retval = tv->receive(receive_sockfd, rcv_msg, VLEN, 0, tst_ts_get(&timeout));
> + TEST(tv->receive(receive_sockfd, rcv_msg, VLEN, 0, tst_ts_get(&timeout)));
>
> - if (retval == -1) {
> + if (TST_RET == -1) {
> tst_res(TFAIL | TERRNO, "recvmmsg() failed");
> return;
> }
> - if (retval != 2) {
> + if (tc->exp_ret != TST_RET) {
> tst_res(TFAIL, "Received unexpected number of messages (%d)",
> - retval);
> + TST_RET);
> return;
> }
>
> @@ -79,10 +112,14 @@ static void run(void)
> else
> tst_res(TPASS, "First message received successfully");
>
> - if (memcmp(rcv2->iov_base, "three", 5))
> - tst_res(TFAIL, "Error in second received message");
> - else
> - tst_res(TPASS, "Second message received successfully");
> + if (tc->ttype == NORMAL) {
> + if (memcmp(rcv2->iov_base, "three", 5))
> + tst_res(TFAIL, "Error in second received message");
> + else
> + tst_res(TPASS, "Second message received successfully");
> + } else {
> + tst_res(TPASS, "Timeout successfully reached before second message");
This actually breaks the test with -i 2 option, which runs the run()
function twice.
We have to receive the second message here as well for the timeout test.
> + }
> }
>
> static void setup(void)
> @@ -128,7 +165,8 @@ static void cleanup(void)
> }
>
> static struct tst_test test = {
> - .test_all = run,
> + .tcnt = ARRAY_SIZE(tcase),
> + .test = do_test,
> .setup = setup,
> .cleanup = cleanup,
> .test_variants = ARRAY_SIZE(variants),
> diff --git a/testcases/kernel/syscalls/sendmmsg/sendmmsg02.c b/testcases/kernel/syscalls/sendmmsg/sendmmsg02.c
> new file mode 100644
> index 000000000..37e6ea66e
> --- /dev/null
> +++ b/testcases/kernel/syscalls/sendmmsg/sendmmsg02.c
> @@ -0,0 +1,235 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
Can we please include a comment with a high level description of the
test here?
> +#define _GNU_SOURCE
> +#include <netinet/ip.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/types.h>
> +
> +#include "tst_test.h"
> +#include "lapi/socket.h"
> +#include "tst_safe_macros.h"
> +#include "sendmmsg_var.h"
> +
> +#define BUFSIZE 16
> +#define VLEN 2
> +
> +static int send_sockfd;
> +static int receive_sockfd;
> +static struct mmsghdr *snd_msg, *rcv_msg;
> +static struct iovec *snd1, *snd2, *rcv1, *rcv2;
> +static struct tst_ts ts;
> +
> +enum test_type {
> + BAD_SEND_FD,
> + BAD_RECV_FD,
> + BAD_SEND_MSGVEC,
> + BAD_RECV_MSGVEC,
> + BAD_TS_VALUE_1,
> + BAD_TS_VALUE_2,
> + BAD_TS_ADDR,
> +};
> +
> +#define TYPE_NAME(x) .ttype = x, .desc = #x
> +
> +static void *bad_addr;
> +
> +struct test_case {
> + int ttype;
> + const char *desc;
> + int send_fd;
> + int recv_fd;
> + long tv_sec;
> + long tv_nsec;
> + int exp_send_ret;
> + int exp_send_errno;
> + int exp_recv_errno;
> +};
> +
> +static struct test_case tcase[] = {
> + {
> + TYPE_NAME(BAD_SEND_FD),
> + .send_fd = -1,
> + .exp_send_ret = -1,
> + .exp_send_errno = EBADF,
> + },
> + {
> + TYPE_NAME(BAD_RECV_FD),
> + .exp_send_ret = VLEN,
> + .recv_fd = -1,
> + .exp_recv_errno = EBADF,
> + },
> + {
> + TYPE_NAME(BAD_SEND_MSGVEC),
> + .exp_send_ret = -1,
> + .exp_send_errno = EFAULT,
> + },
> + {
> + TYPE_NAME(BAD_RECV_MSGVEC),
> + .exp_send_ret = VLEN,
> + .exp_recv_errno = EFAULT,
> + },
> + {
> + TYPE_NAME(BAD_TS_VALUE_1),
> + .exp_send_ret = VLEN,
> + .tv_sec = -1,
> + .tv_nsec = 0,
> + .exp_recv_errno = EINVAL,
> + },
> + {
> + TYPE_NAME(BAD_TS_VALUE_2),
> + .exp_send_ret = VLEN,
> + .tv_sec = 1,
> + .tv_nsec = 1000000001,
> + .exp_recv_errno = EINVAL,
> + },
> + {
> + TYPE_NAME(BAD_TS_ADDR),
> + .exp_send_ret = VLEN,
> + .exp_recv_errno = EFAULT,
> + }
> +};
> +
> +static struct test_variants {
> + int (*receive)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
> + unsigned int flags, void *timeout);
> + int (*send)(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
> + unsigned int flags);
> + enum tst_ts_type type;
> + char *desc;
> +} variants[] = {
> + { .receive = libc_recvmmsg, .send = libc_sendmmsg, .type = TST_LIBC_TIMESPEC, .desc = "vDSO or syscall with libc spec"},
> +
> +#if (__NR_recvmmsg != __LTP__NR_INVALID_SYSCALL)
> + { .receive = sys_recvmmsg, .send = sys_sendmmsg, .type = TST_KERN_OLD_TIMESPEC, .desc = "syscall with old kernel spec"},
> +#endif
> +
> +#if (__NR_recvmmsg_time64 != __LTP__NR_INVALID_SYSCALL)
> + { .receive = sys_recvmmsg64, .send = sys_sendmmsg, .type = TST_KERN_TIMESPEC, .desc = "syscall time64 with kernel spec"},
> +#endif
> +};
Technically the recvmmsg tests should be in a recvmmsg01.c.
We can put the test_variants array to a common header though.
> +static void cleanup(void)
> +{
> + if (send_sockfd > 0)
> + SAFE_CLOSE(send_sockfd);
> + if (receive_sockfd > 0)
> + SAFE_CLOSE(receive_sockfd);
> +}
> +
> +static void do_test(unsigned int i)
> +{
> + struct test_variants *tv = &variants[tst_variant];
> + struct test_case *tc = &tcase[i];
> + void *snd_msgvec, *rcv_msgvec, *timeout;
> +
> + tst_res(TINFO, "case %s", tc->desc);
> +
> + if (tc->ttype != BAD_SEND_FD)
> + tc->send_fd = send_sockfd;
> + if (tc->ttype != BAD_RECV_FD)
> + tc->recv_fd = receive_sockfd;
> +
> + if (tc->ttype == BAD_SEND_MSGVEC)
> + snd_msgvec = bad_addr;
> + else
> + snd_msgvec = snd_msg;
> +
> + TEST(tv->send(tc->send_fd, snd_msgvec, VLEN, 0));
> +
> + if (TST_RET < 0) {
> + if (tc->exp_send_ret != TST_RET || errno != tc->exp_send_errno)
> + tst_res(TFAIL | TERRNO, "sendmmsg() failed unexpectedly");
> + else
> + tst_res(TPASS | TERRNO, "sendmmg() failed successfully");
> + return;
> + }
> +
> + if (tc->exp_send_ret != TST_RET || snd_msg[0].msg_len != 6 ||
> + snd_msg[1].msg_len != 6) {
> + tst_res(TFAIL | TERRNO, "sendmmsg() failed");
> + return;
> + }
> +
> + memset(rcv1->iov_base, 0, rcv1->iov_len);
> + memset(rcv2->iov_base, 0, rcv2->iov_len);
> +
> + ts.type = tv->type;
> + tst_ts_set_sec(&ts, tc->tv_sec);
> + tst_ts_set_nsec(&ts, tc->tv_nsec);
> +
> + if (tc->ttype == BAD_RECV_MSGVEC)
> + rcv_msgvec = bad_addr;
> + else
> + rcv_msgvec = rcv_msg;
> +
> + if (tc->ttype == BAD_TS_ADDR)
> + timeout = bad_addr;
> + else
> + timeout = tst_ts_get(&ts);
> +
> + TEST(tv->receive(tc->recv_fd, rcv_msgvec, VLEN, 0, timeout));
> +
> + if (TST_RET < 0) {
> + if (tc->exp_recv_errno == errno)
> + tst_res(TPASS | TERRNO, "receivemmsg() failed successfully");
> + else
> + tst_res(TFAIL | TERRNO, "receivemmsg() failed unexpectedly");
> + } else {
> + tst_res(TFAIL | TERRNO, "receivemmsg() succeded unexpectedly");
> + }
> +}
> +
> +static void setup(void)
> +{
> + struct sockaddr_in addr;
> + unsigned int port = TST_GET_UNUSED_PORT(AF_INET, SOCK_DGRAM);
> +
> + send_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0);
> + receive_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0);
> +
> + addr.sin_family = AF_INET;
> + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
> + addr.sin_port = port;
> +
> + SAFE_BIND(receive_sockfd, (struct sockaddr *)&addr, sizeof(addr));
> + SAFE_CONNECT(send_sockfd, (struct sockaddr *)&addr, sizeof(addr));
> +
> + memcpy(snd1[0].iov_base, "one", snd1[0].iov_len);
> + memcpy(snd1[1].iov_base, "two", snd1[1].iov_len);
> + memcpy(snd2->iov_base, "three3", snd2->iov_len);
> +
> + memset(snd_msg, 0, VLEN * sizeof(*snd_msg));
> + snd_msg[0].msg_hdr.msg_iov = snd1;
> + snd_msg[0].msg_hdr.msg_iovlen = 2;
> + snd_msg[1].msg_hdr.msg_iov = snd2;
> + snd_msg[1].msg_hdr.msg_iovlen = 1;
> +
> + memset(rcv_msg, 0, VLEN * sizeof(*rcv_msg));
> + rcv_msg[0].msg_hdr.msg_iov = rcv1;
> + rcv_msg[0].msg_hdr.msg_iovlen = 1;
> + rcv_msg[1].msg_hdr.msg_iov = rcv2;
> + rcv_msg[1].msg_hdr.msg_iovlen = 1;
> +
> + bad_addr = tst_get_bad_addr(cleanup);
^
This must be NULL in new-library API
tests.
Since in the new-library API the cleanup is passed in the tst_test
structure and handled in the test library.
> + tst_res(TINFO, "Testing variant: %s", variants[tst_variant].desc);
> +}
> +
> +static struct tst_test test = {
> + .tcnt = ARRAY_SIZE(tcase),
> + .test = do_test,
> + .setup = setup,
> + .cleanup = cleanup,
> + .test_variants = ARRAY_SIZE(variants),
> + .bufs = (struct tst_buffers []) {
> + {&snd1, .iov_sizes = (int[]){3, 3, -1}},
> + {&snd2, .iov_sizes = (int[]){6, -1}},
> + {&rcv1, .iov_sizes = (int[]){6, -1}},
> + {&rcv2, .iov_sizes = (int[]){5, -1}},
> + {&snd_msg, .size = VLEN * sizeof(*snd_msg)},
> + {&rcv_msg, .size = VLEN * sizeof(*rcv_msg)},
> + {},
> + }
> +};
> --
> 2.25.1
>
>
> --
> Mailing list info: https://lists.linux.it/listinfo/ltp
--
Cyril Hrubis
chrubis@suse.cz
^ permalink raw reply [flat|nested] 7+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/{send|recv}mmsg: add a test case for timeout and errno test
2020-08-18 14:37 ` Cyril Hrubis
@ 2020-09-08 15:12 ` Cyril Hrubis
2020-09-20 15:45 ` Filip Bozuta
0 siblings, 1 reply; 7+ messages in thread
From: Cyril Hrubis @ 2020-09-08 15:12 UTC (permalink / raw)
To: ltp
Hi!
Ping. Are you going to send v4?
--
Cyril Hrubis
chrubis@suse.cz
^ permalink raw reply [flat|nested] 7+ messages in thread
* [LTP] [PATCH v3 2/2] syscalls/{send|recv}mmsg: add a test case for timeout and errno test
2020-09-08 15:12 ` Cyril Hrubis
@ 2020-09-20 15:45 ` Filip Bozuta
0 siblings, 0 replies; 7+ messages in thread
From: Filip Bozuta @ 2020-09-20 15:45 UTC (permalink / raw)
To: ltp
Hello,
On 9/8/2020 5:12 PM, Cyril Hrubis wrote:
> Hi!
> Ping. Are you going to send v4?
Sorry for my late response. I had some obligations and haven't got to
seeing the mails.
I have sent v4 about 20 days ago but I marked it as v3 by mistake. I
will resend the patch now as v4 sou you can take a look.
Best regards,
Filip
>
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-09-20 15:45 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2020-08-17 10:22 [LTP] [PATCH v3 0/2] testcases/kernel/syscalls: Adding new testcases for existing tests Filip Bozuta
2020-08-17 10:22 ` [LTP] [PATCH v3 1/2] syscalls/clock_nanosleep: add a test case for bad timespec address Filip Bozuta
2020-08-18 13:37 ` Cyril Hrubis
2020-08-17 10:22 ` [LTP] [PATCH v3 2/2] syscalls/{send|recv}mmsg: add a test case for timeout and errno test Filip Bozuta
2020-08-18 14:37 ` Cyril Hrubis
2020-09-08 15:12 ` Cyril Hrubis
2020-09-20 15:45 ` Filip Bozuta
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox