* [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: add new testcase
@ 2015-12-30 10:44 Guangwen Feng
2015-12-30 10:44 ` [LTP] [PATCH 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng
` (3 more replies)
0 siblings, 4 replies; 17+ messages in thread
From: Guangwen Feng @ 2015-12-30 10:44 UTC (permalink / raw)
To: ltp
Check that epoll_wait(2) works for EPOLLOUT and EPOLLIN events
on a epoll instance and that struct epoll_event is set correctly.
Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
---
runtest/ltplite | 2 +
runtest/stress.part3 | 2 +
runtest/syscalls | 1 +
testcases/kernel/syscalls/.gitignore | 1 +
testcases/kernel/syscalls/epoll_wait/Makefile | 23 ++
.../kernel/syscalls/epoll_wait/epoll_wait01.c | 263 +++++++++++++++++++++
6 files changed, 292 insertions(+)
create mode 100644 testcases/kernel/syscalls/epoll_wait/Makefile
create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait01.c
diff --git a/runtest/ltplite b/runtest/ltplite
index 1aa93e6..59be3ba 100644
--- a/runtest/ltplite
+++ b/runtest/ltplite
@@ -160,6 +160,8 @@ dup203 dup203
dup204 dup204
dup205 dup205
+epoll_wait01 epoll_wait01
+
execl01 execl01
execle01 execle01
execlp01 execlp01
diff --git a/runtest/stress.part3 b/runtest/stress.part3
index 87f42ea..3ed10ca 100644
--- a/runtest/stress.part3
+++ b/runtest/stress.part3
@@ -101,6 +101,8 @@ dup203 dup203
dup204 dup204
dup205 dup205
+epoll_wait01 epoll_wait01
+
execl01 execl01
execle01 execle01
execlp01 execlp01
diff --git a/runtest/syscalls b/runtest/syscalls
index 7173f22..5dbd00f 100644
--- a/runtest/syscalls
+++ b/runtest/syscalls
@@ -123,6 +123,7 @@ dup3_02 dup3_02
epoll_create1_01 epoll_create1_01
epoll01 epoll-ltp
+epoll_wait01 epoll_wait01
eventfd01 eventfd01
diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore
index d5f21ef..7b83307 100644
--- a/testcases/kernel/syscalls/.gitignore
+++ b/testcases/kernel/syscalls/.gitignore
@@ -98,6 +98,7 @@
/dup3/dup3_02
/epoll/epoll-ltp
/epoll_create1/epoll_create1_01
+/epoll_wait/epoll_wait01
/eventfd/eventfd01
/eventfd2/eventfd2_01
/eventfd2/eventfd2_02
diff --git a/testcases/kernel/syscalls/epoll_wait/Makefile b/testcases/kernel/syscalls/epoll_wait/Makefile
new file mode 100644
index 0000000..fa233c8
--- /dev/null
+++ b/testcases/kernel/syscalls/epoll_wait/Makefile
@@ -0,0 +1,23 @@
+#
+# Copyright (c) 2015 Fujitsu Ltd.
+# Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+# the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.
+#
+
+top_srcdir ?= ../../../..
+
+include $(top_srcdir)/include/mk/testcases.mk
+
+include $(top_srcdir)/include/mk/generic_leaf_target.mk
diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c
new file mode 100644
index 0000000..46058a2
--- /dev/null
+++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015 Fujitsu Ltd.
+ * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ */
+
+/*
+ * Description:
+ * Basic test for epoll_wait(2).
+ * Check that epoll_wait(2) works for EPOLLOUT and EPOLLIN events
+ * on a epoll instance and that struct epoll_event is set correctly.
+ */
+
+#include <sys/epoll.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <errno.h>
+
+#include "test.h"
+#include "safe_macros.h"
+#include "lapi/fcntl.h"
+
+char *TCID = "epoll_wait01";
+int TST_TOTAL = 3;
+
+static int write_size, epfd, fds[2];
+static struct epoll_event epevs[2];
+
+static void setup(void);
+static int get_writesize(void);
+static void verify_epollout(void);
+static void verify_epollin(void);
+static void verify_epollio(void);
+static void cleanup(void);
+
+int main(int ac, char **av)
+{
+ int lc;
+
+ tst_parse_opts(ac, av, NULL, NULL);
+
+ setup();
+
+ for (lc = 0; TEST_LOOPING(lc); lc++) {
+ tst_count = 0;
+
+ verify_epollout();
+ verify_epollin();
+ verify_epollio();
+ }
+
+ cleanup();
+ tst_exit();
+}
+
+static void setup(void)
+{
+ int pipe_capacity;
+
+ tst_sig(NOFORK, DEF_HANDLER, cleanup);
+
+ TEST_PAUSE;
+
+ SAFE_PIPE(NULL, fds);
+
+ /* fcntl()'s F_GETPIPE_SZ flag availbility check */
+ if ((tst_kvercmp(2, 6, 35)) < 0) {
+ write_size = get_writesize();
+ } else {
+ pipe_capacity = fcntl(fds[1], F_GETPIPE_SZ);
+ if (pipe_capacity == -1) {
+ tst_brkm(TBROK | TERRNO, cleanup,
+ "failed to get the pipe capacity");
+ }
+
+ write_size = pipe_capacity - getpagesize() + 1;
+ }
+
+ epfd = epoll_create(2);
+ if (epfd == -1) {
+ tst_brkm(TBROK | TERRNO, cleanup,
+ "failed to create epoll instance");
+ }
+
+ epevs[0].events = EPOLLIN;
+ epevs[0].data.fd = fds[0];
+ epevs[1].events = EPOLLOUT;
+ epevs[1].data.fd = fds[1];
+
+ if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]) ||
+ epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[1])) {
+ tst_brkm(TBROK | TERRNO, cleanup,
+ "failed to register epoll target");
+ }
+}
+
+/*
+ * fcntl(fd, F_GETPIPE_SZ) not supported on kernels which
+ * version lower than 2.6.35, so use this function instead
+ */
+static int get_writesize(void)
+{
+ int nfd, write_size;
+
+ struct pollfd pfd[] = {
+ {.fd = fds[0], .events = POLLIN},
+ {.fd = fds[1], .events = POLLOUT},
+ };
+
+ write_size = 0;
+ do {
+ SAFE_WRITE(cleanup, 1, fds[1], "a", 1);
+ write_size++;
+ nfd = poll(pfd, 2, -1);
+ if (nfd == -1)
+ tst_brkm(TBROK | TERRNO, cleanup, "poll failed");
+ } while (nfd == 2);
+
+ char buf[write_size];
+
+ SAFE_READ(cleanup, 1, fds[0], buf, write_size);
+
+ return write_size;
+}
+
+static void verify_epollout(void)
+{
+ TEST(epoll_wait(epfd, epevs, 2, -1));
+
+ if (TEST_RETURN == -1) {
+ tst_resm(TFAIL | TTERRNO, "epoll_wait() epollout failed");
+ return;
+ }
+
+ if (TEST_RETURN != 1) {
+ tst_resm(TFAIL, "epoll_wait() failed to get one fd ready");
+ return;
+ }
+
+ if (epevs[0].data.fd != fds[1]) {
+ tst_resm(TFAIL, "epoll_wait() failed to set write fd");
+ return;
+ }
+
+ if (epevs[0].events != EPOLLOUT) {
+ tst_resm(TFAIL, "epoll_wait() failed to set EPOLLOUT");
+ return;
+ }
+
+ tst_resm(TPASS, "epoll_wait() epollout");
+}
+
+static void verify_epollin(void)
+{
+ char write_buf[write_size];
+ char read_buf[sizeof(write_buf)];
+
+ memset(write_buf, 'a', sizeof(write_buf));
+
+ SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf));
+
+ TEST(epoll_wait(epfd, epevs, 2, -1));
+
+ if (TEST_RETURN == -1) {
+ tst_resm(TFAIL | TTERRNO, "epoll_wait() epollin failed");
+ goto end;
+ }
+
+ if (TEST_RETURN != 1) {
+ tst_resm(TFAIL, "epoll_wait() failed to get one fd ready");
+ goto end;
+ }
+
+ if (epevs[0].data.fd != fds[0]) {
+ tst_resm(TFAIL, "epoll_wait() failed to set read fd");
+ goto end;
+ }
+
+ if (epevs[0].events != EPOLLIN) {
+ tst_resm(TFAIL, "epoll_wait() failed to set EPOLLIN");
+ goto end;
+ }
+
+ tst_resm(TPASS, "epoll_wait() epollin");
+
+end:
+ SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf));
+}
+
+static void verify_epollio(void)
+{
+ int i, checked0, checked1;
+ char write_buf[] = "Testing";
+ char read_buf[sizeof(write_buf)];
+
+ SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf));
+
+ TEST(epoll_wait(epfd, epevs, 2, -1));
+
+ if (TEST_RETURN == -1) {
+ tst_resm(TFAIL | TTERRNO, "epoll_wait() epollio failed");
+ goto end;
+ }
+
+ if (TEST_RETURN != 2) {
+ tst_resm(TFAIL, "epoll_wait() failed to get two fds ready");
+ goto end;
+ }
+
+ checked0 = 0;
+ checked1 = 0;
+ for (i = 0; i < TEST_RETURN; i++) {
+ if (checked0 == 0 && epevs[i].data.fd == fds[0]) {
+ if (epevs[i].events != EPOLLIN) {
+ tst_resm(TFAIL, "epoll_wait()"
+ "failed to set EPOLLIN");
+ goto end;
+ }
+ checked0 = 1;
+ } else if (checked1 == 0 && epevs[i].data.fd == fds[1]) {
+ if (epevs[i].events != EPOLLOUT) {
+ tst_resm(TFAIL, "epoll_wait()"
+ "failed to set EPOLLOUT");
+ goto end;
+ }
+ checked1 = 1;
+ } else {
+ tst_resm(TFAIL, "epoll_wait()"
+ "failed to set write or read fd");
+ goto end;
+ }
+ }
+
+ tst_resm(TPASS, "epoll_wait() epollio");
+
+end:
+ SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf));
+}
+
+static void cleanup(void)
+{
+ if (epfd > 0 && close(epfd))
+ tst_resm(TWARN | TERRNO, "failed to close epfd");
+
+ if (close(fds[0]))
+ tst_resm(TWARN | TERRNO, "failed to close fds[0]");
+
+ if (close(fds[1]))
+ tst_resm(TWARN | TERRNO, "failed to close fds[1]");
+}
--
1.8.4.2
^ permalink raw reply related [flat|nested] 17+ messages in thread* [LTP] [PATCH 2/3] epoll_wait/epoll_wait02.c: add new testcase 2015-12-30 10:44 [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: add new testcase Guangwen Feng @ 2015-12-30 10:44 ` Guangwen Feng 2016-01-28 16:35 ` Cyril Hrubis 2015-12-30 10:44 ` [LTP] [PATCH 3/3] epoll_wait/epoll_wait03.c: " Guangwen Feng ` (2 subsequent siblings) 3 siblings, 1 reply; 17+ messages in thread From: Guangwen Feng @ 2015-12-30 10:44 UTC (permalink / raw) To: ltp Check that epoll_wait(2) timeouts correctly. Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> --- runtest/ltplite | 1 + runtest/stress.part3 | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/epoll_wait/Makefile | 2 + .../kernel/syscalls/epoll_wait/epoll_wait02.c | 144 +++++++++++++++++++++ 6 files changed, 150 insertions(+) create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait02.c diff --git a/runtest/ltplite b/runtest/ltplite index 59be3ba..08bca9a 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -161,6 +161,7 @@ dup204 dup204 dup205 dup205 epoll_wait01 epoll_wait01 +epoll_wait02 epoll_wait02 execl01 execl01 execle01 execle01 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index 3ed10ca..fb6bc0e 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -102,6 +102,7 @@ dup204 dup204 dup205 dup205 epoll_wait01 epoll_wait01 +epoll_wait02 epoll_wait02 execl01 execl01 execle01 execle01 diff --git a/runtest/syscalls b/runtest/syscalls index 5dbd00f..6c79584 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -124,6 +124,7 @@ dup3_02 dup3_02 epoll_create1_01 epoll_create1_01 epoll01 epoll-ltp epoll_wait01 epoll_wait01 +epoll_wait02 epoll_wait02 eventfd01 eventfd01 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 7b83307..46258ba 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -99,6 +99,7 @@ /epoll/epoll-ltp /epoll_create1/epoll_create1_01 /epoll_wait/epoll_wait01 +/epoll_wait/epoll_wait02 /eventfd/eventfd01 /eventfd2/eventfd2_01 /eventfd2/eventfd2_02 diff --git a/testcases/kernel/syscalls/epoll_wait/Makefile b/testcases/kernel/syscalls/epoll_wait/Makefile index fa233c8..94ca683 100644 --- a/testcases/kernel/syscalls/epoll_wait/Makefile +++ b/testcases/kernel/syscalls/epoll_wait/Makefile @@ -18,6 +18,8 @@ top_srcdir ?= ../../../.. +epoll_wait02: LDLIBS+=-lrt + include $(top_srcdir)/include/mk/testcases.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c new file mode 100644 index 0000000..3312902 --- /dev/null +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015 Fujitsu Ltd. + * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + */ + +/* + * Description: + * Check that epoll_wait(2) timeouts correctly. + */ + +#include <sys/epoll.h> +#include <unistd.h> +#include <errno.h> + +#include "test.h" +#include "safe_macros.h" + +char *TCID = "epoll_wait02"; +int TST_TOTAL = 1; + +static int epfd, fds[2]; +static char *opt_sleep_ms; +static struct epoll_event epevs[1]; + +static option_t opts[] = { + {"s:", NULL, &opt_sleep_ms}, + {NULL, NULL, NULL}, +}; + +static void setup(void); +static void cleanup(void); +static void help(void); + +int main(int ac, char **av) +{ + int lc, threshold; + long long elapsed_ms, sleep_ms = 100; + + tst_parse_opts(ac, av, opts, help); + + if (opt_sleep_ms) { + sleep_ms = atoll(opt_sleep_ms); + + if (sleep_ms == 0) { + tst_brkm(TBROK, NULL, + "Invalid timeout '%s'", opt_sleep_ms); + } + } + + threshold = sleep_ms / 100 + 10; + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + tst_timer_start(CLOCK_MONOTONIC); + TEST(epoll_wait(epfd, epevs, 1, sleep_ms)); + tst_timer_stop(); + + if (TEST_RETURN == -1) { + tst_resm(TFAIL | TTERRNO, "epoll_wait() failed"); + continue; + } + + if (TEST_RETURN != 0) { + tst_resm(TFAIL, "epoll_wait() unexpectedly get %li, " + "expected 0", TEST_RETURN); + continue; + } + + elapsed_ms = tst_timer_elapsed_ms(); + + if (elapsed_ms < sleep_ms) { + tst_resm(TFAIL, "epoll_wait() woken up too early %llims, " + "expected %llims", elapsed_ms, sleep_ms); + continue; + } + + if (elapsed_ms - sleep_ms > threshold) { + tst_resm(TFAIL, "epoll_wait() slept too long %llims, " + "expected %llims, threshold %i", + elapsed_ms, sleep_ms, threshold); + continue; + } + + tst_resm(TPASS, "epoll_wait() slept %llims, expected %llims, " + "threshold %i", elapsed_ms, sleep_ms, threshold); + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_timer_check(CLOCK_MONOTONIC); + + SAFE_PIPE(NULL, fds); + + epfd = epoll_create(1); + if (epfd == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to create epoll instance"); + } + + epevs[0].events = EPOLLIN; + epevs[0].data.fd = fds[0]; + + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0])) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to register epoll target"); + } +} + +static void cleanup(void) +{ + if (epfd > 0 && close(epfd)) + tst_resm(TWARN | TERRNO, "failed to close epfd"); + + if (close(fds[0])) + tst_resm(TWARN | TERRNO, "close(fds[0]) failed"); + + if (close(fds[1])) + tst_resm(TWARN | TERRNO, "close(fds[1]) failed"); +} + +static void help(void) +{ + printf(" -s epoll_wait() timeout length in ms\n"); +} -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH 2/3] epoll_wait/epoll_wait02.c: add new testcase 2015-12-30 10:44 ` [LTP] [PATCH 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng @ 2016-01-28 16:35 ` Cyril Hrubis 0 siblings, 0 replies; 17+ messages in thread From: Cyril Hrubis @ 2016-01-28 16:35 UTC (permalink / raw) To: ltp Hi! > + > + if (TEST_RETURN != 0) { > + tst_resm(TFAIL, "epoll_wait() unexpectedly get %li, " ^ Should rather be: "returned %li, expected 0" The sentence does not make sense as it is. > + "expected 0", TEST_RETURN); > + continue; > + } > + > + elapsed_ms = tst_timer_elapsed_ms(); > + > + if (elapsed_ms < sleep_ms) { > + tst_resm(TFAIL, "epoll_wait() woken up too early %llims, " > + "expected %llims", elapsed_ms, sleep_ms); > + continue; > + } > + > + if (elapsed_ms - sleep_ms > threshold) { > + tst_resm(TFAIL, "epoll_wait() slept too long %llims, " > + "expected %llims, threshold %i", > + elapsed_ms, sleep_ms, threshold); > + continue; > + } > + > + tst_resm(TPASS, "epoll_wait() slept %llims, expected %llims, " > + "threshold %i", elapsed_ms, sleep_ms, threshold); > + } > + > + cleanup(); > + tst_exit(); > +} > + > +static void setup(void) > +{ > + tst_timer_check(CLOCK_MONOTONIC); > + > + SAFE_PIPE(NULL, fds); > + > + epfd = epoll_create(1); > + if (epfd == -1) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "failed to create epoll instance"); > + } > + > + epevs[0].events = EPOLLIN; > + epevs[0].data.fd = fds[0]; > + > + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0])) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "failed to register epoll target"); > + } > +} > + > +static void cleanup(void) > +{ > + if (epfd > 0 && close(epfd)) > + tst_resm(TWARN | TERRNO, "failed to close epfd"); > + > + if (close(fds[0])) > + tst_resm(TWARN | TERRNO, "close(fds[0]) failed"); > + > + if (close(fds[1])) > + tst_resm(TWARN | TERRNO, "close(fds[1]) failed"); > +} > + > +static void help(void) > +{ > + printf(" -s epoll_wait() timeout length in ms\n"); > +} The rest looks good. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH 3/3] epoll_wait/epoll_wait03.c: add new testcase 2015-12-30 10:44 [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: add new testcase Guangwen Feng 2015-12-30 10:44 ` [LTP] [PATCH 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng @ 2015-12-30 10:44 ` Guangwen Feng 2016-01-28 17:16 ` Cyril Hrubis 2016-01-06 1:19 ` [LTP] [PATCH 4/4] epoll_wait/epoll_wait04.c: " Guangwen Feng 2016-01-28 16:19 ` [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: " Cyril Hrubis 3 siblings, 1 reply; 17+ messages in thread From: Guangwen Feng @ 2015-12-30 10:44 UTC (permalink / raw) To: ltp Verify that: 1) epoll_wait(2) fails if epfd is not a valid file descriptor 2) epoll_wait(2) fails if epfd is not an epoll file descriptor 3) epoll_wait(2) fails if maxevents is less than zero 4) epoll_wait(2) fails if maxevents is equal to zero Expected result: 1) epoll_wait(2) should return -1 and set errno to EBADF 2) epoll_wait(2) should return -1 and set errno to EINVAL 3) epoll_wait(2) should return -1 and set errno to EINVAL 4) epoll_wait(2) should return -1 and set errno to EINVAL Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> --- runtest/ltplite | 1 + runtest/stress.part3 | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + .../kernel/syscalls/epoll_wait/epoll_wait03.c | 146 +++++++++++++++++++++ 5 files changed, 150 insertions(+) create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait03.c diff --git a/runtest/ltplite b/runtest/ltplite index 08bca9a..4686c08 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -162,6 +162,7 @@ dup205 dup205 epoll_wait01 epoll_wait01 epoll_wait02 epoll_wait02 +epoll_wait03 epoll_wait03 execl01 execl01 execle01 execle01 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index fb6bc0e..e198fb4 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -103,6 +103,7 @@ dup205 dup205 epoll_wait01 epoll_wait01 epoll_wait02 epoll_wait02 +epoll_wait03 epoll_wait03 execl01 execl01 execle01 execle01 diff --git a/runtest/syscalls b/runtest/syscalls index 6c79584..88c748c 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -125,6 +125,7 @@ epoll_create1_01 epoll_create1_01 epoll01 epoll-ltp epoll_wait01 epoll_wait01 epoll_wait02 epoll_wait02 +epoll_wait03 epoll_wait03 eventfd01 eventfd01 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 46258ba..f63077a 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -100,6 +100,7 @@ /epoll_create1/epoll_create1_01 /epoll_wait/epoll_wait01 /epoll_wait/epoll_wait02 +/epoll_wait/epoll_wait03 /eventfd/eventfd01 /eventfd2/eventfd2_01 /eventfd2/eventfd2_02 diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c new file mode 100644 index 0000000..34009c5 --- /dev/null +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015 Fujitsu Ltd. + * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + */ + +/* + * Description: + * 1) epoll_wait(2) fails if epfd is not a valid file descriptor + * 2) epoll_wait(2) fails if epfd is not an epoll file descriptor + * 3) epoll_wait(2) fails if maxevents is less than zero + * 4) epoll_wait(2) fails if maxevents is equal to zero + * + * Expected Result: + * 1) epoll_wait(2) should return -1 and set errno to EBADF + * 2) epoll_wait(2) should return -1 and set errno to EINVAL + * 3) epoll_wait(2) should return -1 and set errno to EINVAL + * 4) epoll_wait(2) should return -1 and set errno to EINVAL + */ + +#include <sys/epoll.h> +#include <string.h> +#include <errno.h> + +#include "test.h" +#include "safe_macros.h" + +static int epfd, fds[2]; +static struct epoll_event epevs[1]; + +static struct test_case_t { + int epfd; + int maxevents; + int exp_errno; +} test_cases[] = { + /* test1 */ + {-1, 1, EBADF}, + /* test2 */ + {0, 1, EINVAL}, + /* + * test3 + * temporarily set epfd to 0 + * will be set to an epoll instance later + */ + {0, -1, EINVAL}, + /* + * test4 + * temporarily set epfd to 0 + * will be set to an epoll instance later + */ + {0, 0, EINVAL}, +}; + +char *TCID = "epoll_wait03"; +int TST_TOTAL = ARRAY_SIZE(test_cases); + +static void setup(void); +static void verify_epoll_wait(struct test_case_t *test_cases); +static void cleanup(void); + +int main(int ac, char **av) +{ + int lc, tc; + + tst_parse_opts(ac, av, NULL, NULL); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + for (tc = 0; tc < TST_TOTAL; tc++) + verify_epoll_wait(&test_cases[tc]); + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; + + SAFE_PIPE(NULL, fds); + + epfd = epoll_create(1); + if (epfd == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to create epoll instance"); + } + + test_cases[2].epfd = epfd; + test_cases[3].epfd = epfd; + + epevs[0].events = EPOLLOUT; + epevs[0].data.fd = fds[1]; + + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[0])) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to register epoll target"); + } +} + +static void verify_epoll_wait(struct test_case_t *test_cases) +{ + TEST(epoll_wait(test_cases->epfd, epevs, test_cases->maxevents, -1)); + if (TEST_RETURN != -1) { + tst_resm(TFAIL, "epoll_wait() succeed unexpectedly"); + } else { + if (TEST_ERRNO == test_cases->exp_errno) { + tst_resm(TPASS | TTERRNO, + "epoll_wait() fails as expected"); + } else { + tst_resm(TFAIL | TTERRNO, + "epoll_wait() fails unexpectedly, " + "expected %d: %s", test_cases->exp_errno, + strerror(test_cases->exp_errno)); + } + } +} + +static void cleanup(void) +{ + if (epfd > 0 && close(epfd)) + tst_resm(TWARN | TERRNO, "failed to close epfd"); + + if (close(fds[0])) + tst_resm(TWARN | TERRNO, "close(fds[0]) failed"); + + if (close(fds[1])) + tst_resm(TWARN | TERRNO, "close(fds[1]) failed"); +} -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH 3/3] epoll_wait/epoll_wait03.c: add new testcase 2015-12-30 10:44 ` [LTP] [PATCH 3/3] epoll_wait/epoll_wait03.c: " Guangwen Feng @ 2016-01-28 17:16 ` Cyril Hrubis 0 siblings, 0 replies; 17+ messages in thread From: Cyril Hrubis @ 2016-01-28 17:16 UTC (permalink / raw) To: ltp Hi! > +#include <sys/epoll.h> > +#include <string.h> > +#include <errno.h> > + > +#include "test.h" > +#include "safe_macros.h" > + > +static int epfd, fds[2]; > +static struct epoll_event epevs[1]; > + > +static struct test_case_t { > + int epfd; > + int maxevents; > + int exp_errno; > +} test_cases[] = { > + /* test1 */ > + {-1, 1, EBADF}, > + /* test2 */ > + {0, 1, EINVAL}, > + /* > + * test3 > + * temporarily set epfd to 0 > + * will be set to an epoll instance later > + */ Instead of this comment the epfd should rather be pointer to an integer that is initialized in setup(). Changing this structure in setup() by explicit position is a bad habbit and will lead to unexpected side effect when this structure gets changed. > + {0, -1, EINVAL}, > + /* > + * test4 > + * temporarily set epfd to 0 > + * will be set to an epoll instance later > + */ > + {0, 0, EINVAL}, > +}; > + > +char *TCID = "epoll_wait03"; > +int TST_TOTAL = ARRAY_SIZE(test_cases); > + > +static void setup(void); > +static void verify_epoll_wait(struct test_case_t *test_cases); > +static void cleanup(void); > + > +int main(int ac, char **av) > +{ > + int lc, tc; > + > + tst_parse_opts(ac, av, NULL, NULL); > + > + setup(); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + tst_count = 0; > + > + for (tc = 0; tc < TST_TOTAL; tc++) > + verify_epoll_wait(&test_cases[tc]); > + } > + > + cleanup(); > + tst_exit(); > +} > + > +static void setup(void) > +{ > + tst_sig(NOFORK, DEF_HANDLER, cleanup); > + > + TEST_PAUSE; > + > + SAFE_PIPE(NULL, fds); > + > + epfd = epoll_create(1); > + if (epfd == -1) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "failed to create epoll instance"); > + } > + > + test_cases[2].epfd = epfd; > + test_cases[3].epfd = epfd; > + > + epevs[0].events = EPOLLOUT; > + epevs[0].data.fd = fds[1]; This should be initialized statically as: static struct epoll_event epevs[1] = { {.events = EPOLLOUT, .data = {.fd = fds[1]}} }; > + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[0])) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "failed to register epoll target"); > + } > +} > + > +static void verify_epoll_wait(struct test_case_t *test_cases) > +{ > + TEST(epoll_wait(test_cases->epfd, epevs, test_cases->maxevents, -1)); > + if (TEST_RETURN != -1) { > + tst_resm(TFAIL, "epoll_wait() succeed unexpectedly"); > + } else { > + if (TEST_ERRNO == test_cases->exp_errno) { > + tst_resm(TPASS | TTERRNO, > + "epoll_wait() fails as expected"); > + } else { > + tst_resm(TFAIL | TTERRNO, > + "epoll_wait() fails unexpectedly, " > + "expected %d: %s", test_cases->exp_errno, > + strerror(test_cases->exp_errno)); ^ you shoud use tst_strerrno() instead > + } > + } > +} > + > +static void cleanup(void) > +{ > + if (epfd > 0 && close(epfd)) > + tst_resm(TWARN | TERRNO, "failed to close epfd"); > + > + if (close(fds[0])) > + tst_resm(TWARN | TERRNO, "close(fds[0]) failed"); > + > + if (close(fds[1])) > + tst_resm(TWARN | TERRNO, "close(fds[1]) failed"); > +} The rest looks good. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH 4/4] epoll_wait/epoll_wait04.c: add new testcase 2015-12-30 10:44 [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: add new testcase Guangwen Feng 2015-12-30 10:44 ` [LTP] [PATCH 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng 2015-12-30 10:44 ` [LTP] [PATCH 3/3] epoll_wait/epoll_wait03.c: " Guangwen Feng @ 2016-01-06 1:19 ` Guangwen Feng 2016-01-28 17:24 ` Cyril Hrubis 2016-01-28 16:19 ` [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: " Cyril Hrubis 3 siblings, 1 reply; 17+ messages in thread From: Guangwen Feng @ 2016-01-06 1:19 UTC (permalink / raw) To: ltp Verify that: epoll_wait(2) fails if the memory area pointed to by events is not accessible with write permissions. Expected result: epoll_wait(2) should return -1 and set errno to EFAULT Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> --- runtest/ltplite | 1 + runtest/stress.part3 | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + .../kernel/syscalls/epoll_wait/epoll_wait04.c | 119 +++++++++++++++++++++ 5 files changed, 123 insertions(+) create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait04.c diff --git a/runtest/ltplite b/runtest/ltplite index 4686c08..d30e596 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -163,6 +163,7 @@ dup205 dup205 epoll_wait01 epoll_wait01 epoll_wait02 epoll_wait02 epoll_wait03 epoll_wait03 +epoll_wait04 epoll_wait04 execl01 execl01 execle01 execle01 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index e198fb4..9d8b87a 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -104,6 +104,7 @@ dup205 dup205 epoll_wait01 epoll_wait01 epoll_wait02 epoll_wait02 epoll_wait03 epoll_wait03 +epoll_wait04 epoll_wait04 execl01 execl01 execle01 execle01 diff --git a/runtest/syscalls b/runtest/syscalls index 88c748c..df1a267 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -126,6 +126,7 @@ epoll01 epoll-ltp epoll_wait01 epoll_wait01 epoll_wait02 epoll_wait02 epoll_wait03 epoll_wait03 +epoll_wait04 epoll_wait04 eventfd01 eventfd01 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index f63077a..23bd9ac 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -101,6 +101,7 @@ /epoll_wait/epoll_wait01 /epoll_wait/epoll_wait02 /epoll_wait/epoll_wait03 +/epoll_wait/epoll_wait04 /eventfd/eventfd01 /eventfd2/eventfd2_01 /eventfd2/eventfd2_02 diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait04.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait04.c new file mode 100644 index 0000000..36110f3 --- /dev/null +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait04.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015 Fujitsu Ltd. + * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + */ + +/* + * Description: + * epoll_wait(2) fails if the memory area pointed to by events is not + * accessible with write permissions. + * + * Expected Result: + * epoll_wait(2) should return -1 and set errno to EFAULT + */ + +#include <sys/epoll.h> +#include <sys/mman.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include "test.h" +#include "safe_macros.h" + +char *TCID = "epoll_wait04"; +int TST_TOTAL = 1; + +static int page_size, epfd, fds[2]; +static struct epoll_event *epevs; + +static void setup(void); +static void cleanup(void); + +int main(int ac, char **av) +{ + int lc; + + tst_parse_opts(ac, av, NULL, NULL); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + TEST(epoll_wait(epfd, epevs, 1, -1)); + if (TEST_RETURN != -1) { + tst_resm(TFAIL, "epoll_wait() succeed unexpectedly"); + } else { + if (TEST_ERRNO == EFAULT) { + tst_resm(TPASS | TTERRNO, + "epoll_wait() fails as expected"); + } else { + tst_resm(TFAIL | TTERRNO, + "epoll_wait() fails unexpectedly, " + "expected errno is EFAULT"); + } + } + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; + + page_size = getpagesize(); + + epevs = SAFE_MMAP(NULL, NULL, page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + SAFE_PIPE(NULL, fds); + + epfd = epoll_create(1); + if (epfd == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to create epoll instance"); + } + + epevs->events = EPOLLOUT; + epevs->data.fd = fds[1]; + + if (mprotect(epevs, page_size, PROT_READ)) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to set memory area read-only"); + } + + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], epevs)) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to register epoll target"); + } +} + +static void cleanup(void) +{ + if (epfd > 0 && close(epfd)) + tst_resm(TWARN | TERRNO, "failed to close epfd"); + + if (close(fds[0])) + tst_resm(TWARN | TERRNO, "close(fds[0]) failed"); + + if (close(fds[1])) + tst_resm(TWARN | TERRNO, "close(fds[1]) failed"); +} -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH 4/4] epoll_wait/epoll_wait04.c: add new testcase 2016-01-06 1:19 ` [LTP] [PATCH 4/4] epoll_wait/epoll_wait04.c: " Guangwen Feng @ 2016-01-28 17:24 ` Cyril Hrubis 0 siblings, 0 replies; 17+ messages in thread From: Cyril Hrubis @ 2016-01-28 17:24 UTC (permalink / raw) To: ltp Hi! > Verify that: > epoll_wait(2) fails if the memory area pointed to by events is not > accessible with write permissions. > > Expected result: > epoll_wait(2) should return -1 and set errno to EFAULT Is there any reason why this is not part of the previous (epoll_wait03) test? All that needs to be done is that the test_case structrue would have to have epoll_event **ev member that would either pointing to epoll_event * variable initialized in the setup by mmap() or different one that will point to the static array (since we cannot get pointer to variable holding the array). The code would look like: epoll_event *ev_efault; epoll_event *ev = &evps; { {&fd, 1, &ev_efault, EFAULT}, {&fd, -1, &ev, EINVAL}, ... } ... TEST(epoll_wait(*(tc->epfd), *(tc->ev), tc->maxevents, -1)); ... -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: add new testcase 2015-12-30 10:44 [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: add new testcase Guangwen Feng ` (2 preceding siblings ...) 2016-01-06 1:19 ` [LTP] [PATCH 4/4] epoll_wait/epoll_wait04.c: " Guangwen Feng @ 2016-01-28 16:19 ` Cyril Hrubis 2016-02-01 5:28 ` Guangwen Feng 3 siblings, 1 reply; 17+ messages in thread From: Cyril Hrubis @ 2016-01-28 16:19 UTC (permalink / raw) To: ltp Hi! > diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c > new file mode 100644 > index 0000000..46058a2 > --- /dev/null > +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c > @@ -0,0 +1,263 @@ > +/* > + * Copyright (c) 2015 Fujitsu Ltd. > + * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See > + * the GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. > + */ > + > +/* > + * Description: > + * Basic test for epoll_wait(2). > + * Check that epoll_wait(2) works for EPOLLOUT and EPOLLIN events > + * on a epoll instance and that struct epoll_event is set correctly. > + */ > + > +#include <sys/epoll.h> > +#include <unistd.h> > +#include <fcntl.h> > +#include <poll.h> > +#include <errno.h> > + > +#include "test.h" > +#include "safe_macros.h" > +#include "lapi/fcntl.h" > + > +char *TCID = "epoll_wait01"; > +int TST_TOTAL = 3; > + > +static int write_size, epfd, fds[2]; > +static struct epoll_event epevs[2]; > + > +static void setup(void); > +static int get_writesize(void); > +static void verify_epollout(void); > +static void verify_epollin(void); > +static void verify_epollio(void); > +static void cleanup(void); > + > +int main(int ac, char **av) > +{ > + int lc; > + > + tst_parse_opts(ac, av, NULL, NULL); > + > + setup(); > + > + for (lc = 0; TEST_LOOPING(lc); lc++) { > + tst_count = 0; > + > + verify_epollout(); > + verify_epollin(); > + verify_epollio(); > + } > + > + cleanup(); > + tst_exit(); > +} > + > +static void setup(void) > +{ > + int pipe_capacity; > + > + tst_sig(NOFORK, DEF_HANDLER, cleanup); > + > + TEST_PAUSE; > + > + SAFE_PIPE(NULL, fds); > + > + /* fcntl()'s F_GETPIPE_SZ flag availbility check */ > + if ((tst_kvercmp(2, 6, 35)) < 0) { > + write_size = get_writesize(); > + } else { > + pipe_capacity = fcntl(fds[1], F_GETPIPE_SZ); > + if (pipe_capacity == -1) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "failed to get the pipe capacity"); > + } > + > + write_size = pipe_capacity - getpagesize() + 1; > + } I would rather go with runtime detection even for newer kernels. Since otherwise we have two different codepaths to test. > + epfd = epoll_create(2); > + if (epfd == -1) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "failed to create epoll instance"); > + } > + > + epevs[0].events = EPOLLIN; > + epevs[0].data.fd = fds[0]; > + epevs[1].events = EPOLLOUT; > + epevs[1].data.fd = fds[1]; > + > + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]) || > + epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[1])) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "failed to register epoll target"); > + } > +} > + > +/* > + * fcntl(fd, F_GETPIPE_SZ) not supported on kernels which > + * version lower than 2.6.35, so use this function instead > + */ > +static int get_writesize(void) > +{ > + int nfd, write_size; > + > + struct pollfd pfd[] = { > + {.fd = fds[0], .events = POLLIN}, > + {.fd = fds[1], .events = POLLOUT}, > + }; > + > + write_size = 0; > + do { > + SAFE_WRITE(cleanup, 1, fds[1], "a", 1); > + write_size++; > + nfd = poll(pfd, 2, -1); > + if (nfd == -1) > + tst_brkm(TBROK | TERRNO, cleanup, "poll failed"); > + } while (nfd == 2); Why don't we write larger chunks and add the return from SAFE_WRITE to the write_size? That should work if we pass 0 as len strict, the last write should just end up truncated. > + char buf[write_size]; > + > + SAFE_READ(cleanup, 1, fds[0], buf, write_size); > + > + return write_size; > +} > + > +static void verify_epollout(void) > +{ > + TEST(epoll_wait(epfd, epevs, 2, -1)); > + > + if (TEST_RETURN == -1) { > + tst_resm(TFAIL | TTERRNO, "epoll_wait() epollout failed"); > + return; > + } > + > + if (TEST_RETURN != 1) { > + tst_resm(TFAIL, "epoll_wait() failed to get one fd ready"); ^ We should add the TEST_RETURN value to the output here I would go for: tst_resm(TFAIL, "epoll_wait() returned %i expected 1", TEST_RETURN); > + return; > + } > + > + if (epevs[0].data.fd != fds[1]) { > + tst_resm(TFAIL, "epoll_wait() failed to set write fd"); And maybe write the actuall fds here: tst_resm(TFAIL, "epoll.data.fd %i expected %i", ...); > + return; > + } > + > + if (epevs[0].events != EPOLLOUT) { > + tst_resm(TFAIL, "epoll_wait() failed to set EPOLLOUT"); And perhaps print the value of events as hexadecimal here. > + return; > + } > + > + tst_resm(TPASS, "epoll_wait() epollout"); > +} > + > +static void verify_epollin(void) > +{ > + char write_buf[write_size]; > + char read_buf[sizeof(write_buf)]; > + > + memset(write_buf, 'a', sizeof(write_buf)); > + > + SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf)); > + > + TEST(epoll_wait(epfd, epevs, 2, -1)); > + > + if (TEST_RETURN == -1) { > + tst_resm(TFAIL | TTERRNO, "epoll_wait() epollin failed"); > + goto end; > + } > + > + if (TEST_RETURN != 1) { > + tst_resm(TFAIL, "epoll_wait() failed to get one fd ready"); > + goto end; > + } > + > + if (epevs[0].data.fd != fds[0]) { > + tst_resm(TFAIL, "epoll_wait() failed to set read fd"); > + goto end; > + } > + > + if (epevs[0].events != EPOLLIN) { > + tst_resm(TFAIL, "epoll_wait() failed to set EPOLLIN"); > + goto end; > + } And I would be more verbose about the values in these messages as well. > + tst_resm(TPASS, "epoll_wait() epollin"); > + > +end: > + SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf)); > +} > + > +static void verify_epollio(void) > +{ > + int i, checked0, checked1; > + char write_buf[] = "Testing"; > + char read_buf[sizeof(write_buf)]; > + > + SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf)); > + > + TEST(epoll_wait(epfd, epevs, 2, -1)); ^ Shouldn't we pass at least 3 here (and declare epevs to have three elements as well). Since if there were three events queued the epoll_wait() would return just 2 and the test will pass. > + > + if (TEST_RETURN == -1) { > + tst_resm(TFAIL | TTERRNO, "epoll_wait() epollio failed"); > + goto end; > + } > + > + if (TEST_RETURN != 2) { > + tst_resm(TFAIL, "epoll_wait() failed to get two fds ready"); > + goto end; > + } > + > + checked0 = 0; > + checked1 = 0; > + for (i = 0; i < TEST_RETURN; i++) { > + if (checked0 == 0 && epevs[i].data.fd == fds[0]) { > + if (epevs[i].events != EPOLLIN) { > + tst_resm(TFAIL, "epoll_wait()" > + "failed to set EPOLLIN"); > + goto end; > + } > + checked0 = 1; > + } else if (checked1 == 0 && epevs[i].data.fd == fds[1]) { > + if (epevs[i].events != EPOLLOUT) { > + tst_resm(TFAIL, "epoll_wait()" > + "failed to set EPOLLOUT"); > + goto end; > + } > + checked1 = 1; > + } else { > + tst_resm(TFAIL, "epoll_wait()" > + "failed to set write or read fd"); > + goto end; > + } > + } Hmm, this is kind of messy. I would implement this as function that checks if the array has event with specific values and would have called it twice once with read fd and once with write fd. static int has_event(struct epoll_event *events, int events_len, int fd, uint32_t events) { ... } ... if (!has_event(epevs, 2, fds[0], EPOLLIN)) tst_resm(TFAIL, ...); if (!has_event(epevs, 2, fds[1], EPOLLOUT)) tst_resm(TFAIL, ...); ... And perhaps we can add a function to dump the epevs array with tst_resm(TINFO, "") and call it on the array whenever we find that something went wrong before we do tst_resm(TFAIL, ...); > + tst_resm(TPASS, "epoll_wait() epollio"); > + > +end: > + SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf)); > +} > + > +static void cleanup(void) > +{ > + if (epfd > 0 && close(epfd)) > + tst_resm(TWARN | TERRNO, "failed to close epfd"); > + > + if (close(fds[0])) > + tst_resm(TWARN | TERRNO, "failed to close fds[0]"); > + > + if (close(fds[1])) > + tst_resm(TWARN | TERRNO, "failed to close fds[1]"); > +} The rest looks good. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: add new testcase 2016-01-28 16:19 ` [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: " Cyril Hrubis @ 2016-02-01 5:28 ` Guangwen Feng 2016-02-17 10:51 ` [LTP] [PATCH v2 " Guangwen Feng 0 siblings, 1 reply; 17+ messages in thread From: Guangwen Feng @ 2016-02-01 5:28 UTC (permalink / raw) To: ltp Hi! Thanks for your review! I will modify these test cases according to your suggestion. Best Regards, Guangwen Feng On 01/29/2016 12:19 AM, Cyril Hrubis wrote: > Hi! >> diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c >> new file mode 100644 >> index 0000000..46058a2 >> --- /dev/null >> +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c >> @@ -0,0 +1,263 @@ >> +/* >> + * Copyright (c) 2015 Fujitsu Ltd. >> + * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> >> + * >> + * This program is free software; you can redistribute it and/or modify >> + * it under the terms of the GNU General Public License as published by >> + * the Free Software Foundation; either version 2 of the License, or >> + * (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See >> + * the GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public License >> + * along with this program. >> + */ >> + >> +/* >> + * Description: >> + * Basic test for epoll_wait(2). >> + * Check that epoll_wait(2) works for EPOLLOUT and EPOLLIN events >> + * on a epoll instance and that struct epoll_event is set correctly. >> + */ >> + >> +#include <sys/epoll.h> >> +#include <unistd.h> >> +#include <fcntl.h> >> +#include <poll.h> >> +#include <errno.h> >> + >> +#include "test.h" >> +#include "safe_macros.h" >> +#include "lapi/fcntl.h" >> + >> +char *TCID = "epoll_wait01"; >> +int TST_TOTAL = 3; >> + >> +static int write_size, epfd, fds[2]; >> +static struct epoll_event epevs[2]; >> + >> +static void setup(void); >> +static int get_writesize(void); >> +static void verify_epollout(void); >> +static void verify_epollin(void); >> +static void verify_epollio(void); >> +static void cleanup(void); >> + >> +int main(int ac, char **av) >> +{ >> + int lc; >> + >> + tst_parse_opts(ac, av, NULL, NULL); >> + >> + setup(); >> + >> + for (lc = 0; TEST_LOOPING(lc); lc++) { >> + tst_count = 0; >> + >> + verify_epollout(); >> + verify_epollin(); >> + verify_epollio(); >> + } >> + >> + cleanup(); >> + tst_exit(); >> +} >> + >> +static void setup(void) >> +{ >> + int pipe_capacity; >> + >> + tst_sig(NOFORK, DEF_HANDLER, cleanup); >> + >> + TEST_PAUSE; >> + >> + SAFE_PIPE(NULL, fds); >> + >> + /* fcntl()'s F_GETPIPE_SZ flag availbility check */ >> + if ((tst_kvercmp(2, 6, 35)) < 0) { >> + write_size = get_writesize(); >> + } else { >> + pipe_capacity = fcntl(fds[1], F_GETPIPE_SZ); >> + if (pipe_capacity == -1) { >> + tst_brkm(TBROK | TERRNO, cleanup, >> + "failed to get the pipe capacity"); >> + } >> + >> + write_size = pipe_capacity - getpagesize() + 1; >> + } > > I would rather go with runtime detection even for newer kernels. Since > otherwise we have two different codepaths to test. > >> + epfd = epoll_create(2); >> + if (epfd == -1) { >> + tst_brkm(TBROK | TERRNO, cleanup, >> + "failed to create epoll instance"); >> + } >> + >> + epevs[0].events = EPOLLIN; >> + epevs[0].data.fd = fds[0]; >> + epevs[1].events = EPOLLOUT; >> + epevs[1].data.fd = fds[1]; >> + >> + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]) || >> + epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[1])) { >> + tst_brkm(TBROK | TERRNO, cleanup, >> + "failed to register epoll target"); >> + } >> +} >> + >> +/* >> + * fcntl(fd, F_GETPIPE_SZ) not supported on kernels which >> + * version lower than 2.6.35, so use this function instead >> + */ >> +static int get_writesize(void) >> +{ >> + int nfd, write_size; >> + >> + struct pollfd pfd[] = { >> + {.fd = fds[0], .events = POLLIN}, >> + {.fd = fds[1], .events = POLLOUT}, >> + }; >> + >> + write_size = 0; >> + do { >> + SAFE_WRITE(cleanup, 1, fds[1], "a", 1); >> + write_size++; >> + nfd = poll(pfd, 2, -1); >> + if (nfd == -1) >> + tst_brkm(TBROK | TERRNO, cleanup, "poll failed"); >> + } while (nfd == 2); > > Why don't we write larger chunks and add the return from SAFE_WRITE to > the write_size? That should work if we pass 0 as len strict, the last > write should just end up truncated. > >> + char buf[write_size]; >> + >> + SAFE_READ(cleanup, 1, fds[0], buf, write_size); >> + >> + return write_size; >> +} >> + >> +static void verify_epollout(void) >> +{ >> + TEST(epoll_wait(epfd, epevs, 2, -1)); >> + >> + if (TEST_RETURN == -1) { >> + tst_resm(TFAIL | TTERRNO, "epoll_wait() epollout failed"); >> + return; >> + } >> + >> + if (TEST_RETURN != 1) { >> + tst_resm(TFAIL, "epoll_wait() failed to get one fd ready"); > ^ > We should add the TEST_RETURN > value to the output here > I would go for: > tst_resm(TFAIL, "epoll_wait() returned %i expected 1", > TEST_RETURN); > > >> + return; >> + } >> + >> + if (epevs[0].data.fd != fds[1]) { >> + tst_resm(TFAIL, "epoll_wait() failed to set write fd"); > > And maybe write the actuall fds here: > > tst_resm(TFAIL, "epoll.data.fd %i expected %i", ...); > >> + return; >> + } >> + >> + if (epevs[0].events != EPOLLOUT) { >> + tst_resm(TFAIL, "epoll_wait() failed to set EPOLLOUT"); > > And perhaps print the value of events as hexadecimal here. > >> + return; >> + } >> + >> + tst_resm(TPASS, "epoll_wait() epollout"); >> +} >> + >> +static void verify_epollin(void) >> +{ >> + char write_buf[write_size]; >> + char read_buf[sizeof(write_buf)]; >> + >> + memset(write_buf, 'a', sizeof(write_buf)); >> + >> + SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf)); >> + >> + TEST(epoll_wait(epfd, epevs, 2, -1)); >> + >> + if (TEST_RETURN == -1) { >> + tst_resm(TFAIL | TTERRNO, "epoll_wait() epollin failed"); >> + goto end; >> + } >> + >> + if (TEST_RETURN != 1) { >> + tst_resm(TFAIL, "epoll_wait() failed to get one fd ready"); >> + goto end; >> + } >> + >> + if (epevs[0].data.fd != fds[0]) { >> + tst_resm(TFAIL, "epoll_wait() failed to set read fd"); >> + goto end; >> + } >> + >> + if (epevs[0].events != EPOLLIN) { >> + tst_resm(TFAIL, "epoll_wait() failed to set EPOLLIN"); >> + goto end; >> + } > > And I would be more verbose about the values in these messages as well. > >> + tst_resm(TPASS, "epoll_wait() epollin"); >> + >> +end: >> + SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf)); >> +} >> + >> +static void verify_epollio(void) >> +{ >> + int i, checked0, checked1; >> + char write_buf[] = "Testing"; >> + char read_buf[sizeof(write_buf)]; >> + >> + SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf)); >> + >> + TEST(epoll_wait(epfd, epevs, 2, -1)); > ^ > Shouldn't we pass at least 3 here (and > declare epevs to have three elements as > well). Since if there were three events > queued the epoll_wait() would return just > 2 and the test will pass. > >> + >> + if (TEST_RETURN == -1) { >> + tst_resm(TFAIL | TTERRNO, "epoll_wait() epollio failed"); >> + goto end; >> + } >> + >> + if (TEST_RETURN != 2) { >> + tst_resm(TFAIL, "epoll_wait() failed to get two fds ready"); >> + goto end; >> + } >> + >> + checked0 = 0; >> + checked1 = 0; >> + for (i = 0; i < TEST_RETURN; i++) { >> + if (checked0 == 0 && epevs[i].data.fd == fds[0]) { >> + if (epevs[i].events != EPOLLIN) { >> + tst_resm(TFAIL, "epoll_wait()" >> + "failed to set EPOLLIN"); >> + goto end; >> + } >> + checked0 = 1; >> + } else if (checked1 == 0 && epevs[i].data.fd == fds[1]) { >> + if (epevs[i].events != EPOLLOUT) { >> + tst_resm(TFAIL, "epoll_wait()" >> + "failed to set EPOLLOUT"); >> + goto end; >> + } >> + checked1 = 1; >> + } else { >> + tst_resm(TFAIL, "epoll_wait()" >> + "failed to set write or read fd"); >> + goto end; >> + } >> + } > > > Hmm, this is kind of messy. I would implement this as function that > checks if the array has event with specific values and would have called > it twice once with read fd and once with write fd. > > static int has_event(struct epoll_event *events, int events_len, > int fd, uint32_t events) > { > ... > } > > ... > if (!has_event(epevs, 2, fds[0], EPOLLIN)) > tst_resm(TFAIL, ...); > > if (!has_event(epevs, 2, fds[1], EPOLLOUT)) > tst_resm(TFAIL, ...); > ... > > > And perhaps we can add a function to dump the epevs array with > tst_resm(TINFO, "") and call it on the array whenever we find that > something went wrong before we do tst_resm(TFAIL, ...); > >> + tst_resm(TPASS, "epoll_wait() epollio"); >> + >> +end: >> + SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf)); >> +} >> + >> +static void cleanup(void) >> +{ >> + if (epfd > 0 && close(epfd)) >> + tst_resm(TWARN | TERRNO, "failed to close epfd"); >> + >> + if (close(fds[0])) >> + tst_resm(TWARN | TERRNO, "failed to close fds[0]"); >> + >> + if (close(fds[1])) >> + tst_resm(TWARN | TERRNO, "failed to close fds[1]"); >> +} > > The rest looks good. > ^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH v2 1/3] epoll_wait/epoll_wait01.c: add new testcase 2016-02-01 5:28 ` Guangwen Feng @ 2016-02-17 10:51 ` Guangwen Feng 2016-02-17 10:51 ` [LTP] [PATCH v2 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng ` (2 more replies) 0 siblings, 3 replies; 17+ messages in thread From: Guangwen Feng @ 2016-02-17 10:51 UTC (permalink / raw) To: ltp Check that epoll_wait(2) works for EPOLLOUT and EPOLLIN events on a epoll instance and that struct epoll_event is set correctly. Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> --- runtest/ltplite | 2 + runtest/stress.part3 | 2 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/epoll_wait/Makefile | 23 ++ .../kernel/syscalls/epoll_wait/epoll_wait01.c | 281 +++++++++++++++++++++ 6 files changed, 310 insertions(+) create mode 100644 testcases/kernel/syscalls/epoll_wait/Makefile create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait01.c diff --git a/runtest/ltplite b/runtest/ltplite index 89accc4..79ab6a1 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -159,6 +159,8 @@ dup203 dup203 dup204 dup204 dup205 dup205 +epoll_wait01 epoll_wait01 + execl01 execl01 execle01 execle01 execlp01 execlp01 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index 85950bf..20fe314 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -100,6 +100,8 @@ dup203 dup203 dup204 dup204 dup205 dup205 +epoll_wait01 epoll_wait01 + execl01 execl01 execle01 execle01 execlp01 execlp01 diff --git a/runtest/syscalls b/runtest/syscalls index 5f169a3..a1591ec 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -122,6 +122,7 @@ dup3_02 dup3_02 epoll_create1_01 epoll_create1_01 epoll01 epoll-ltp +epoll_wait01 epoll_wait01 eventfd01 eventfd01 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index de403e4..01a3cc0 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -97,6 +97,7 @@ /dup3/dup3_02 /epoll/epoll-ltp /epoll_create1/epoll_create1_01 +/epoll_wait/epoll_wait01 /eventfd/eventfd01 /eventfd2/eventfd2_01 /eventfd2/eventfd2_02 diff --git a/testcases/kernel/syscalls/epoll_wait/Makefile b/testcases/kernel/syscalls/epoll_wait/Makefile new file mode 100644 index 0000000..289aaaf --- /dev/null +++ b/testcases/kernel/syscalls/epoll_wait/Makefile @@ -0,0 +1,23 @@ +# +# Copyright (c) 2016 Fujitsu Ltd. +# Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. +# + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk + +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c new file mode 100644 index 0000000..9ae7580 --- /dev/null +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait01.c @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2016 Fujitsu Ltd. + * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + */ + +/* + * Description: + * Basic test for epoll_wait(2). + * Check that epoll_wait(2) works for EPOLLOUT and EPOLLIN events + * on a epoll instance and that struct epoll_event is set correctly. + */ + +#include <sys/epoll.h> +#include <poll.h> +#include <string.h> +#include <errno.h> + +#include "test.h" +#include "safe_macros.h" + +char *TCID = "epoll_wait01"; +int TST_TOTAL = 3; + +static int write_size, epfd, fds[2], fds2[2]; +static struct epoll_event epevs[3] = { + {.events = EPOLLIN}, + {.events = EPOLLOUT}, + {.events = EPOLLIN} +}; + +static void setup(void); +static int get_writesize(void); +static void verify_epollout(void); +static void verify_epollin(void); +static void verify_epollio(void); +static int has_event(struct epoll_event *, int, int, uint32_t); +static void dump_epevs(struct epoll_event *, int); +static void cleanup(void); + +int main(int ac, char **av) +{ + int lc; + + tst_parse_opts(ac, av, NULL, NULL); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + verify_epollout(); + verify_epollin(); + verify_epollio(); + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; + + SAFE_PIPE(NULL, fds); + SAFE_PIPE(cleanup, fds2); + + write_size = get_writesize(); + + epfd = epoll_create(3); + if (epfd == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to create epoll instance"); + } + + epevs[0].data.fd = fds[0]; + epevs[1].data.fd = fds[1]; + epevs[2].data.fd = fds2[0]; + + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0]) || + epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[1]) || + epoll_ctl(epfd, EPOLL_CTL_ADD, fds2[0], &epevs[2])) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to register epoll target"); + } +} + +static int get_writesize(void) +{ + int nfd, write_size; + char buf[4096]; + + memset(buf, 'a', sizeof(buf)); + + struct pollfd pfd[] = { + {.fd = fds[0], .events = POLLIN}, + {.fd = fds[1], .events = POLLOUT}, + }; + + write_size = 0; + do { + write_size += SAFE_WRITE(cleanup, 0, fds[1], buf, sizeof(buf)); + nfd = poll(pfd, 2, -1); + if (nfd == -1) + tst_brkm(TBROK | TERRNO, cleanup, "poll failed"); + } while (nfd == 2); + + char read_buf[write_size]; + + SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(read_buf)); + + return write_size; +} + +static void verify_epollout(void) +{ + TEST(epoll_wait(epfd, epevs, 3, -1)); + + if (TEST_RETURN == -1) { + tst_resm(TFAIL | TTERRNO, "epoll_wait() epollout failed"); + return; + } + + if (TEST_RETURN != 1) { + tst_resm(TFAIL, "epoll_wait() returned %li, expected 1", + TEST_RETURN); + return; + } + + if (epevs[0].data.fd != fds[1]) { + tst_resm(TFAIL, "epoll.data.fd %i, expected %i", + epevs[0].data.fd, fds[1]); + return; + } + + if (epevs[0].events != EPOLLOUT) { + tst_resm(TFAIL, "epoll.events %x, expected EPOLLOUT %x", + epevs[0].events, EPOLLOUT); + return; + } + + tst_resm(TPASS, "epoll_wait() epollout"); +} + +static void verify_epollin(void) +{ + char write_buf[write_size]; + char read_buf[sizeof(write_buf)]; + + memset(write_buf, 'a', sizeof(write_buf)); + + SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf)); + + TEST(epoll_wait(epfd, epevs, 3, -1)); + + if (TEST_RETURN == -1) { + tst_resm(TFAIL | TTERRNO, "epoll_wait() epollin failed"); + goto end; + } + + if (TEST_RETURN != 1) { + tst_resm(TFAIL, "epoll_wait() returned %li, expected 1", + TEST_RETURN); + goto end; + } + + if (epevs[0].data.fd != fds[0]) { + tst_resm(TFAIL, "epoll.data.fd %i, expected %i", + epevs[0].data.fd, fds[0]); + goto end; + } + + if (epevs[0].events != EPOLLIN) { + tst_resm(TFAIL, "epoll.events %x, expected EPOLLIN %x", + epevs[0].events, EPOLLIN); + goto end; + } + + tst_resm(TPASS, "epoll_wait() epollin"); + +end: + SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf)); +} + +static void verify_epollio(void) +{ + char write_buf[] = "Testing"; + char read_buf[sizeof(write_buf)]; + + SAFE_WRITE(cleanup, 1, fds[1], write_buf, sizeof(write_buf)); + + TEST(epoll_wait(epfd, epevs, 3, -1)); + + if (TEST_RETURN == -1) { + tst_resm(TFAIL | TTERRNO, "epoll_wait() epollio failed"); + goto end; + } + + if (TEST_RETURN != 2) { + tst_resm(TFAIL, "epoll_wait() returned %li, expected 2", + TEST_RETURN); + goto end; + } + + if (!has_event(epevs, 2, fds[0], EPOLLIN)) { + dump_epevs(epevs, 2); + tst_resm(TFAIL, "epoll_wait() expected %d and EPOLLIN %x", + fds[0], EPOLLIN); + goto end; + } + + if (!has_event(epevs, 2, fds[1], EPOLLOUT)) { + dump_epevs(epevs, 2); + tst_resm(TFAIL, "epoll_wait() expected %d and EPOLLOUT %x", + fds[1], EPOLLOUT); + goto end; + } + + tst_resm(TPASS, "epoll_wait() epollio"); + +end: + SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(write_buf)); +} + +static int has_event(struct epoll_event *epevs, int epevs_len, + int fd, uint32_t events) +{ + int i, result; + + result = 0; + for (i = 0; i < epevs_len; i++) { + if ((epevs[i].data.fd == fd) && (epevs[i].events == events)) { + result = 1; + break; + } + } + + return result; +} + +static void dump_epevs(struct epoll_event *epevs, int epevs_len) +{ + int i; + + for (i = 0; i < epevs_len; i++) { + tst_resm(TINFO, "epevs[%d]: epoll.data.fd %d, epoll.events %x", + i, epevs[i].data.fd, epevs[i].events); + } +} + +static void cleanup(void) +{ + if (epfd > 0 && close(epfd)) + tst_resm(TWARN | TERRNO, "failed to close epfd"); + + if (close(fds[0])) + tst_resm(TWARN | TERRNO, "failed to close fds[0]"); + + if (close(fds[1])) + tst_resm(TWARN | TERRNO, "failed to close fds[1]"); + + if (fds2[0] > 0 && close(fds2[0])) + tst_resm(TWARN | TERRNO, "failed to close fds2[0]"); + + if (fds2[1] > 0 && close(fds2[1])) + tst_resm(TWARN | TERRNO, "failed to close fds2[1]"); +} -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v2 2/3] epoll_wait/epoll_wait02.c: add new testcase 2016-02-17 10:51 ` [LTP] [PATCH v2 " Guangwen Feng @ 2016-02-17 10:51 ` Guangwen Feng 2016-02-25 12:37 ` Cyril Hrubis 2016-02-17 10:51 ` [LTP] [PATCH v2 3/3] epoll_wait/epoll_wait03.c: " Guangwen Feng 2016-02-24 16:11 ` [LTP] [PATCH v2 1/3] epoll_wait/epoll_wait01.c: " Cyril Hrubis 2 siblings, 1 reply; 17+ messages in thread From: Guangwen Feng @ 2016-02-17 10:51 UTC (permalink / raw) To: ltp Check that epoll_wait(2) timeouts correctly. Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> --- runtest/ltplite | 1 + runtest/stress.part3 | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/epoll_wait/Makefile | 2 + .../kernel/syscalls/epoll_wait/epoll_wait02.c | 145 +++++++++++++++++++++ 6 files changed, 151 insertions(+) create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait02.c diff --git a/runtest/ltplite b/runtest/ltplite index 79ab6a1..aa4ebdc 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -160,6 +160,7 @@ dup204 dup204 dup205 dup205 epoll_wait01 epoll_wait01 +epoll_wait02 epoll_wait02 execl01 execl01 execle01 execle01 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index 20fe314..7d629c5 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -101,6 +101,7 @@ dup204 dup204 dup205 dup205 epoll_wait01 epoll_wait01 +epoll_wait02 epoll_wait02 execl01 execl01 execle01 execle01 diff --git a/runtest/syscalls b/runtest/syscalls index a1591ec..23d7adc 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -123,6 +123,7 @@ dup3_02 dup3_02 epoll_create1_01 epoll_create1_01 epoll01 epoll-ltp epoll_wait01 epoll_wait01 +epoll_wait02 epoll_wait02 eventfd01 eventfd01 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 01a3cc0..85feeac 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -98,6 +98,7 @@ /epoll/epoll-ltp /epoll_create1/epoll_create1_01 /epoll_wait/epoll_wait01 +/epoll_wait/epoll_wait02 /eventfd/eventfd01 /eventfd2/eventfd2_01 /eventfd2/eventfd2_02 diff --git a/testcases/kernel/syscalls/epoll_wait/Makefile b/testcases/kernel/syscalls/epoll_wait/Makefile index 289aaaf..f29b9a7 100644 --- a/testcases/kernel/syscalls/epoll_wait/Makefile +++ b/testcases/kernel/syscalls/epoll_wait/Makefile @@ -18,6 +18,8 @@ top_srcdir ?= ../../../.. +epoll_wait02: LDLIBS+=-lrt + include $(top_srcdir)/include/mk/testcases.mk include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c new file mode 100644 index 0000000..a32e82e --- /dev/null +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait02.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2016 Fujitsu Ltd. + * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + */ + +/* + * Description: + * Check that epoll_wait(2) timeouts correctly. + */ + +#include <sys/epoll.h> +#include <unistd.h> +#include <errno.h> + +#include "test.h" +#include "safe_macros.h" + +char *TCID = "epoll_wait02"; +int TST_TOTAL = 1; + +static int epfd, fds[2]; +static char *opt_sleep_ms; +static struct epoll_event epevs[1] = { + {.events = EPOLLIN} +}; + +static option_t opts[] = { + {"s:", NULL, &opt_sleep_ms}, + {NULL, NULL, NULL} +}; + +static void setup(void); +static void cleanup(void); +static void help(void); + +int main(int ac, char **av) +{ + int lc, threshold; + long long elapsed_ms, sleep_ms = 100; + + tst_parse_opts(ac, av, opts, help); + + if (opt_sleep_ms) { + sleep_ms = atoll(opt_sleep_ms); + + if (sleep_ms == 0) { + tst_brkm(TBROK, NULL, + "Invalid timeout '%s'", opt_sleep_ms); + } + } + + threshold = sleep_ms / 100 + 10; + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + tst_timer_start(CLOCK_MONOTONIC); + TEST(epoll_wait(epfd, epevs, 1, sleep_ms)); + tst_timer_stop(); + + if (TEST_RETURN == -1) { + tst_resm(TFAIL | TTERRNO, "epoll_wait() failed"); + continue; + } + + if (TEST_RETURN != 0) { + tst_resm(TFAIL, "epoll_wait() returned %li, expected 0", + TEST_RETURN); + continue; + } + + elapsed_ms = tst_timer_elapsed_ms(); + + if (elapsed_ms < sleep_ms) { + tst_resm(TFAIL, "epoll_wait() woken up too early %llims, " + "expected %llims", elapsed_ms, sleep_ms); + continue; + } + + if (elapsed_ms - sleep_ms > threshold) { + tst_resm(TFAIL, "epoll_wait() slept too long %llims, " + "expected %llims, threshold %i", + elapsed_ms, sleep_ms, threshold); + continue; + } + + tst_resm(TPASS, "epoll_wait() slept %llims, expected %llims, " + "threshold %i", elapsed_ms, sleep_ms, threshold); + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_timer_check(CLOCK_MONOTONIC); + + SAFE_PIPE(NULL, fds); + + epfd = epoll_create(1); + if (epfd == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to create epoll instance"); + } + + epevs[0].data.fd = fds[0]; + + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0])) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to register epoll target"); + } +} + +static void cleanup(void) +{ + if (epfd > 0 && close(epfd)) + tst_resm(TWARN | TERRNO, "failed to close epfd"); + + if (close(fds[0])) + tst_resm(TWARN | TERRNO, "close(fds[0]) failed"); + + if (close(fds[1])) + tst_resm(TWARN | TERRNO, "close(fds[1]) failed"); +} + +static void help(void) +{ + printf(" -s epoll_wait() timeout length in ms\n"); +} -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v2 2/3] epoll_wait/epoll_wait02.c: add new testcase 2016-02-17 10:51 ` [LTP] [PATCH v2 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng @ 2016-02-25 12:37 ` Cyril Hrubis 0 siblings, 0 replies; 17+ messages in thread From: Cyril Hrubis @ 2016-02-25 12:37 UTC (permalink / raw) To: ltp Hi! Applied, thanks. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH v2 3/3] epoll_wait/epoll_wait03.c: add new testcase 2016-02-17 10:51 ` [LTP] [PATCH v2 " Guangwen Feng 2016-02-17 10:51 ` [LTP] [PATCH v2 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng @ 2016-02-17 10:51 ` Guangwen Feng 2016-02-25 13:52 ` [LTP] [PATCH v2 3/3] llistxattr/llistxattr03.c: " Cyril Hrubis 2016-02-24 16:11 ` [LTP] [PATCH v2 1/3] epoll_wait/epoll_wait01.c: " Cyril Hrubis 2 siblings, 1 reply; 17+ messages in thread From: Guangwen Feng @ 2016-02-17 10:51 UTC (permalink / raw) To: ltp Verify that: 1) epoll_wait(2) fails if epfd is not a valid file descriptor 2) epoll_wait(2) fails if epfd is not an epoll file descriptor 3) epoll_wait(2) fails if maxevents is less than zero 4) epoll_wait(2) fails if maxevents is equal to zero 5) epoll_wait(2) fails if the memory area pointed to by events is not accessible with write permissions. Expected result: 1) epoll_wait(2) should return -1 and set errno to EBADF 2) epoll_wait(2) should return -1 and set errno to EINVAL 3) epoll_wait(2) should return -1 and set errno to EINVAL 4) epoll_wait(2) should return -1 and set errno to EINVAL 5) epoll_wait(2) should return -1 and set errno to EFAULT Signed-off-by: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> --- runtest/ltplite | 1 + runtest/stress.part3 | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + .../kernel/syscalls/epoll_wait/epoll_wait03.c | 158 +++++++++++++++++++++ 5 files changed, 162 insertions(+) create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait03.c diff --git a/runtest/ltplite b/runtest/ltplite index aa4ebdc..ced593f 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -161,6 +161,7 @@ dup205 dup205 epoll_wait01 epoll_wait01 epoll_wait02 epoll_wait02 +epoll_wait03 epoll_wait03 execl01 execl01 execle01 execle01 diff --git a/runtest/stress.part3 b/runtest/stress.part3 index 7d629c5..ab2c531 100644 --- a/runtest/stress.part3 +++ b/runtest/stress.part3 @@ -102,6 +102,7 @@ dup205 dup205 epoll_wait01 epoll_wait01 epoll_wait02 epoll_wait02 +epoll_wait03 epoll_wait03 execl01 execl01 execle01 execle01 diff --git a/runtest/syscalls b/runtest/syscalls index 23d7adc..dbef381 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -124,6 +124,7 @@ epoll_create1_01 epoll_create1_01 epoll01 epoll-ltp epoll_wait01 epoll_wait01 epoll_wait02 epoll_wait02 +epoll_wait03 epoll_wait03 eventfd01 eventfd01 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 85feeac..97b8fd8 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -99,6 +99,7 @@ /epoll_create1/epoll_create1_01 /epoll_wait/epoll_wait01 /epoll_wait/epoll_wait02 +/epoll_wait/epoll_wait03 /eventfd/eventfd01 /eventfd2/eventfd2_01 /eventfd2/eventfd2_02 diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c new file mode 100644 index 0000000..56b32da --- /dev/null +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait03.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2016 Fujitsu Ltd. + * Author: Guangwen Feng <fenggw-fnst@cn.fujitsu.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. + */ + +/* + * Description: + * 1) epoll_wait(2) fails if epfd is not a valid file descriptor + * 2) epoll_wait(2) fails if epfd is not an epoll file descriptor + * 3) epoll_wait(2) fails if maxevents is less than zero + * 4) epoll_wait(2) fails if maxevents is equal to zero + * 5) epoll_wait(2) fails if the memory area pointed to by events + * is not accessible with write permissions. + * + * Expected Result: + * 1) epoll_wait(2) should return -1 and set errno to EBADF + * 2) epoll_wait(2) should return -1 and set errno to EINVAL + * 3) epoll_wait(2) should return -1 and set errno to EINVAL + * 4) epoll_wait(2) should return -1 and set errno to EINVAL + * 5) epoll_wait(2) should return -1 and set errno to EFAULT + */ + +#include <sys/epoll.h> +#include <sys/mman.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include "test.h" +#include "safe_macros.h" + +static int page_size, fds[2], epfd, inv_epfd, bad_epfd = -1; + +static struct epoll_event epevs[1] = { + {.events = EPOLLOUT} +}; + +static struct epoll_event *ev_rdwr = epevs; +static struct epoll_event *ev_rdonly; + +static struct test_case_t { + int *epfd; + struct epoll_event **ev; + int maxevents; + int exp_errno; +} tc[] = { + /* test1 */ + {&bad_epfd, &ev_rdwr, 1, EBADF}, + /* test2 */ + {&inv_epfd, &ev_rdwr, 1, EINVAL}, + /* test3 */ + {&epfd, &ev_rdwr, -1, EINVAL}, + /* test4 */ + {&epfd, &ev_rdwr, 0, EINVAL}, + /* test5 */ + {&epfd, &ev_rdonly, 1, EFAULT} +}; + +char *TCID = "epoll_wait03"; +int TST_TOTAL = ARRAY_SIZE(tc); + +static void setup(void); +static void verify_epoll_wait(struct test_case_t *tc); +static void cleanup(void); + +int main(int ac, char **av) +{ + int lc, i; + + tst_parse_opts(ac, av, NULL, NULL); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + for (i = 0; i < TST_TOTAL; i++) + verify_epoll_wait(&tc[i]); + } + + cleanup(); + tst_exit(); +} + +static void setup(void) +{ + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; + + page_size = getpagesize(); + + ev_rdonly = SAFE_MMAP(NULL, NULL, page_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + SAFE_PIPE(NULL, fds); + + epfd = epoll_create(1); + if (epfd == -1) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to create epoll instance"); + } + + epevs[0].data.fd = fds[1]; + + if (mprotect(ev_rdonly, page_size, PROT_READ)) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to set memory area read-only"); + } + + if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[1], &epevs[0])) { + tst_brkm(TBROK | TERRNO, cleanup, + "failed to register epoll target"); + } +} + +static void verify_epoll_wait(struct test_case_t *tc) +{ + TEST(epoll_wait(*(tc->epfd), *(tc->ev), tc->maxevents, -1)); + if (TEST_RETURN != -1) { + tst_resm(TFAIL, "epoll_wait() succeed unexpectedly"); + } else { + if (tc->exp_errno == TEST_ERRNO) { + tst_resm(TPASS | TTERRNO, + "epoll_wait() fails as expected"); + } else { + tst_resm(TFAIL | TTERRNO, + "epoll_wait() fails unexpectedly, " + "expected %d: %s", tc->exp_errno, + tst_strerrno(tc->exp_errno)); + } + } +} + +static void cleanup(void) +{ + if (epfd > 0 && close(epfd)) + tst_resm(TWARN | TERRNO, "failed to close epfd"); + + if (close(fds[0])) + tst_resm(TWARN | TERRNO, "close(fds[0]) failed"); + + if (close(fds[1])) + tst_resm(TWARN | TERRNO, "close(fds[1]) failed"); +} -- 1.8.4.2 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v2 3/3] llistxattr/llistxattr03.c: add new testcase 2016-02-17 10:51 ` [LTP] [PATCH v2 3/3] epoll_wait/epoll_wait03.c: " Guangwen Feng @ 2016-02-25 13:52 ` Cyril Hrubis 0 siblings, 0 replies; 17+ messages in thread From: Cyril Hrubis @ 2016-02-25 13:52 UTC (permalink / raw) To: ltp Hi! > + ev_rdonly = SAFE_MMAP(NULL, NULL, page_size, PROT_READ | PROT_WRITE, > + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); > + ... > + if (mprotect(ev_rdonly, page_size, PROT_READ)) { > + tst_brkm(TBROK | TERRNO, cleanup, > + "failed to set memory area read-only"); > + } I've removed the PROT_WRITE from the mmap() flags and the mprotect() and pushed, thanks. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH v2 1/3] epoll_wait/epoll_wait01.c: add new testcase 2016-02-17 10:51 ` [LTP] [PATCH v2 " Guangwen Feng 2016-02-17 10:51 ` [LTP] [PATCH v2 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng 2016-02-17 10:51 ` [LTP] [PATCH v2 3/3] epoll_wait/epoll_wait03.c: " Guangwen Feng @ 2016-02-24 16:11 ` Cyril Hrubis 2 siblings, 0 replies; 17+ messages in thread From: Cyril Hrubis @ 2016-02-24 16:11 UTC (permalink / raw) To: ltp Hi! Pushed with minor changes. Thanks. > +static int get_writesize(void) > +{ > + int nfd, write_size; > + char buf[4096]; > + > + memset(buf, 'a', sizeof(buf)); > + > + struct pollfd pfd[] = { > + {.fd = fds[0], .events = POLLIN}, > + {.fd = fds[1], .events = POLLOUT}, > + }; > + > + write_size = 0; > + do { > + write_size += SAFE_WRITE(cleanup, 0, fds[1], buf, sizeof(buf)); > + nfd = poll(pfd, 2, -1); > + if (nfd == -1) > + tst_brkm(TBROK | TERRNO, cleanup, "poll failed"); > + } while (nfd == 2); I've removed the fds[0] from the pollfd structure and instead of that changed the poll() to have 1 ms timeout. Since making sure that it returns on timeout is less confusing than making sure the poll returns because we passed another file descriptor that has some data to be read... > + char read_buf[write_size]; > + > + SAFE_READ(cleanup, 1, fds[0], read_buf, sizeof(read_buf)); > + > + return write_size; > +} ... > +static int has_event(struct epoll_event *epevs, int epevs_len, > + int fd, uint32_t events) > +{ > + int i, result; > + > + result = 0; > + for (i = 0; i < epevs_len; i++) { > + if ((epevs[i].data.fd == fd) && (epevs[i].events == events)) { > + result = 1; > + break; > + } > + } > + > + return result; > +} And simplified this part to: ... { int i; for (i = 0; i < epevs_len; i++) { if ((epevs[i].data.fd == fd) && (epevs[i].events == events)) return 1; } return 0; } -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 17+ messages in thread
* [LTP] [PATCH 1/3] llistxattr/llistxattr01.c: add new testcase
@ 2016-02-18 12:03 Cyril Hrubis
2016-02-19 4:55 ` [LTP] [PATCH v2 " Xiao Yang
0 siblings, 1 reply; 17+ messages in thread
From: Cyril Hrubis @ 2016-02-18 12:03 UTC (permalink / raw)
To: ltp
Hi!
> > I do not like the special case for seliux here. What we should do
> > instead is to:
> >
> > * Create file/symlink and store it's attribute list
> >
> > * Add an attribute
> >
> > * Check that the list has exactly one more attribute
> >
> > * Remove the file/symlink
> >
> >
> If we don't check that selinux adds default attribute to symlinks, What
> about the return value.
>
> We're not going to judge the size of the extended attribute name list.
> That's OK?
By "Check that the list has exactly one more attribute" I meant that we
compare the result to the previous state. If we store the attribute list
right after the symlink was created we can check if the increase in list
size is as expected. Or is there a reason why we can't do this?
--
Cyril Hrubis
chrubis@suse.cz
^ permalink raw reply [flat|nested] 17+ messages in thread* [LTP] [PATCH v2 1/3] llistxattr/llistxattr01.c: add new testcase 2016-02-18 12:03 [LTP] [PATCH 1/3] llistxattr/llistxattr01.c: " Cyril Hrubis @ 2016-02-19 4:55 ` Xiao Yang 2016-02-19 4:55 ` [LTP] [PATCH v2 3/3] llistxattr/llistxattr03.c: " Xiao Yang 0 siblings, 1 reply; 17+ messages in thread From: Xiao Yang @ 2016-02-19 4:55 UTC (permalink / raw) To: ltp The testcase checks the basic functionality of the llistxattr(2). llistxattr(2) retrieves the list of extended attribute names associated with the link itself in the filesystem. Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com> --- runtest/ltplite | 2 + runtest/syscalls | 2 + testcases/kernel/syscalls/.gitignore | 1 + testcases/kernel/syscalls/llistxattr/Makefile | 23 +++ .../kernel/syscalls/llistxattr/llistxattr01.c | 159 +++++++++++++++++++++ 5 files changed, 187 insertions(+) create mode 100644 testcases/kernel/syscalls/llistxattr/Makefile create mode 100644 testcases/kernel/syscalls/llistxattr/llistxattr01.c diff --git a/runtest/ltplite b/runtest/ltplite index 89accc4..de7cecb 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -387,6 +387,8 @@ link08 link08 listen01 listen01 +llistxattr01 llistxattr01 + llseek01 llseek01 llseek02 llseek02 llseek03 llseek03 diff --git a/runtest/syscalls b/runtest/syscalls index 5f169a3..c48dd92 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -513,6 +513,8 @@ linkat02 linkat02 listen01 listen01 +llistxattr01 llistxattr01 + llseek01 llseek01 llseek02 llseek02 llseek03 llseek03 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index de403e4..47f2fc8 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -473,6 +473,7 @@ /linkat/linkat01 /linkat/linkat02 /listen/listen01 +/llistxattr/llistxattr01 /llseek/llseek01 /llseek/llseek02 /llseek/llseek03 diff --git a/testcases/kernel/syscalls/llistxattr/Makefile b/testcases/kernel/syscalls/llistxattr/Makefile new file mode 100644 index 0000000..ed05a48 --- /dev/null +++ b/testcases/kernel/syscalls/llistxattr/Makefile @@ -0,0 +1,23 @@ +# +# Copyright (c) 2016 Fujitsu Ltd. +# Author: Xiao Yang <yangx.jy@cn.fujitsu.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See +# the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. +# + +top_srcdir ?= ../../../.. + +include $(top_srcdir)/include/mk/testcases.mk + +include $(top_srcdir)/include/mk/generic_leaf_target.mk diff --git a/testcases/kernel/syscalls/llistxattr/llistxattr01.c b/testcases/kernel/syscalls/llistxattr/llistxattr01.c new file mode 100644 index 0000000..0bf6f25 --- /dev/null +++ b/testcases/kernel/syscalls/llistxattr/llistxattr01.c @@ -0,0 +1,159 @@ +/* +* Copyright (c) 2016 Fujitsu Ltd. +* Author: Xiao Yang <yangx.jy@cn.fujitsu.com> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of version 2 of the GNU General Public License as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it would be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* +* You should have received a copy of the GNU General Public License +* alone with this program. +*/ + +/* +* Test Name: llistxattr01 +* +* Description: +* The testcase checks the basic functionality of the llistxattr(2). +* llistxattr(2) retrieves the list of extended attribute names +* associated with the link itself in the filesystem. +* +*/ + +#include "config.h" +#include <errno.h> +#include <sys/types.h> +#include <string.h> + +#ifdef HAVE_ATTR_XATTR_H +#include <attr/xattr.h> +#endif + +#include "test.h" +#include "safe_macros.h" +#include "safe_file_ops.h" + +char *TCID = "llistxattr01"; + +#ifdef HAVE_ATTR_XATTR_H +#define SECURITY_KEY1 "security.ltptest1" +#define SECURITY_KEY2 "security.ltptest2" +#define VALUE "test" +#define VALUE_SIZE 4 +#define KEY_SIZE 17 + +static void verify_llistxattr(void); +static void setup(void); +static void set_xattr(const char *, const char *); +static int has_attribute(const char *, int, const char *); +static void cleanup(void); + +int TST_TOTAL = 1; + +int main(int ac, char **av) +{ + int lc; + + tst_parse_opts(ac, av, NULL, NULL); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + verify_llistxattr(); + } + + cleanup(); + tst_exit(); +} + +static void verify_llistxattr(void) +{ + int size = 64; + char buf[size]; + + TEST(llistxattr("symlink", buf, size)); + if (TEST_RETURN == -1) { + tst_resm(TFAIL | TERRNO, "llistxattr() failed"); + return; + } + + if (has_attribute(buf, size, SECURITY_KEY1)) { + tst_resm(TFAIL, "get file attribute %s unexpectlly", + SECURITY_KEY1); + return; + } + + if (!has_attribute(buf, size, SECURITY_KEY2)) { + tst_resm(TFAIL, "missing attribute %s", SECURITY_KEY2); + return; + } + + tst_resm(TPASS, "llistxattr() succeeded"); +} + +static void setup(void) +{ + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; + + tst_tmpdir(); + + SAFE_TOUCH(cleanup, "testfile", 0644, NULL); + + SAFE_SYMLINK(cleanup, "testfile", "symlink"); + + set_xattr("testfile", SECURITY_KEY1); + + set_xattr("symlink", SECURITY_KEY2); +} + +static void set_xattr(const char *path, const char *key) +{ + int n; + + n = lsetxattr(path, key, VALUE, VALUE_SIZE, XATTR_CREATE); + if (n == -1) { + if (errno == ENOTSUP) { + tst_brkm(TCONF, cleanup, + "no xattr support in fs or mounted " + "without user_xattr option"); + } + + if (errno == EEXIST) { + tst_brkm(TFAIL, cleanup, "exist attribute %s", key); + } else { + tst_brkm(TFAIL | TERRNO, cleanup, + "lsetxattr() failed"); + } + } +} + +static int has_attribute(const char *list, int llen, const char *attr) +{ + int i; + + for (i = 0; i < llen; i += strlen(list + i) + 1) { + if (!strcmp(list + i, attr)) + return 1; + } + return 0; +} + +static void cleanup(void) +{ + tst_rmdir(); +} + +#else /* HAVE_ATTR_XATTR_H */ +int main(int ac, char **av) +{ + tst_brkm(TCONF, NULL, "<attr/xattr.h> does not exist."); +} +#endif -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v2 3/3] llistxattr/llistxattr03.c: add new testcase 2016-02-19 4:55 ` [LTP] [PATCH v2 " Xiao Yang @ 2016-02-19 4:55 ` Xiao Yang 2016-02-24 14:28 ` Cyril Hrubis 0 siblings, 1 reply; 17+ messages in thread From: Xiao Yang @ 2016-02-19 4:55 UTC (permalink / raw) To: ltp llistxattr() is identical to listxattr(), we call llistxattr() with zero size and check that it returns value which is suitable size of buffer to hold the name list. Signed-off-by: Xiao Yang <yangx.jy@cn.fujitsu.com> --- runtest/ltplite | 1 + runtest/syscalls | 1 + testcases/kernel/syscalls/.gitignore | 1 + .../kernel/syscalls/llistxattr/llistxattr03.c | 114 +++++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 testcases/kernel/syscalls/llistxattr/llistxattr03.c diff --git a/runtest/ltplite b/runtest/ltplite index ea18c22..d9a362d 100644 --- a/runtest/ltplite +++ b/runtest/ltplite @@ -389,6 +389,7 @@ listen01 listen01 llistxattr01 llistxattr01 llistxattr02 llistxattr02 +llistxattr03 llistxattr03 llseek01 llseek01 llseek02 llseek02 diff --git a/runtest/syscalls b/runtest/syscalls index a986a4e..d1abf16 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -515,6 +515,7 @@ listen01 listen01 llistxattr01 llistxattr01 llistxattr02 llistxattr02 +llistxattr03 llistxattr03 llseek01 llseek01 llseek02 llseek02 diff --git a/testcases/kernel/syscalls/.gitignore b/testcases/kernel/syscalls/.gitignore index 1762c14..f5ea349 100644 --- a/testcases/kernel/syscalls/.gitignore +++ b/testcases/kernel/syscalls/.gitignore @@ -475,6 +475,7 @@ /listen/listen01 /llistxattr/llistxattr01 /llistxattr/llistxattr02 +/llistxattr/llistxattr03 /llseek/llseek01 /llseek/llseek02 /llseek/llseek03 diff --git a/testcases/kernel/syscalls/llistxattr/llistxattr03.c b/testcases/kernel/syscalls/llistxattr/llistxattr03.c new file mode 100644 index 0000000..2c5792f --- /dev/null +++ b/testcases/kernel/syscalls/llistxattr/llistxattr03.c @@ -0,0 +1,114 @@ +/* +* Copyright (c) 2016 Fujitsu Ltd. +* Author: Xiao Yang <yangx.jy@cn.fujitsu.com> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of version 2 of the GNU General Public License as +* published by the Free Software Foundation. +* +* This program is distributed in the hope that it would be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* +* You should have received a copy of the GNU General Public License +* alone with this program. +*/ + +/* +* Test Name: llistxattr03 +* +* Description: +* llistxattr is identical to listxattr. an empty buffer of size zero +* can return the current size of the list of extended attribute names, +* which can be used to estimate a suitable buffer. +*/ + +#include "config.h" +#include <errno.h> +#include <sys/types.h> + +#ifdef HAVE_ATTR_XATTR_H +#include <attr/xattr.h> +#endif + +#include "test.h" +#include "safe_macros.h" +#include "safe_file_ops.h" + +char *TCID = "llistxattr03"; + +#ifdef HAVE_ATTR_XATTR_H + +static void verify_llistxattr(void); +static void setup(void); +static int check_suitable_buf(long); +static void cleanup(void); + +int TST_TOTAL = 1; + +int main(int ac, char **av) +{ + int lc; + + tst_parse_opts(ac, av, NULL, NULL); + + setup(); + + for (lc = 0; TEST_LOOPING(lc); lc++) { + tst_count = 0; + + verify_llistxattr(); + } + + cleanup(); + tst_exit(); +} + +static void verify_llistxattr(void) +{ + TEST(llistxattr("testfile", NULL, 0)); + if (TEST_RETURN == -1) { + tst_resm(TFAIL | TERRNO, "llistxattr() failed"); + return; + } + + if (check_suitable_buf(TEST_RETURN)) + tst_resm(TPASS, "llistxattr() succeed with suitable buffer"); + else + tst_resm(TFAIL, "llistxattr() failed with small buffer"); +} + +static void setup(void) +{ + tst_sig(NOFORK, DEF_HANDLER, cleanup); + + TEST_PAUSE; + + tst_tmpdir(); + + SAFE_TOUCH(cleanup, "testfile", 0644, NULL); +} + +static int check_suitable_buf(long size) +{ + int n; + char buf[size]; + + n = llistxattr("testfile", buf, size); + if (n == -1) + return 0; + else + return 1; +} + +static void cleanup(void) +{ + tst_rmdir(); +} + +#else /* HAVE_ATTR_XATTR_H */ +int main(int ac, char **av) +{ + tst_brkm(TCONF, NULL, "<attr/xattr.h> does not exist."); +} +#endif -- 1.8.3.1 ^ permalink raw reply related [flat|nested] 17+ messages in thread
* [LTP] [PATCH v2 3/3] llistxattr/llistxattr03.c: add new testcase 2016-02-19 4:55 ` [LTP] [PATCH v2 3/3] llistxattr/llistxattr03.c: " Xiao Yang @ 2016-02-24 14:28 ` Cyril Hrubis 0 siblings, 0 replies; 17+ messages in thread From: Cyril Hrubis @ 2016-02-24 14:28 UTC (permalink / raw) To: ltp Hi! > +static void verify_llistxattr(void) > +{ > + TEST(llistxattr("testfile", NULL, 0)); > + if (TEST_RETURN == -1) { > + tst_resm(TFAIL | TERRNO, "llistxattr() failed"); > + return; > + } For me the call returns 0 here. Can we create another file with some attribute in the setup as well so that we can test both with no attributes (zero sized buffer) and with non-zero one? Otherwise it looks fine. -- Cyril Hrubis chrubis@suse.cz ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2016-02-25 13:52 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-12-30 10:44 [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: add new testcase Guangwen Feng 2015-12-30 10:44 ` [LTP] [PATCH 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng 2016-01-28 16:35 ` Cyril Hrubis 2015-12-30 10:44 ` [LTP] [PATCH 3/3] epoll_wait/epoll_wait03.c: " Guangwen Feng 2016-01-28 17:16 ` Cyril Hrubis 2016-01-06 1:19 ` [LTP] [PATCH 4/4] epoll_wait/epoll_wait04.c: " Guangwen Feng 2016-01-28 17:24 ` Cyril Hrubis 2016-01-28 16:19 ` [LTP] [PATCH 1/3] epoll_wait/epoll_wait01.c: " Cyril Hrubis 2016-02-01 5:28 ` Guangwen Feng 2016-02-17 10:51 ` [LTP] [PATCH v2 " Guangwen Feng 2016-02-17 10:51 ` [LTP] [PATCH v2 2/3] epoll_wait/epoll_wait02.c: " Guangwen Feng 2016-02-25 12:37 ` Cyril Hrubis 2016-02-17 10:51 ` [LTP] [PATCH v2 3/3] epoll_wait/epoll_wait03.c: " Guangwen Feng 2016-02-25 13:52 ` [LTP] [PATCH v2 3/3] llistxattr/llistxattr03.c: " Cyril Hrubis 2016-02-24 16:11 ` [LTP] [PATCH v2 1/3] epoll_wait/epoll_wait01.c: " Cyril Hrubis -- strict thread matches above, loose matches on Subject: below -- 2016-02-18 12:03 [LTP] [PATCH 1/3] llistxattr/llistxattr01.c: " Cyril Hrubis 2016-02-19 4:55 ` [LTP] [PATCH v2 " Xiao Yang 2016-02-19 4:55 ` [LTP] [PATCH v2 3/3] llistxattr/llistxattr03.c: " Xiao Yang 2016-02-24 14:28 ` Cyril Hrubis
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox