tests: add poll.test
* tests/poll.c: New file.
* tests/poll.test: New test.
* tests/.gitignore: Add poll.
* tests/Makefile.am (check_PROGRAMS): Likewise.
(TESTS): Add poll.test.
diff --git a/tests/.gitignore b/tests/.gitignore
index 1cee1f8..5671978 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -72,6 +72,7 @@
pc
personality
pipe
+poll
ppoll
pselect6
readdir
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b36362a..2e77934 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -120,6 +120,7 @@
pc \
personality \
pipe \
+ poll \
ppoll \
pselect6 \
readdir \
@@ -270,6 +271,7 @@
pc.test \
personality.test \
pipe.test \
+ poll.test \
ppoll.test \
pselect6.test \
readdir.test \
diff --git a/tests/poll.c b/tests/poll.c
new file mode 100644
index 0000000..045aca0
--- /dev/null
+++ b/tests/poll.c
@@ -0,0 +1,260 @@
+/*
+ * This file is part of poll strace test.
+ *
+ * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tests.h"
+#include <sys/syscall.h>
+
+#ifdef __NR_poll
+
+# include <assert.h>
+# include <errno.h>
+# include <poll.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+
+#define PRINT_EVENT(flag, member) \
+ if (member & flag) { \
+ if (member != pfd->member) \
+ tprintf("|"); \
+ tprintf(#flag); \
+ member &= ~flag; \
+ }
+
+static void
+print_pollfd_entering(const struct pollfd *const pfd)
+{
+ tprintf("{fd=%d", pfd->fd);
+ if (pfd->fd >= 0) {
+ tprintf(", events=");
+ short events = pfd->events;
+
+ if (pfd->events) {
+ PRINT_EVENT(POLLIN, events)
+ PRINT_EVENT(POLLPRI, events)
+ PRINT_EVENT(POLLOUT, events)
+#ifdef POLLRDNORM
+ PRINT_EVENT(POLLRDNORM, events)
+#endif
+#ifdef POLLWRNORM
+ PRINT_EVENT(POLLWRNORM, events)
+#endif
+#ifdef POLLRDBAND
+ PRINT_EVENT(POLLRDBAND, events)
+#endif
+#ifdef POLLWRBAND
+ PRINT_EVENT(POLLWRBAND, events)
+#endif
+ PRINT_EVENT(POLLERR, events)
+ PRINT_EVENT(POLLHUP, events)
+ PRINT_EVENT(POLLNVAL, events)
+ } else
+ tprintf("0");
+ }
+ tprintf("}");
+}
+
+static void
+print_pollfd_array_entering(const struct pollfd *const pfd,
+ const unsigned int size,
+ const unsigned int valid,
+ const unsigned int abbrev)
+{
+ tprintf("[");
+ unsigned int i;
+ for (i = 0; i < size; ++i) {
+ if (i)
+ tprintf(", ");
+ if (i >= abbrev) {
+ tprintf("...");
+ break;
+ }
+ if (i < valid)
+ print_pollfd_entering(&pfd[i]);
+ else {
+ tprintf("%p", &pfd[i]);
+ break;
+ }
+ }
+ tprintf("]");
+}
+
+static void
+print_pollfd_exiting(const struct pollfd *const pfd,
+ unsigned int *const seen,
+ const unsigned int abbrev)
+{
+ if (!pfd->revents || pfd->fd < 0 || *seen > abbrev)
+ return;
+
+ if (*seen)
+ tprintf(", ");
+ ++(*seen);
+
+ if (*seen > abbrev) {
+ tprintf("...");
+ return;
+ }
+ tprintf("{fd=%d, revents=", pfd->fd);
+ short revents = pfd->revents;
+
+ PRINT_EVENT(POLLIN, revents)
+ PRINT_EVENT(POLLPRI, revents)
+ PRINT_EVENT(POLLOUT, revents)
+#ifdef POLLRDNORM
+ PRINT_EVENT(POLLRDNORM, revents)
+#endif
+#ifdef POLLWRNORM
+ PRINT_EVENT(POLLWRNORM, revents)
+#endif
+#ifdef POLLRDBAND
+ PRINT_EVENT(POLLRDBAND, revents)
+#endif
+#ifdef POLLWRBAND
+ PRINT_EVENT(POLLWRBAND, revents)
+#endif
+ PRINT_EVENT(POLLERR, revents)
+ PRINT_EVENT(POLLHUP, revents)
+ PRINT_EVENT(POLLNVAL, revents)
+ tprintf("}");
+}
+
+static void
+print_pollfd_array_exiting(const struct pollfd *const pfd,
+ const unsigned int size,
+ const unsigned int abbrev)
+{
+ tprintf("[");
+ unsigned int seen = 0;
+ unsigned int i;
+ for (i = 0; i < size; ++i)
+ print_pollfd_exiting(&pfd[i], &seen, abbrev);
+ tprintf("]");
+}
+
+int
+main(int ac, char **av)
+{
+ tprintf("%s", "");
+
+ assert(syscall(__NR_poll, NULL, 42, 0) == -1);
+ if (ENOSYS == errno)
+ perror_msg_and_skip("poll");
+ tprintf("poll(NULL, 42, 0) = -1 EFAULT (%m)\n");
+
+ int fds[2];
+ if (pipe(fds) || pipe(fds))
+ perror_msg_and_fail("pipe");
+
+ const unsigned int abbrev = (ac > 1) ? atoi(av[1]) : -1;
+ const struct pollfd pfds0[] = {
+ { .fd = 0, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND },
+ { .fd = 1, .events = POLLOUT | POLLWRNORM | POLLWRBAND },
+ { .fd = fds[0], .events = POLLIN | POLLPRI },
+ { .fd = fds[1], .events = POLLOUT },
+ { .fd = 2, .events = POLLOUT | POLLWRBAND }
+ };
+ struct pollfd *const tail_fds0 = tail_memdup(pfds0, sizeof(pfds0));
+ const int timeout = 42;
+ int rc = syscall(__NR_poll, tail_fds0, 0, timeout);
+ assert(rc == 0);
+
+ tprintf("poll(%p, 0, %d) = %d (Timeout)\n", tail_fds0, timeout, rc);
+
+ rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
+ assert(rc == 3);
+
+ tprintf("poll(");
+ print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
+ ARRAY_SIZE(pfds0), abbrev);
+ tprintf(", %u, %d) = %d (", ARRAY_SIZE(pfds0), timeout, rc);
+ print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
+ tprintf(")\n");
+
+ tail_fds0[0].fd = -1;
+ tail_fds0[2].fd = -3;
+ tail_fds0[4].events = 0;
+ rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
+ assert(rc == 2);
+
+ tprintf("poll(");
+ print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
+ ARRAY_SIZE(pfds0), abbrev);
+ tprintf(", %u, %d) = %d (", ARRAY_SIZE(pfds0), timeout, rc);
+ print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
+ tprintf(")\n");
+
+ tail_fds0[1].fd = -2;
+ tail_fds0[4].fd = -5;
+ rc = syscall(__NR_poll, tail_fds0, ARRAY_SIZE(pfds0), timeout);
+ assert(rc == 1);
+
+ tprintf("poll(");
+ print_pollfd_array_entering(tail_fds0, ARRAY_SIZE(pfds0),
+ ARRAY_SIZE(pfds0), abbrev);
+ tprintf(", %u, %d) = %d (", ARRAY_SIZE(pfds0), timeout, rc);
+ print_pollfd_array_exiting(tail_fds0, ARRAY_SIZE(pfds0), abbrev);
+ tprintf(")\n");
+
+ struct pollfd pfds1[] = {
+ { .fd = 1, .events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND },
+ { .fd = 0, .events = POLLOUT | POLLWRNORM | POLLWRBAND }
+ };
+ struct pollfd *const tail_fds1 = tail_memdup(pfds1, sizeof(pfds1));
+ rc = syscall(__NR_poll, tail_fds1, ARRAY_SIZE(pfds1), timeout);
+ assert(rc == 0);
+
+ tprintf("poll(");
+ print_pollfd_array_entering(tail_fds1, ARRAY_SIZE(pfds1),
+ ARRAY_SIZE(pfds1), abbrev);
+ tprintf(", %u, %d) = %d (Timeout)\n", ARRAY_SIZE(pfds1), timeout, rc);
+
+ const void *const efault = tail_fds0 + ARRAY_SIZE(pfds0);
+ rc = syscall(__NR_poll, efault, 1, 0);
+ assert(rc == -1);
+ tprintf("poll(%p, 1, 0) = -1 EFAULT (%m)\n", efault);
+
+ const unsigned int valid = 1;
+ const void *const epfds = tail_fds0 + ARRAY_SIZE(pfds0) - valid;
+ rc = syscall(__NR_poll, epfds, valid + 1, 0);
+ assert(rc == -1);
+ tprintf("poll(");
+ print_pollfd_array_entering(epfds, valid + 1, valid, abbrev);
+ errno = EFAULT;
+ tprintf(", %u, 0) = -1 EFAULT (%m)\n", valid + 1);
+
+ tprintf("+++ exited with 0 +++\n");
+ return 0;
+}
+
+#else
+
+SKIP_MAIN_UNDEFINED("__NR_poll")
+
+#endif
diff --git a/tests/poll.test b/tests/poll.test
new file mode 100755
index 0000000..869f709
--- /dev/null
+++ b/tests/poll.test
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Check poll syscall decoding.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+OUT="$LOG.out"
+run_strace -a18 -vepoll $args > "$OUT"
+match_diff "$LOG" "$OUT"
+
+for abbrev in 0 1 2 3 4 5; do
+ run_prog "./${ME_%.test}" $abbrev > /dev/null
+ run_strace -a18 -epoll -s$abbrev $args > "$OUT"
+ match_diff "$LOG" "$OUT"
+done
+
+rm -f "$OUT"