--- /dev/null 2020-01-02 04:43:18.583999853 +0000 +++ new/test/lib/jdk/test/lib/NetworkConfiguration.java 2020-01-30 06:38:15.723599299 +0000 @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code 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 + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.test.lib; + +import java.io.PrintStream; +import java.io.UncheckedIOException; +import java.io.IOException; +import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static java.net.NetworkInterface.getNetworkInterfaces; +import static java.util.Collections.list; + +/** + * Helper class for retrieving network interfaces and local addresses + * suitable for testing. + */ +public class NetworkConfiguration { + + private Map> ip4Interfaces; + private Map> ip6Interfaces; + + private NetworkConfiguration( + Map> ip4Interfaces, + Map> ip6Interfaces) { + this.ip4Interfaces = ip4Interfaces; + this.ip6Interfaces = ip6Interfaces; + } + + /** + * Returns a stream of interfaces suitable for functional tests. + */ + public Stream interfaces() { + return Stream.concat(ip4Interfaces(), ip6Interfaces()) + .distinct(); + } + + /** + * Returns a stream of interfaces suitable for IPv4 functional tests. + */ + public Stream ip4Interfaces() { + return ip4Interfaces.keySet() + .stream() + .filter(NetworkConfiguration::isNotExcludedInterface) + .filter(hasIp4Addresses); + } + + /** + * Returns a stream of interfaces suitable for IPv6 functional tests. + */ + public Stream ip6Interfaces() { + return ip6Interfaces.keySet() + .stream() + .filter(NetworkConfiguration::isNotExcludedInterface) + .filter(hasIp6Addresses); + } + + private static boolean isNotExcludedInterface(NetworkInterface nif) { + if (Platform.isOSX() && nif.getName().contains("awdl")) { + return false; + } + String dName = nif.getDisplayName(); + if (Platform.isWindows() && dName != null && dName.contains("Teredo")) { + return false; + } + return true; + } + + private final Predicate hasIp4Addresses = nif -> + ip4Interfaces.get(nif).stream().anyMatch(a -> !a.isAnyLocalAddress()); + + private final Predicate hasIp6Addresses = nif -> + ip6Interfaces.get(nif).stream().anyMatch(a -> !a.isAnyLocalAddress()); + + + /** + * Returns a stream of interfaces suitable for IPv4 multicast tests. + */ + public Stream ip4MulticastInterfaces() { + return ip4Interfaces().filter(supportsIp4Multicast); + } + + /** + * Returns a stream of interfaces suitable for IPv6 multicast tests. + */ + public Stream ip6MulticastInterfaces() { + return ip6Interfaces().filter(supportsIp6Multicast); + } + + private final Predicate supportsIp4Multicast = nif -> { + try { + if (!nif.supportsMulticast() || nif.isLoopback()) { + return false; + } + return hasIp4Addresses.test(nif); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }; + + private final Predicate supportsIp6Multicast = nif -> { + try { + if (!nif.supportsMulticast() || nif.isLoopback()) { + return false; + } + + return hasIp6Addresses.test(nif); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }; + + /** + * Returns all addresses on all "functional" interfaces. + */ + public Stream addresses(NetworkInterface nif) { + return Stream.concat(ip4Interfaces.get(nif).stream(), + ip6Interfaces.get(nif).stream()); + } + + /** + * Returns all IPv4 addresses on all "functional" interfaces. + */ + public Stream ip4Addresses() { + return ip4Interfaces().flatMap(this::ip4Addresses); + } + + /** + * Returns all IPv6 addresses on all "functional" interfaces. + */ + public Stream ip6Addresses() { + return ip6Interfaces().flatMap(this::ip6Addresses); + } + + /** + * Returns all IPv4 addresses the given interface. + */ + public Stream ip4Addresses(NetworkInterface nif) { + return ip4Interfaces.get(nif).stream(); + } + + /** + * Returns all IPv6 addresses for the given interface. + */ + public Stream ip6Addresses(NetworkInterface nif) { + return ip6Interfaces.get(nif).stream(); + } + + /** + * Return a NetworkConfiguration instance. + */ + public static NetworkConfiguration probe() throws IOException { + Map> ip4Interfaces = new HashMap<>(); + Map> ip6Interfaces = new HashMap<>(); + + List nifs = list(getNetworkInterfaces()); + for (NetworkInterface nif : nifs) { + // ignore interfaces that are down + if (!nif.isUp() || nif.isPointToPoint()) { + continue; + } + + List ip4Addresses = new LinkedList<>(); + List ip6Addresses = new LinkedList<>(); + ip4Interfaces.put(nif, ip4Addresses); + ip6Interfaces.put(nif, ip6Addresses); + for (InetAddress addr : list(nif.getInetAddresses())) { + if (addr instanceof Inet4Address) { + ip4Addresses.add((Inet4Address) addr); + } else if (addr instanceof Inet6Address) { + ip6Addresses.add((Inet6Address) addr); + } + } + } + return new NetworkConfiguration(ip4Interfaces, ip6Interfaces); + } + + @Override + public String toString() { + return interfaces().map(NetworkConfiguration::interfaceInformation) + .collect(Collectors.joining()); + } + + /** Returns detailed information for the given interface. */ + public static String interfaceInformation(NetworkInterface nif) { + StringBuilder sb = new StringBuilder(); + try { + sb.append("Display name: ") + .append(nif.getDisplayName()) + .append("\n"); + sb.append("Name: ") + .append(nif.getName()) + .append("\n"); + for (InetAddress inetAddress : list(nif.getInetAddresses())) { + sb.append("InetAddress: ") + .append(inetAddress) + .append("\n"); + } + sb.append("Up? ") + .append(nif.isUp()) + .append("\n"); + sb.append("Loopback? ") + .append(nif.isLoopback()) + .append("\n"); + sb.append("PointToPoint? ") + .append(nif.isPointToPoint()) + .append("\n"); + sb.append("Supports multicast? ") + .append(nif.supportsMulticast()) + .append("\n"); + sb.append("Virtual? ") + .append(nif.isVirtual()) + .append("\n"); + sb.append("Hardware address: ") + .append(Arrays.toString(nif.getHardwareAddress())) + .append("\n"); + sb.append("MTU: ") + .append(nif.getMTU()) + .append("\n"); + sb.append("Index: ") + .append(nif.getIndex()) + .append("\n"); + sb.append("\n"); + return sb.toString(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** Prints all the system interface information to the give stream. */ + public static void printSystemConfiguration(PrintStream out) { + try { + out.println("*** all system network interface configuration ***"); + for (NetworkInterface nif : list(getNetworkInterfaces())) { + out.print(interfaceInformation(nif)); + } + out.println("*** end ***"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +}