--- /dev/null 2017-04-13 16:57:43.000000000 +0100 +++ new/test/lib/testlibrary/jdk/testlibrary/NetworkConfiguration.java 2017-04-13 16:57:42.000000000 +0100 @@ -0,0 +1,267 @@ +/* + * 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.testlibrary; + +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.Optional; +import java.util.function.Predicate; +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 { + + static final boolean isWindows = + System.getProperty("os.name").startsWith("Windows"); + static final boolean isMacOS = + System.getProperty("os.name").contains("OS X"); + + 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 (isMacOS && nif.getName().contains("awdl")) + return false; + String dName = nif.getDisplayName(); + if (isWindows && dName != null && dName.contains("Teredo")) + return false; + return true; + } + + private final Predicate hasIp4Addresses = nif -> { + Optional addr = ip4Interfaces.get(nif).stream() + .filter(a -> !a.isAnyLocalAddress()) + .findAny(); + + return addr.isPresent(); + }; + + private final Predicate hasIp6Addresses = nif -> { + Optional addr = ip6Interfaces.get(nif).stream() + .filter(a -> !a.isAnyLocalAddress()) + .findAny(); + + return addr.isPresent(); + }; + + + /** + * 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; + + Optional addr = ip4Interfaces.get(nif).stream() + .filter(a -> !a.isAnyLocalAddress()) + .findAny(); + + return addr.isPresent(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }; + + private final Predicate supportsIp6Multicast = nif -> { + try { + if (!nif.supportsMulticast() || nif.isLoopback()) + return false; + + Optional addr = ip6Interfaces.get(nif).stream() + .filter(a -> !a.isAnyLocalAddress()) + .findAny(); + + return addr.isPresent(); + } 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(nif -> ip4Addresses(nif)); + } + + /** + * Returns all IPv6 addresses on all "functional" interfaces. + */ + public Stream ip6Addresses() { + return ip6Interfaces().flatMap(nif -> ip6Addresses(nif)); + } + + /** + * 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() { + StringBuilder sb = new StringBuilder(); + interfaces().forEach(nif -> sb.append(interfaceInformation(nif))); + return sb.toString(); + } + + /** Returns detailed information for the given interface. */ + public static String interfaceInformation(NetworkInterface nif) { + StringBuilder sb = new StringBuilder(); + try { + sb.append("Display name: " + nif.getDisplayName() + "\n"); + sb.append("Name: " + nif.getName() + "\n"); + for (InetAddress inetAddress : list(nif.getInetAddresses())) + sb.append("InetAddress: " + inetAddress + "\n"); + sb.append("Up? " + nif.isUp() + "\n"); + sb.append("Loopback? " + nif.isLoopback() + "\n"); + sb.append("PointToPoint? " + nif.isPointToPoint() + "\n"); + sb.append("Supports multicast? " + nif.supportsMulticast() + "\n"); + sb.append("Virtual? " + nif.isVirtual() + "\n"); + sb.append("Hardware address: " + + Arrays.toString(nif.getHardwareAddress()) + "\n"); + sb.append("MTU: " + nif.getMTU() + "\n"); + sb.append("Index: " + nif.getIndex() + "\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 ***"); + List nifs = list(getNetworkInterfaces()); + for (NetworkInterface nif : nifs) + out.print(interfaceInformation(nif)); + out.println("*** end ***"); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +}