From: Dmitry V. Levin Date: Tue, 2 Feb 2016 19:48:46 +0000 (+0000) Subject: tests: replace net-fd.test with net-y-unix.test X-Git-Tag: v4.12~604 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=751fcb8f8af7c4c76ea0339b8193edb17d612762;p=strace tests: replace net-fd.test with net-y-unix.test Unlike the former test that was based on match_grep, the new one uses match_diff and does more rigorous testing. * tests/net-y-unix.c: New file. * tests/net-y-unix.test: New test. * tests/net-fd.test: Remove. * tests/net-fd.expected: Remove. * tests/.gitignore: Add net-y-unix. * tests/Makefile.am (check_PROGRAMS): Likewise. (TESTS): Replace net-fd.test with net-y-unix.test. (net-fd.log): Remove. (EXTRA_DIST): Remove net-fd.expected. --- diff --git a/tests/.gitignore b/tests/.gitignore index ffd6356d..f6347c0b 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -57,6 +57,7 @@ mmsg mq nanosleep net-accept-connect +net-y-unix net-yy-inet net-yy-unix netlink_inet_diag diff --git a/tests/Makefile.am b/tests/Makefile.am index af8f7c96..667d8633 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -104,6 +104,7 @@ check_PROGRAMS = \ mq \ nanosleep \ net-accept-connect \ + net-y-unix \ net-yy-inet \ net-yy-unix \ netlink_inet_diag \ @@ -245,7 +246,7 @@ TESTS = \ mmsg.test \ mq.test \ nanosleep.test \ - net-fd.test \ + net-y-unix.test \ net-yy-inet.test \ net-yy-unix.test \ net.test \ @@ -317,8 +318,6 @@ XFAIL_TESTS_m32 = $(LIBUNWIND_TESTS) XFAIL_TESTS_mx32 = $(LIBUNWIND_TESTS) XFAIL_TESTS = $(XFAIL_TESTS_$(MPERS_NAME)) -net-fd.log: net.log - TEST_LOG_COMPILER = env AM_TEST_LOG_FLAGS = STRACE_ARCH=$(ARCH) $(srcdir)/run.sh @@ -342,7 +341,6 @@ EXTRA_DIST = init.sh run.sh match.awk \ memfd_create.expected \ mq.expected \ net.expected \ - net-fd.expected \ oldselect.expected \ pipe.expected \ ppoll.expected \ diff --git a/tests/net-fd.expected b/tests/net-fd.expected deleted file mode 100644 index 49b69924..00000000 --- a/tests/net-fd.expected +++ /dev/null @@ -1,5 +0,0 @@ -[1-9][0-9]* +[0-9]+:[0-9]+:[0-9]+\.[0-9]+ +bind\(0, \{sa_family=AF_(LOCAL|UNIX|FILE), sun_path="net-fd-local-stream"\}, 22\) += 0 -[1-9][0-9]* +[0-9]+:[0-9]+:[0-9]+\.[0-9]+ +listen\(0, 5\) += 0 -[1-9][0-9]* +[0-9]+:[0-9]+:[0-9]+\.[0-9]+ +getsockname\(0, \{sa_family=AF_(LOCAL|UNIX|FILE), sun_path="net-fd-local-stream"\}, \[22\]\) += 0 -[1-9][0-9]* +[0-9]+:[0-9]+:[0-9]+\.[0-9]+ +accept\(0, \{sa_family=AF_(LOCAL|UNIX|FILE), NULL\}, \[2\]\) += 1 -[1-9][0-9]* +[0-9]+:[0-9]+:[0-9]+\.[0-9]+ +connect\(1, \{sa_family=AF_(LOCAL|UNIX|FILE), sun_path="net-fd-local-stream"\}, 22\) += 0 diff --git a/tests/net-fd.test b/tests/net-fd.test deleted file mode 100755 index ddef8fc7..00000000 --- a/tests/net-fd.test +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -# Check how network syscalls are traced when decoding socket descriptors - -. "${srcdir=.}/init.sh" - -# strace -y is implemented using /proc/self/fd -[ -d /proc/self/fd/ ] || - framework_skip_ '/proc/self/fd/ is not available' - -run_prog ./net-accept-connect net-fd-local-stream -# using -y to test socket descriptors 'paths' decoding -run_strace_merge -y -enetwork $args -match_grep - -exit 0 diff --git a/tests/net-y-unix.c b/tests/net-y-unix.c new file mode 100644 index 00000000..421f502c --- /dev/null +++ b/tests/net-y-unix.c @@ -0,0 +1,230 @@ +/* + * This file is part of net-y-unix strace test. + * + * Copyright (c) 2013-2016 Dmitry V. Levin + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(int ac, const char **av) +{ + assert(ac == 2); + + struct sockaddr_un addr = { .sun_family = AF_UNIX }; + unsigned int sun_path_len = strlen(av[1]); + assert(sun_path_len > 0 && sun_path_len <= sizeof(addr.sun_path)); + strncpy(addr.sun_path, av[1], sizeof(addr.sun_path)); + struct sockaddr * const listen_sa = tail_memdup(&addr, sizeof(addr)); + + socklen_t * const len = tail_alloc(sizeof(socklen_t)); + *len = offsetof(struct sockaddr_un, sun_path) + strlen(av[1]) + 1; + if (*len > sizeof(addr)) + *len = sizeof(addr); + + int listen_fd = socket(PF_LOCAL, SOCK_STREAM, 0); + if (listen_fd < 0) + perror_msg_and_skip("socket"); + unsigned long listen_inode = inode_of_sockfd(listen_fd); + printf("socket(PF_LOCAL, SOCK_STREAM, 0) = %d\n", + listen_fd, listen_inode); + + (void) unlink(av[1]); + if (bind(listen_fd, listen_sa, *len)) + perror_msg_and_skip("bind"); + printf("bind(%d, {sa_family=AF_LOCAL, sun_path=\"%s\"}" + ", %u) = 0\n", listen_fd, listen_inode, av[1], (unsigned) *len); + + if (listen(listen_fd, 1)) + perror_msg_and_skip("listen"); + printf("listen(%d, 1) = 0\n", listen_fd, listen_inode); + + unsigned int * const optval = tail_alloc(sizeof(unsigned int)); + *len = sizeof(*optval); + if (getsockopt(listen_fd, SOL_SOCKET, SO_PASSCRED, optval, len)) + perror_msg_and_fail("getsockopt"); + printf("getsockopt(%d, SOL_SOCKET, SO_PASSCRED" + ", [%u], [%u]) = 0\n", + listen_fd, listen_inode, *optval, (unsigned) *len); + + memset(listen_sa, 0, sizeof(addr)); + *len = sizeof(addr); + if (getsockname(listen_fd, listen_sa, len)) + perror_msg_and_fail("getsockname"); + printf("getsockname(%d, {sa_family=AF_LOCAL" + ", sun_path=\"%s\"}, [%u]) = 0\n", listen_fd, listen_inode, + av[1], (unsigned) *len); + + int connect_fd = socket(PF_LOCAL, SOCK_STREAM, 0); + if (connect_fd < 0) + perror_msg_and_fail("socket"); + unsigned long connect_inode = inode_of_sockfd(connect_fd); + printf("socket(PF_LOCAL, SOCK_STREAM, 0) = %d\n", + connect_fd, connect_inode); + + if (connect(connect_fd, listen_sa, *len)) + perror_msg_and_fail("connect"); + printf("connect(%d, {sa_family=AF_LOCAL" + ", sun_path=\"%s\"}, %u) = 0\n", + connect_fd, connect_inode, av[1], (unsigned) *len); + + struct sockaddr * const accept_sa = tail_alloc(sizeof(addr)); + memset(accept_sa, 0, sizeof(addr)); + *len = sizeof(addr); + int accept_fd = accept(listen_fd, accept_sa, len); + if (accept_fd < 0) + perror_msg_and_fail("accept"); + unsigned long accept_inode = inode_of_sockfd(accept_fd); + printf("accept(%d, {sa_family=AF_LOCAL, NULL}" + ", [%u]) = %d\n", + listen_fd, listen_inode, (unsigned) *len, + accept_fd, accept_inode); + + memset(listen_sa, 0, sizeof(addr)); + *len = sizeof(addr); + if (getpeername(connect_fd, listen_sa, len)) + perror_msg_and_fail("getpeername"); + printf("getpeername(%d, {sa_family=AF_LOCAL" + ", sun_path=\"%s\"}, [%u]) = 0\n", connect_fd, connect_inode, + av[1], (unsigned) *len); + + char text[] = "text"; + assert(sendto(connect_fd, text, sizeof(text) - 1, MSG_DONTWAIT, NULL, 0) + == sizeof(text) - 1); + printf("sendto(%d, \"%s\", %u, MSG_DONTWAIT" + ", NULL, 0) = %u\n", + connect_fd, connect_inode, text, + (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1); + + assert(close(connect_fd) == 0); + printf("close(%d) = 0\n", connect_fd, connect_inode); + + assert(recvfrom(accept_fd, text, sizeof(text) - 1, MSG_DONTWAIT, NULL, NULL) + == sizeof(text) - 1); + printf("recvfrom(%d, \"%s\", %u, MSG_DONTWAIT" + ", NULL, NULL) = %u\n", + accept_fd, accept_inode, text, + (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1); + + assert(close(accept_fd) == 0); + printf("close(%d) = 0\n", accept_fd, accept_inode); + + connect_fd = socket(PF_LOCAL, SOCK_STREAM, 0); + if (connect_fd < 0) + perror_msg_and_fail("socket"); + connect_inode = inode_of_sockfd(connect_fd); + printf("socket(PF_LOCAL, SOCK_STREAM, 0) = %d\n", + connect_fd, connect_inode); + + *optval = 1; + *len = sizeof(*optval); + if (setsockopt(connect_fd, SOL_SOCKET, SO_PASSCRED, optval, *len)) + perror_msg_and_fail("setsockopt"); + printf("setsockopt(%d, SOL_SOCKET, SO_PASSCRED" + ", [%u], %u) = 0\n", + connect_fd, connect_inode, *optval, (unsigned) *len); + + memset(listen_sa, 0, sizeof(addr)); + *len = sizeof(addr); + if (getsockname(listen_fd, listen_sa, len)) + perror_msg_and_fail("getsockname"); + printf("getsockname(%d, {sa_family=AF_LOCAL" + ", sun_path=\"%s\"}, [%u]) = 0\n", + listen_fd, listen_inode, av[1], (unsigned) *len); + + if (connect(connect_fd, listen_sa, *len)) + perror_msg_and_fail("connect"); + printf("connect(%d, {sa_family=AF_LOCAL" + ", sun_path=\"%s\"}, %u) = 0\n", + connect_fd, connect_inode, av[1], (unsigned) *len); + + memset(accept_sa, 0, sizeof(addr)); + *len = sizeof(addr); + accept_fd = accept(listen_fd, accept_sa, len); + if (accept_fd < 0) + perror_msg_and_fail("accept"); + accept_inode = inode_of_sockfd(accept_fd); + const char * const sun_path1 = + ((struct sockaddr_un *) accept_sa) -> sun_path + 1; + printf("accept(%d, {sa_family=AF_LOCAL" + ", sun_path=@\"%s\"}, [%u]) = %d\n", + listen_fd, listen_inode, sun_path1, (unsigned) *len, + accept_fd, accept_inode); + + memset(listen_sa, 0, sizeof(addr)); + *len = sizeof(addr); + if (getpeername(connect_fd, listen_sa, len)) + perror_msg_and_fail("getpeername"); + printf("getpeername(%d, {sa_family=AF_LOCAL" + ", sun_path=\"%s\"}, [%u]) = 0\n", + connect_fd, connect_inode, av[1], (unsigned) *len); + + memset(accept_sa, 0, sizeof(addr)); + *len = sizeof(addr); + if (getsockname(connect_fd, accept_sa, len)) + perror_msg_and_fail("getsockname"); + printf("getsockname(%d, {sa_family=AF_LOCAL" + ", sun_path=@\"%s\"}, [%u]) = 0\n", + connect_fd, connect_inode, sun_path1, (unsigned) *len); + + assert(sendto(connect_fd, text, sizeof(text) - 1, MSG_DONTWAIT, NULL, 0) + == sizeof(text) - 1); + printf("sendto(%d, \"%s\", %u, MSG_DONTWAIT" + ", NULL, 0) = %u\n", + connect_fd, connect_inode, text, + (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1); + + assert(close(connect_fd) == 0); + printf("close(%d) = 0\n", connect_fd, connect_inode); + + assert(recvfrom(accept_fd, text, sizeof(text) - 1, MSG_DONTWAIT, NULL, NULL) + == sizeof(text) - 1); + printf("recvfrom(%d, \"%s\", %u, MSG_DONTWAIT" + ", NULL, NULL) = %u\n", + accept_fd, accept_inode, text, + (unsigned) sizeof(text) - 1, (unsigned) sizeof(text) - 1); + + assert(close(accept_fd) == 0); + printf("close(%d) = 0\n", accept_fd, accept_inode); + + assert(unlink(av[1]) == 0); + + assert(close(listen_fd) == 0); + printf("close(%d) = 0\n", + listen_fd, listen_inode); + + puts("+++ exited with 0 +++"); + return 0; +} diff --git a/tests/net-y-unix.test b/tests/net-y-unix.test new file mode 100755 index 00000000..90761589 --- /dev/null +++ b/tests/net-y-unix.test @@ -0,0 +1,48 @@ +#!/bin/sh +# +# Check decoding of network syscalls in -y mode. +# +# Copyright (c) 2016 Dmitry V. Levin +# 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. + +. "${srcdir=.}/init.sh" + +# strace -y is implemented using /proc/self/fd +[ -d /proc/self/fd/ ] || + framework_skip_ '/proc/self/fd/ is not available' + +check_prog sed + +addr="${ME_%.test}-local-stream" +run_prog "./${ME_%.test}" $addr > /dev/null + +OUT="$LOG.out" +EXP="$LOG.exp" +run_strace -a20 -y -eclose,network $args > "$EXP" +# Filter out close() calls made by ld.so and libc. +sed -n '/socket/,$p' < "$LOG" > "$OUT" + +match_diff "$OUT" "$EXP" +rm -f "$EXP" "$OUT"