1 /*
2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /**
25  * @test
26  * @bug 8016521
27  * @library /test/lib
28  * @summary InetAddress should not always re-order addresses returned from name
29  *          service
30  * @run main/othervm -Djava.net.preferIPv6Addresses=false PreferIPv6AddressesTest
31  * @run main/othervm -Djava.net.preferIPv6Addresses=true PreferIPv6AddressesTest
32  * @run main/othervm -Djava.net.preferIPv6Addresses=system PreferIPv6AddressesTest
33  * @run main/othervm PreferIPv6AddressesTest
34  */
35 
36 import java.io.IOException;
37 import java.net.*;
38 import java.nio.channels.DatagramChannel;
39 import java.util.Arrays;
40 import java.util.stream.IntStream;
41 import static java.lang.System.out;
42 import jdk.test.lib.net.IPSupport;
43 
44 public class PreferIPv6AddressesTest {
45 
46     // A name, that if resolves, returns both IPv4 and IPv6 addresses.
47     static final String HOST_NAME = "www.google.com";
48 
49     static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
50 
51     static final String preferIPV6Address =
52             System.getProperty("java.net.preferIPv6Addresses", "false");
53 
main(String args[])54     public static void main(String args[]) throws IOException {
55         InetAddress addrs[];
56         try {
57             addrs = InetAddress.getAllByName(HOST_NAME);
58         } catch (UnknownHostException e) {
59             out.println("Unknown host " + HOST_NAME + ", cannot run test.");
60             return;
61         }
62 
63         int firstIPv4Address = IntStream.range(0, addrs.length)
64                 .filter(x -> addrs[x] instanceof Inet4Address)
65                 .findFirst().orElse(-1);
66         int firstIPv6Address = IntStream.range(0, addrs.length)
67                 .filter(x -> addrs[x] instanceof Inet6Address)
68                 .findFirst().orElse(-1);
69 
70         out.println("IPv6 supported: " + IPSupport.hasIPv6());
71         out.println("Addresses: " + Arrays.asList(addrs));
72 
73         if (preferIPV6Address.equalsIgnoreCase("true") && firstIPv6Address != -1) {
74             int off = firstIPv4Address != -1 ? firstIPv4Address : addrs.length;
75             assertAllv6Addresses(addrs, 0, off);
76             assertAllv4Addresses(addrs, off, addrs.length);
77             assertLoopbackAddress(Inet6Address.class);
78             assertAnyLocalAddress(Inet6Address.class);
79         } else if (preferIPV6Address.equalsIgnoreCase("false") && firstIPv4Address != -1) {
80             int off = firstIPv6Address != -1 ? firstIPv6Address : addrs.length;
81             assertAllv4Addresses(addrs, 0, off);
82             assertAllv6Addresses(addrs, off, addrs.length);
83             assertLoopbackAddress(Inet4Address.class);
84             assertAnyLocalAddress(Inet4Address.class);
85         } else if (preferIPV6Address.equalsIgnoreCase("system") && IPSupport.hasIPv6()) {
86             assertLoopbackAddress(Inet6Address.class);
87             assertAnyLocalAddress(Inet6Address.class);
88         } else if (preferIPV6Address.equalsIgnoreCase("system") && !IPSupport.hasIPv6()) {
89             assertLoopbackAddress(Inet4Address.class);
90             assertAnyLocalAddress(Inet4Address.class);
91         }
92     }
93 
assertAllv4Addresses(InetAddress[] addrs, int off, int len)94     static void assertAllv4Addresses(InetAddress[] addrs, int off, int len) {
95         IntStream.range(off, len)
96                  .mapToObj(x -> addrs[x])
97                  .forEach(x -> {
98                      if (!(x instanceof Inet4Address))
99                          throw new RuntimeException("Expected IPv4, got " + x);
100                  });
101     }
102 
assertAllv6Addresses(InetAddress[] addrs, int off, int len)103     static void assertAllv6Addresses(InetAddress[] addrs, int off, int len) {
104         IntStream.range(off, len)
105                 .mapToObj(x -> addrs[x])
106                 .forEach(x -> {
107                     if (!(x instanceof Inet6Address))
108                         throw new RuntimeException("Expected IPv6, got " + x);
109                 });
110     }
111 
assertLoopbackAddress(Class<?> expectedType)112     static void assertLoopbackAddress(Class<?> expectedType) {
113         if (!LOOPBACK.getClass().isAssignableFrom(expectedType))
114             throw new RuntimeException("Expected " + expectedType
115                     + ", got " + LOOPBACK.getClass());
116     }
117 
assertAnyLocalAddress(Class<?> expectedType)118     static void assertAnyLocalAddress(Class<?> expectedType) {
119         InetAddress anyAddr = (new InetSocketAddress(0)).getAddress();
120         if (!anyAddr.getClass().isAssignableFrom(expectedType))
121             throw new RuntimeException("Expected " + expectedType
122                     + ", got " + anyAddr.getClass());
123     }
124 }
125