]> granicus.if.org Git - strace/commitdiff
tests: add a test for -yy option
authorDmitry V. Levin <ldv@altlinux.org>
Tue, 23 Sep 2014 00:14:04 +0000 (00:14 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Tue, 23 Sep 2014 01:42:07 +0000 (01:42 +0000)
* tests/net-yy.test: New test.
* tests/inet-accept-connect-send-recv.c: New file.
* tests/netlink_inet_diag.c: Likewise.
* tests/net-yy-accept.awk: Likewise.
* tests/net-yy-connect.awk: Likewise.
* tests/.gitignore: Add inet-accept-connect-send-recv,
netlink_inet_diag, *.tmp-*, and *.tmp.*.
* tests/Makefile.am (check_PROGRAMS): Add inet-accept-connect-send-recv
and netlink_inet_diag.
(TESTS): Add net-yy.test.
(EXTRA_DIST): Add net-yy-accept.awk and net-yy-connect.awk.

tests/.gitignore
tests/Makefile.am
tests/inet-accept-connect-send-recv.c [new file with mode: 0644]
tests/net-yy-accept.awk [new file with mode: 0644]
tests/net-yy-connect.awk [new file with mode: 0644]
tests/net-yy.test [new file with mode: 0755]
tests/netlink_inet_diag.c [new file with mode: 0644]

index cf7aaf0d4ac480693651b252450cc410a646ac7f..dc408c9aa0bb8ddcae41526d7c92b51feb63b990 100644 (file)
@@ -1,4 +1,6 @@
+inet-accept-connect-send-recv
 net-accept-connect
+netlink_inet_diag
 scm_rights
 set_ptracer_any
 sigaction
@@ -8,5 +10,7 @@ uio
 *.log
 *.log.*
 *.o
-*.trs
 *.tmp
+*.tmp-*
+*.tmp.*
+*.trs
index 3b97b2cd5a667b2c2e4d3d576cf8d794b817ff00..541a0c4669853558280fbdd3018d378bfbd34de8 100644 (file)
@@ -3,7 +3,9 @@
 AM_CFLAGS = $(WARN_CFLAGS)
 
 check_PROGRAMS = \
+       inet-accept-connect-send-recv \
        net-accept-connect \
+       netlink_inet_diag \
        scm_rights \
        set_ptracer_any \
        sigaction \
@@ -27,6 +29,7 @@ TESTS = \
        statfs.test \
        net.test \
        net-fd.test \
+       net-yy.test \
        uio.test \
        count.test \
        detach-sleeping.test \
@@ -38,6 +41,11 @@ net-fd.log: net.log
 
 TEST_LOG_COMPILER = $(srcdir)/run.sh
 
-EXTRA_DIST = init.sh run.sh getdents.awk sigaction.awk $(TESTS)
+EXTRA_DIST = init.sh run.sh \
+            getdents.awk \
+            net-yy-accept.awk \
+            net-yy-connect.awk \
+            sigaction.awk \
+            $(TESTS)
 
 CLEANFILES = $(TESTS:=.tmp)
diff --git a/tests/inet-accept-connect-send-recv.c b/tests/inet-accept-connect-send-recv.c
new file mode 100644 (file)
index 0000000..38376ae
--- /dev/null
@@ -0,0 +1,53 @@
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+int main(void)
+{
+       static const char data[] = "data";
+       const size_t size = sizeof(data) - 1;
+       struct sockaddr_in addr;
+       socklen_t len = sizeof(addr);
+       pid_t pid;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+       close(0);
+       close(1);
+
+       assert(socket(PF_INET, SOCK_STREAM, 0) == 0);
+       assert(bind(0, (struct sockaddr *) &addr, len) == 0);
+       assert(listen(0, 5) == 0);
+
+       memset(&addr, 0, sizeof(addr));
+       assert(getsockname(0, (struct sockaddr *) &addr, &len) == 0);
+
+       assert((pid = fork()) >= 0);
+
+       if (pid) {
+               char buf[sizeof(data)];
+               int status;
+
+               assert(accept(0, (struct sockaddr *) &addr, &len) == 1);
+               assert(close(0) == 0);
+               assert(recv(1, buf, sizeof(buf), MSG_WAITALL) == (int) size);
+               assert(waitpid(pid, &status, 0) == pid);
+               assert(status == 0);
+               assert(close(1) == 0);
+       } else {
+               assert(close(0) == 0);
+               assert(socket(PF_INET, SOCK_STREAM, 0) == 0);
+               assert(connect(0, (struct sockaddr *) &addr, len) == 0);
+               assert(send(0, data, size, MSG_DONTROUTE) == (int) size);
+               assert(close(0) == 0);
+       }
+
+       return 0;
+}
diff --git a/tests/net-yy-accept.awk b/tests/net-yy-accept.awk
new file mode 100644 (file)
index 0000000..3ea4afe
--- /dev/null
@@ -0,0 +1,76 @@
+BEGIN {
+  lines = 9
+  fail = 0
+
+  inode = "?"
+  port_l = "?"
+  port_r = "?"
+
+  r_i = "[1-9][0-9]*"
+  r_port = "[1-9][0-9][0-9][0-9]+"
+  r_localhost = "127\\.0\\.0\\.1"
+  r_bind = "^bind\\(0<socket:\\[(" r_i ")\\]>, {sa_family=AF_INET, sin_port=htons\\(0\\), sin_addr=inet_addr\\(\"" r_localhost "\"\\)}, " r_i "\\) += 0$"
+  r_listen = "^/$"
+  r_getsockname = "^getsockname\\(0<" r_localhost ":(" r_port ")>, {sa_family=AF_INET, sin_port=htons\\((" r_port ")\\), sin_addr=inet_addr\\(\"" r_localhost "\"\\)}, \\[" r_i "\\]\\) += 0$"
+  r_accept = "^/$"
+  r_close0 = "^/$"
+  r_recv = "^/$"
+  r_recvfrom = "^/$"
+  r_close1 = "^/$"
+}
+
+NR == 1 && /^socket\(PF_INET, SOCK_STREAM, IPPROTO_IP\) += 0$/ {next}
+
+NR == 2 {
+  if (match($0, r_bind, a)) {
+    inode = a[1]
+    r_listen = "^listen\\(0<socket:\\[" inode "\\]>, 5\\) += 0$"
+    next
+  }
+}
+
+NR == 3 {if (match($0, r_listen)) next}
+
+NR == 4 {
+  if (match($0, r_getsockname, a) && a[1] == a[2]) {
+    port_l = a[1]
+    r_accept = "^accept\\(0<" r_localhost ":" port_l ">, {sa_family=AF_INET, sin_port=htons\\((" r_port ")\\), sin_addr=inet_addr\\(\"" r_localhost "\"\\)}, \\[" r_i "\\]\\) += 1<" r_localhost ":" port_l "->" r_localhost ":(" r_port ")>$"
+    r_close0 = "^close\\(0<" r_localhost ":" port_l ">) += 0$"
+    next
+  }
+}
+
+NR == 5 {
+  if (match($0, r_accept, a) && a[1] == a[2]) {
+    port_r = a[1]
+    r_recv = "^recv\\(1<" r_localhost ":" port_l "->" r_localhost ":" port_r ">, \"data\", 5, MSG_WAITALL\\) += 4$"
+    r_recvfrom = "^recvfrom\\(1<" r_localhost ":" port_l "->" r_localhost ":" port_r ">, \"data\", 5, MSG_WAITALL, NULL, NULL\\) += 4$"
+    r_close1 = "^close\\(1<" r_localhost ":" port_l "->" r_localhost ":" port_r ">) += 0$"
+    next
+  }
+}
+
+NR == 6 {if (match($0, r_close0)) next}
+
+NR == 7 {if (match($0, r_recv) || match($0, r_recvfrom)) next}
+
+NR == 8 {if (match($0, r_close1)) next}
+
+NR == lines && /^\+\+\+ exited with 0 \+\+\+$/ {next}
+
+{
+  print "Line " NR " does not match: " $0
+  fail=1
+}
+
+END {
+  if (NR != lines) {
+    print "Expected " lines " lines, found " NR " line(s)."
+    print ""
+    exit 1
+  }
+  if (fail) {
+    print ""
+    exit 1
+  }
+}
diff --git a/tests/net-yy-connect.awk b/tests/net-yy-connect.awk
new file mode 100644 (file)
index 0000000..18c1a28
--- /dev/null
@@ -0,0 +1,55 @@
+BEGIN {
+  lines = 5
+  fail = 0
+
+  port_l = "?"
+  port_r = "?"
+
+  r_i = "[1-9][0-9]*"
+  r_port = "[1-9][0-9][0-9][0-9]+"
+  r_localhost = "127\\.0\\.0\\.1"
+  r_connect = "^connect\\(0<socket:\\[" r_i "\\]>, {sa_family=AF_INET, sin_port=htons\\((" r_port ")\\), sin_addr=inet_addr\\(\"" r_localhost "\"\\)}, " r_i ") += 0$"
+  r_send = "^/$"
+  r_sendto = "^/$"
+  r_close = "^/$"
+}
+
+NR == 1 && /^socket\(PF_INET, SOCK_STREAM, IPPROTO_IP\) += 0$/ {next}
+
+NR == 2 {
+  if (match($0, r_connect, a)) {
+    port_r = a[1]
+    r_send = "^send\\(0<" r_localhost ":(" r_port ")->" r_localhost ":" port_r ">, \"data\", 4, MSG_DONTROUTE\\) += 4$"
+    r_sendto = "^sendto\\(0<" r_localhost ":(" r_port ")->" r_localhost ":" port_r ">, \"data\", 4, MSG_DONTROUTE, NULL, 0\\) += 4$"
+    next
+  }
+}
+
+NR == 3 {
+  if (match($0, r_send, a) || match($0, r_sendto, a)) {
+    port_l = a[1]
+    r_close = "^close\\(0<" r_localhost ":" port_l "->" r_localhost ":" port_r ">\\) += 0$"
+    next
+  }
+}
+
+NR == 4 {if (match($0, r_close)) next}
+
+NR == lines && /^\+\+\+ exited with 0 \+\+\+$/ {next}
+
+{
+  print "Line " NR " does not match: " $0
+  fail=1
+}
+
+END {
+  if (NR != lines) {
+    print "Expected " lines " lines, found " NR " line(s)."
+    print ""
+    exit 1
+  }
+  if (fail) {
+    print ""
+    exit 1
+  }
+}
diff --git a/tests/net-yy.test b/tests/net-yy.test
new file mode 100755 (executable)
index 0000000..8b6c098
--- /dev/null
@@ -0,0 +1,59 @@
+#!/bin/sh
+
+# Check decoding of ip:port pairs associated with socket descriptors
+
+. "${srcdir=.}/init.sh"
+
+# strace -yy is implemented using /proc/self/fd
+[ -d /proc/self/fd/ ] ||
+       framework_skip_ '/proc/self/fd/ is not available'
+
+check_prog sed
+check_prog awk
+
+rm -f $LOG.* $LOG-*
+
+./inet-accept-connect-send-recv ||
+       fail_ 'inet-accept-connect-send-recv failed'
+
+./netlink_inet_diag || {
+       if [ $? -eq 77 ]; then
+               framework_skip_ 'NETLINK_INET_DIAG is not available'
+       else
+               fail_ 'netlink_inet_diag failed'
+       fi
+}
+
+args="-tt -ff -yy -o $LOG -eclose,network ./inet-accept-connect-send-recv"
+$STRACE $args ||
+       fail_ "strace $args failed"
+
+"$srcdir"/../strace-log-merge $LOG > $LOG || {
+       cat $LOG
+       fail_ 'strace-log-merge failed'
+}
+rm -f $LOG.*
+
+child="$(sed -rn '/SIGCHLD/ s/^.*, si_pid=([1-9][0-9]*), .*/\1/p' $LOG)"
+[ -n "$child" ] || {
+       cat $LOG
+       fail_ 'failed to find pid of child process'
+}
+
+sed -rn "/^$child"' /!d; / socket\(/,$ s/^[0-9]+ +[^ ]+ (.+)/\1/p' $LOG > $LOG-connect &&
+sed -rn "/^$child"' /d; /SIGCHLD/d; / socket\(/,$ s/^[0-9]+ +[^ ]+ (.+)/\1/p' $LOG > $LOG-accept || {
+       cat $LOG
+       fail_ 'failed to separate logs'
+}
+
+awk -f "$srcdir"/net-yy-connect.awk $LOG-connect || {
+       cat $LOG-connect
+       fail_ "strace $args failed to decode socket descriptors properly"
+}
+
+awk -f "$srcdir"/net-yy-accept.awk $LOG-accept || {
+       cat $LOG-accept
+       fail_ "strace $args failed to decode socket descriptors properly"
+}
+
+exit 0
diff --git a/tests/netlink_inet_diag.c b/tests/netlink_inet_diag.c
new file mode 100644 (file)
index 0000000..ffd3591
--- /dev/null
@@ -0,0 +1,96 @@
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <linux/netlink.h>
+#include <linux/sock_diag.h>
+#include <linux/inet_diag.h>
+
+static int
+send_query(const int fd, const int family, const int proto)
+{
+       struct sockaddr_nl nladdr;
+       struct {
+               struct nlmsghdr nlh;
+               struct inet_diag_req_v2 idr;
+       } req;
+       struct iovec iov = {
+               .iov_base = &req,
+               .iov_len = sizeof(req)
+       };
+       struct msghdr msg = {
+               .msg_name = (void*)&nladdr,
+               .msg_namelen = sizeof(nladdr),
+               .msg_iov = &iov,
+               .msg_iovlen = 1
+       };
+
+       memset(&nladdr, 0, sizeof(nladdr));
+       nladdr.nl_family = AF_NETLINK;
+
+       memset(&req, 0, sizeof(req));
+       req.nlh.nlmsg_len = sizeof(req);
+       req.nlh.nlmsg_type = SOCK_DIAG_BY_FAMILY;
+       req.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+       req.idr.sdiag_family = family;
+       req.idr.sdiag_protocol = proto;
+       req.idr.idiag_states = -1;
+
+       return sendmsg(fd, &msg, 0) > 0;
+}
+
+static int
+check_responses(const int fd)
+{
+       static char buf[8192];
+       struct sockaddr_nl nladdr;
+       struct iovec iov = {
+               .iov_base = buf,
+               .iov_len = sizeof(buf)
+       };
+
+       memset(&nladdr, 0, sizeof(nladdr));
+       nladdr.nl_family = AF_NETLINK;
+
+       struct msghdr msg = {
+               .msg_name = (void*)&nladdr,
+               .msg_namelen = sizeof(nladdr),
+               .msg_iov = &iov,
+               .msg_iovlen = 1,
+               .msg_control = NULL,
+               .msg_controllen = 0,
+               .msg_flags = 0
+       };
+
+       ssize_t ret = recvmsg(fd, &msg, 0);
+       if (ret <= 0)
+               return 0;
+
+       struct nlmsghdr *h = (struct nlmsghdr*)buf;
+       return (NLMSG_OK(h, ret) &&
+               h->nlmsg_type != NLMSG_ERROR &&
+               h->nlmsg_type != NLMSG_DONE) ? 1 : 0;
+}
+
+int main(void)
+{
+       struct sockaddr_in addr;
+       socklen_t len = sizeof(addr);
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin_family = AF_INET;
+       addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+       close(0);
+       close(1);
+
+       assert(socket(PF_INET, SOCK_STREAM, 0) == 0);
+       assert(bind(0, (struct sockaddr *) &addr, len) == 0);
+       assert(listen(0, 5) == 0);
+
+       if (socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG) != 1)
+               return 77;
+
+       return (send_query(1, AF_INET, IPPROTO_TCP) &&
+               check_responses(1)) ? 0 : 77;
+}