diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/core/echo/echo_test.c | 64 | ||||
-rw-r--r-- | test/core/end2end/dualstack_socket_test.c | 21 | ||||
-rw-r--r-- | test/core/util/ipv6.c | 55 | ||||
-rw-r--r-- | test/core/util/ipv6.h | 41 |
4 files changed, 153 insertions, 28 deletions
diff --git a/test/core/echo/echo_test.c b/test/core/echo/echo_test.c index bbce9da846..cc265cadbf 100644 --- a/test/core/echo/echo_test.c +++ b/test/core/echo/echo_test.c @@ -42,12 +42,33 @@ #include <grpc/support/alloc.h> #include <grpc/support/host_port.h> +#include <grpc/support/log.h> #include <grpc/support/string.h> +#include "test/core/util/ipv6.h" #include "test/core/util/port.h" -static const char *const kHosts[] = { - "127.0.0.1", "::1", "::ffff:127.0.0.1", "localhost", -}; +int test_client(const char *root, const char *host, int port) { + char *args[3]; + int status; + pid_t cli; + cli = fork(); + if (cli == 0) { + gpr_asprintf(&args[0], "%s/echo_client", root); + gpr_join_host_port(&args[1], host, port); + args[2] = 0; + execv(args[0], args); + + gpr_free(args[0]); + gpr_free(args[1]); + return 1; + } + /* wait for client */ + gpr_log(GPR_INFO, "Waiting for client: %s", host); + if (waitpid(cli, &status, 0) == -1) return 2; + if (!WIFEXITED(status)) return 4; + if (WEXITSTATUS(status)) return WEXITSTATUS(status); + return 0; +} int main(int argc, char **argv) { char *me = argv[0]; @@ -56,8 +77,13 @@ int main(int argc, char **argv) { int port = grpc_pick_unused_port_or_die(); char *args[3]; int status; - pid_t svr, cli; - int i; + pid_t svr; + int ret; + int do_ipv6 = 1; + if (!grpc_ipv6_loopback_available()) { + gpr_log(GPR_INFO, "Can't bind to ::1. Skipping IPv6 tests."); + do_ipv6 = 0; + } /* figure out where we are */ if (lslash) { memcpy(root, me, lslash - me); @@ -80,26 +106,18 @@ int main(int argc, char **argv) { /* wait a little */ sleep(2); /* start the clients */ - for (i = 0; i < sizeof(kHosts) / sizeof(*kHosts); i++) { - cli = fork(); - if (cli == 0) { - gpr_asprintf(&args[0], "%s/echo_client", root); - gpr_join_host_port(&args[1], kHosts[i], port); - args[2] = 0; - execv(args[0], args); - - gpr_free(args[0]); - gpr_free(args[1]); - return 1; - } - /* wait for client */ - printf("waiting for client: %s\n", kHosts[i]); - if (waitpid(cli, &status, 0) == -1) return 2; - if (!WIFEXITED(status)) return 4; - if (WEXITSTATUS(status)) return WEXITSTATUS(status); + ret = test_client(root, "127.0.0.1", port); + if (ret != 0) return ret; + ret = test_client(root, "::ffff:127.0.0.1", port); + if (ret != 0) return ret; + ret = test_client(root, "localhost", port); + if (ret != 0) return ret; + if (do_ipv6) { + ret = test_client(root, "::1", port); + if (ret != 0) return ret; } /* wait for server */ - printf("waiting for server\n"); + gpr_log(GPR_INFO, "Waiting for server"); kill(svr, SIGINT); if (waitpid(svr, &status, 0) == -1) return 2; if (!WIFEXITED(status)) return 4; diff --git a/test/core/end2end/dualstack_socket_test.c b/test/core/end2end/dualstack_socket_test.c index e127c61b25..f2dcc80afe 100644 --- a/test/core/end2end/dualstack_socket_test.c +++ b/test/core/end2end/dualstack_socket_test.c @@ -37,6 +37,7 @@ #include <grpc/support/host_port.h> #include <grpc/support/log.h> #include "test/core/end2end/cq_verifier.h" +#include "test/core/util/ipv6.h" #include "test/core/util/port.h" #include "test/core/util/test_config.h" @@ -168,31 +169,41 @@ void test_connect(const char *server_host, const char *client_host, int port, } int main(int argc, char **argv) { + int do_ipv6 = 1; int i; grpc_test_init(argc, argv); grpc_init(); + if (!grpc_ipv6_loopback_available()) { + gpr_log(GPR_INFO, "Can't bind to ::1. Skipping IPv6 tests."); + do_ipv6 = 0; + } + for (i = 0; i <= 1; i++) { /* For coverage, test with and without dualstack sockets. */ grpc_forbid_dualstack_sockets_for_testing = i; /* :: and 0.0.0.0 are handled identically. */ test_connect("::", "127.0.0.1", grpc_pick_unused_port_or_die(), 1); - test_connect("::", "::1", grpc_pick_unused_port_or_die(), 1); test_connect("::", "::ffff:127.0.0.1", grpc_pick_unused_port_or_die(), 1); test_connect("::", "localhost", grpc_pick_unused_port_or_die(), 1); test_connect("0.0.0.0", "127.0.0.1", grpc_pick_unused_port_or_die(), 1); - test_connect("0.0.0.0", "::1", grpc_pick_unused_port_or_die(), 1); test_connect("0.0.0.0", "::ffff:127.0.0.1", grpc_pick_unused_port_or_die(), 1); test_connect("0.0.0.0", "localhost", grpc_pick_unused_port_or_die(), 1); + if (do_ipv6) { + test_connect("::", "::1", grpc_pick_unused_port_or_die(), 1); + test_connect("0.0.0.0", "::1", grpc_pick_unused_port_or_die(), 1); + } /* These only work when the families agree. */ - test_connect("::1", "::1", grpc_pick_unused_port_or_die(), 1); - test_connect("::1", "127.0.0.1", grpc_pick_unused_port_or_die(), 0); test_connect("127.0.0.1", "127.0.0.1", grpc_pick_unused_port_or_die(), 1); - test_connect("127.0.0.1", "::1", grpc_pick_unused_port_or_die(), 0); + if (do_ipv6) { + test_connect("::1", "::1", grpc_pick_unused_port_or_die(), 1); + test_connect("::1", "127.0.0.1", grpc_pick_unused_port_or_die(), 0); + test_connect("127.0.0.1", "::1", grpc_pick_unused_port_or_die(), 0); + } } diff --git a/test/core/util/ipv6.c b/test/core/util/ipv6.c new file mode 100644 index 0000000000..80f6a0ec91 --- /dev/null +++ b/test/core/util/ipv6.c @@ -0,0 +1,55 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 COPYRIGHT + * OWNER OR CONTRIBUTORS 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 "test/core/util/ipv6.h" + +#include <netinet/in.h> +#include <string.h> +#include <sys/socket.h> +#include <unistd.h> + +int grpc_ipv6_loopback_available() { + int ok = 0; + int fd = socket(AF_INET6, SOCK_STREAM, 0); + if (fd >= 0) { + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */ + if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + ok = 1; + } + close(fd); + } + return ok; +} diff --git a/test/core/util/ipv6.h b/test/core/util/ipv6.h new file mode 100644 index 0000000000..bb536645b8 --- /dev/null +++ b/test/core/util/ipv6.h @@ -0,0 +1,41 @@ +/* + * + * Copyright 2014, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 COPYRIGHT + * OWNER OR CONTRIBUTORS 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. + * + */ + +#ifndef __GRPC_TEST_UTIL_IPV6_H__ +#define __GRPC_TEST_UTIL_IPV6_H__ + +/* Returns true if we're able to create an AF_INET6 socket bound to ::1 on an + arbitrary port. */ +int grpc_ipv6_loopback_available(); + +#endif /* __GRPC_TEST_UTIL_IPV6_H__ */ |