• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Guava Authors
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.common.net;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static org.junit.Assert.assertThrows;
21 
22 import com.google.common.collect.ImmutableSet;
23 import com.google.common.testing.NullPointerTester;
24 import java.math.BigInteger;
25 import java.net.Inet4Address;
26 import java.net.Inet6Address;
27 import java.net.InetAddress;
28 import java.net.UnknownHostException;
29 import junit.framework.TestCase;
30 
31 /**
32  * Tests for {@link InetAddresses}.
33  *
34  * @author Erik Kline
35  */
36 public class InetAddressesTest extends TestCase {
37 
testNulls()38   public void testNulls() {
39     NullPointerTester tester = new NullPointerTester();
40 
41     tester.testAllPublicStaticMethods(InetAddresses.class);
42   }
43 
testForStringBogusInput()44   public void testForStringBogusInput() {
45     ImmutableSet<String> bogusInputs =
46         ImmutableSet.of(
47             "",
48             "016.016.016.016",
49             "016.016.016",
50             "016.016",
51             "016",
52             "000.000.000.000",
53             "000",
54             "0x0a.0x0a.0x0a.0x0a",
55             "0x0a.0x0a.0x0a",
56             "0x0a.0x0a",
57             "0x0a",
58             "42.42.42.42.42",
59             "42.42.42",
60             "42.42",
61             "42",
62             "42..42.42",
63             "42..42.42.42",
64             "42.42.42.42.",
65             "42.42.42.42...",
66             ".42.42.42.42",
67             ".42.42.42",
68             "...42.42.42.42",
69             "42.42.42.-0",
70             "42.42.42.+0",
71             ".",
72             "...",
73             "bogus",
74             "bogus.com",
75             "192.168.0.1.com",
76             "12345.67899.-54321.-98765",
77             "257.0.0.0",
78             "42.42.42.-42",
79             "42.42.42.ab",
80             "3ffe::1.net",
81             "3ffe::1::1",
82             "1::2::3::4:5",
83             "::7:6:5:4:3:2:", // should end with ":0"
84             ":6:5:4:3:2:1::", // should begin with "0:"
85             "2001::db:::1",
86             "FEDC:9878",
87             "+1.+2.+3.4",
88             "1.2.3.4e0",
89             "6:5:4:3:2:1:0", // too few parts
90             "::7:6:5:4:3:2:1:0", // too many parts
91             "7:6:5:4:3:2:1:0::", // too many parts
92             "9:8:7:6:5:4:3::2:1", // too many parts
93             "0:1:2:3::4:5:6:7", // :: must remove at least one 0.
94             "3ffe:0:0:0:0:0:0:0:1", // too many parts (9 instead of 8)
95             "3ffe::10000", // hextet exceeds 16 bits
96             "3ffe::goog",
97             "3ffe::-0",
98             "3ffe::+0",
99             "3ffe::-1",
100             ":",
101             ":::",
102             "::1.2.3",
103             "::1.2.3.4.5",
104             "::1.2.3.4:",
105             "1.2.3.4::",
106             "2001:db8::1:",
107             ":2001:db8::1",
108             ":1:2:3:4:5:6:7",
109             "1:2:3:4:5:6:7:",
110             ":1:2:3:4:5:6:");
111 
112     for (String bogusInput : bogusInputs) {
113       assertThrows(
114           "IllegalArgumentException expected for '" + bogusInput + "'",
115           IllegalArgumentException.class,
116           () -> InetAddresses.forString(bogusInput));
117       assertFalse(InetAddresses.isInetAddress(bogusInput));
118     }
119   }
120 
test3ff31()121   public void test3ff31() {
122     assertThrows(IllegalArgumentException.class, () -> InetAddresses.forString("3ffe:::1"));
123     assertFalse(InetAddresses.isInetAddress("016.016.016.016"));
124   }
125 
testForStringIPv4Input()126   public void testForStringIPv4Input() throws UnknownHostException {
127     String ipStr = "192.168.0.1";
128     // Shouldn't hit DNS, because it's an IP string literal.
129     InetAddress ipv4Addr = InetAddress.getByName(ipStr);
130     assertEquals(ipv4Addr, InetAddresses.forString(ipStr));
131     assertTrue(InetAddresses.isInetAddress(ipStr));
132   }
133 
testForStringIPv4NonAsciiInput()134   public void testForStringIPv4NonAsciiInput() throws UnknownHostException {
135     String ipStr = "૧૯૨.૧૬૮.૦.૧"; // 192.168.0.1 in Gujarati digits
136     // Shouldn't hit DNS, because it's an IP string literal.
137     InetAddress ipv4Addr;
138     try {
139       ipv4Addr = InetAddress.getByName(ipStr);
140     } catch (UnknownHostException e) {
141       // OK: this is probably Android, which is stricter.
142       return;
143     }
144     assertEquals(ipv4Addr, InetAddresses.forString(ipStr));
145     assertTrue(InetAddresses.isInetAddress(ipStr));
146   }
147 
testForStringIPv6Input()148   public void testForStringIPv6Input() throws UnknownHostException {
149     String ipStr = "3ffe::1";
150     // Shouldn't hit DNS, because it's an IP string literal.
151     InetAddress ipv6Addr = InetAddress.getByName(ipStr);
152     assertEquals(ipv6Addr, InetAddresses.forString(ipStr));
153     assertTrue(InetAddresses.isInetAddress(ipStr));
154   }
155 
testForStringIPv6NonAsciiInput()156   public void testForStringIPv6NonAsciiInput() throws UnknownHostException {
157     String ipStr = "૩ffe::૧"; // 3ffe::1 with Gujarati digits for 3 and 1
158     // Shouldn't hit DNS, because it's an IP string literal.
159     InetAddress ipv6Addr;
160     try {
161       ipv6Addr = InetAddress.getByName(ipStr);
162     } catch (UnknownHostException e) {
163       // OK: this is probably Android, which is stricter.
164       return;
165     }
166     assertEquals(ipv6Addr, InetAddresses.forString(ipStr));
167     assertTrue(InetAddresses.isInetAddress(ipStr));
168   }
169 
testForStringIPv6EightColons()170   public void testForStringIPv6EightColons() throws UnknownHostException {
171     ImmutableSet<String> eightColons =
172         ImmutableSet.of("::7:6:5:4:3:2:1", "::7:6:5:4:3:2:0", "7:6:5:4:3:2:1::", "0:6:5:4:3:2:1::");
173 
174     for (String ipString : eightColons) {
175       // Shouldn't hit DNS, because it's an IP string literal.
176       InetAddress ipv6Addr = InetAddress.getByName(ipString);
177       assertEquals(ipv6Addr, InetAddresses.forString(ipString));
178       assertTrue(InetAddresses.isInetAddress(ipString));
179     }
180   }
181 
testConvertDottedQuadToHex()182   public void testConvertDottedQuadToHex() throws UnknownHostException {
183     ImmutableSet<String> ipStrings =
184         ImmutableSet.of("7::0.128.0.127", "7::0.128.0.128", "7::128.128.0.127", "7::0.128.128.127");
185 
186     for (String ipString : ipStrings) {
187       // Shouldn't hit DNS, because it's an IP string literal.
188       InetAddress ipv6Addr = InetAddress.getByName(ipString);
189       assertEquals(ipv6Addr, InetAddresses.forString(ipString));
190       assertTrue(InetAddresses.isInetAddress(ipString));
191     }
192   }
193 
194   // see https://github.com/google/guava/issues/2587
195   private static final ImmutableSet<String> SCOPE_IDS =
196       ImmutableSet.of("eno1", "en1", "eth0", "X", "1", "2", "14", "20");
197 
testIPv4AddressWithScopeId()198   public void testIPv4AddressWithScopeId() {
199     ImmutableSet<String> ipStrings = ImmutableSet.of("1.2.3.4", "192.168.0.1");
200     for (String ipString : ipStrings) {
201       for (String scopeId : SCOPE_IDS) {
202         String withScopeId = ipString + "%" + scopeId;
203         assertFalse(
204             "InetAddresses.isInetAddress(" + withScopeId + ") should be false but was true",
205             InetAddresses.isInetAddress(withScopeId));
206       }
207     }
208   }
209 
testDottedQuadAddressWithScopeId()210   public void testDottedQuadAddressWithScopeId() {
211     ImmutableSet<String> ipStrings =
212         ImmutableSet.of("7::0.128.0.127", "7::0.128.0.128", "7::128.128.0.127", "7::0.128.128.127");
213     for (String ipString : ipStrings) {
214       for (String scopeId : SCOPE_IDS) {
215         String withScopeId = ipString + "%" + scopeId;
216         assertFalse(
217             "InetAddresses.isInetAddress(" + withScopeId + ") should be false but was true",
218             InetAddresses.isInetAddress(withScopeId));
219       }
220     }
221   }
222 
testIPv6AddressWithScopeId()223   public void testIPv6AddressWithScopeId() {
224     ImmutableSet<String> ipStrings =
225         ImmutableSet.of(
226             "0:0:0:0:0:0:0:1",
227             "fe80::a",
228             "fe80::1",
229             "fe80::2",
230             "fe80::42",
231             "fe80::3dd0:7f8e:57b7:34d5",
232             "fe80::71a3:2b00:ddd3:753f",
233             "fe80::8b2:d61e:e5c:b333",
234             "fe80::b059:65f4:e877:c40");
235     for (String ipString : ipStrings) {
236       for (String scopeId : SCOPE_IDS) {
237         String withScopeId = ipString + "%" + scopeId;
238         assertTrue(
239             "InetAddresses.isInetAddress(" + withScopeId + ") should be true but was false",
240             InetAddresses.isInetAddress(withScopeId));
241         assertEquals(InetAddresses.forString(withScopeId), InetAddresses.forString(ipString));
242       }
243     }
244   }
245 
testToAddrStringIPv4()246   public void testToAddrStringIPv4() {
247     // Don't need to test IPv4 much; it just calls getHostAddress().
248     assertEquals("1.2.3.4", InetAddresses.toAddrString(InetAddresses.forString("1.2.3.4")));
249   }
250 
testToAddrStringIPv6()251   public void testToAddrStringIPv6() {
252     assertEquals(
253         "1:2:3:4:5:6:7:8", InetAddresses.toAddrString(InetAddresses.forString("1:2:3:4:5:6:7:8")));
254     assertEquals(
255         "2001:0:0:4::8", InetAddresses.toAddrString(InetAddresses.forString("2001:0:0:4:0:0:0:8")));
256     assertEquals(
257         "2001::4:5:6:7:8",
258         InetAddresses.toAddrString(InetAddresses.forString("2001:0:0:4:5:6:7:8")));
259     assertEquals(
260         "2001:0:3:4:5:6:7:8",
261         InetAddresses.toAddrString(InetAddresses.forString("2001:0:3:4:5:6:7:8")));
262     assertEquals(
263         "0:0:3::ffff", InetAddresses.toAddrString(InetAddresses.forString("0:0:3:0:0:0:0:ffff")));
264     assertEquals(
265         "::4:0:0:0:ffff",
266         InetAddresses.toAddrString(InetAddresses.forString("0:0:0:4:0:0:0:ffff")));
267     assertEquals(
268         "::5:0:0:ffff", InetAddresses.toAddrString(InetAddresses.forString("0:0:0:0:5:0:0:ffff")));
269     assertEquals(
270         "1::4:0:0:7:8", InetAddresses.toAddrString(InetAddresses.forString("1:0:0:4:0:0:7:8")));
271     assertEquals("::", InetAddresses.toAddrString(InetAddresses.forString("0:0:0:0:0:0:0:0")));
272     assertEquals("::1", InetAddresses.toAddrString(InetAddresses.forString("0:0:0:0:0:0:0:1")));
273     assertEquals(
274         "2001:658:22a:cafe::",
275         InetAddresses.toAddrString(InetAddresses.forString("2001:0658:022a:cafe::")));
276     assertEquals("::102:304", InetAddresses.toAddrString(InetAddresses.forString("::1.2.3.4")));
277   }
278 
testToUriStringIPv4()279   public void testToUriStringIPv4() {
280     String ipStr = "1.2.3.4";
281     InetAddress ip = InetAddresses.forString(ipStr);
282     assertEquals("1.2.3.4", InetAddresses.toUriString(ip));
283   }
284 
testToUriStringIPv6()285   public void testToUriStringIPv6() {
286     // Unfortunately the InetAddress.toString() method for IPv6 addresses
287     // does not collapse contiguous shorts of zeroes with the :: abbreviation.
288     String ipStr = "3ffe::1";
289     InetAddress ip = InetAddresses.forString(ipStr);
290     assertEquals("[3ffe::1]", InetAddresses.toUriString(ip));
291   }
292 
testForUriStringIPv4()293   public void testForUriStringIPv4() {
294     Inet4Address expected = (Inet4Address) InetAddresses.forString("192.168.1.1");
295     assertEquals(expected, InetAddresses.forUriString("192.168.1.1"));
296   }
297 
testForUriStringIPv6()298   public void testForUriStringIPv6() {
299     Inet6Address expected = (Inet6Address) InetAddresses.forString("3ffe:0:0:0:0:0:0:1");
300     assertEquals(expected, InetAddresses.forUriString("[3ffe:0:0:0:0:0:0:1]"));
301   }
302 
testForUriStringIPv4Mapped()303   public void testForUriStringIPv4Mapped() {
304     Inet4Address expected = (Inet4Address) InetAddresses.forString("192.0.2.1");
305     assertEquals(expected, InetAddresses.forUriString("[::ffff:192.0.2.1]"));
306   }
307 
testIsUriInetAddress()308   public void testIsUriInetAddress() {
309     assertTrue(InetAddresses.isUriInetAddress("192.168.1.1"));
310     assertTrue(InetAddresses.isUriInetAddress("[3ffe:0:0:0:0:0:0:1]"));
311     assertTrue(InetAddresses.isUriInetAddress("[::ffff:192.0.2.1]"));
312 
313     assertFalse(InetAddresses.isUriInetAddress("[192.168.1.1"));
314     assertFalse(InetAddresses.isUriInetAddress("192.168.1.1]"));
315     assertFalse(InetAddresses.isUriInetAddress(""));
316     assertFalse(InetAddresses.isUriInetAddress("192.168.999.888"));
317     assertFalse(InetAddresses.isUriInetAddress("www.google.com"));
318     assertFalse(InetAddresses.isUriInetAddress("1:2e"));
319     assertFalse(InetAddresses.isUriInetAddress("[3ffe:0:0:0:0:0:0:1"));
320     assertFalse(InetAddresses.isUriInetAddress("3ffe:0:0:0:0:0:0:1]"));
321     assertFalse(InetAddresses.isUriInetAddress("3ffe:0:0:0:0:0:0:1"));
322     assertFalse(InetAddresses.isUriInetAddress("::ffff:192.0.2.1"));
323   }
324 
testForUriStringBad()325   public void testForUriStringBad() {
326     assertThrows(IllegalArgumentException.class, () -> InetAddresses.forUriString(""));
327 
328     assertThrows(
329         IllegalArgumentException.class, () -> InetAddresses.forUriString("192.168.999.888"));
330 
331     assertThrows(
332         IllegalArgumentException.class, () -> InetAddresses.forUriString("www.google.com"));
333 
334     assertThrows(IllegalArgumentException.class, () -> InetAddresses.forUriString("[1:2e]"));
335 
336     assertThrows(IllegalArgumentException.class, () -> InetAddresses.forUriString("[192.168.1.1]"));
337 
338     assertThrows(IllegalArgumentException.class, () -> InetAddresses.forUriString("192.168.1.1]"));
339 
340     assertThrows(IllegalArgumentException.class, () -> InetAddresses.forUriString("[192.168.1.1"));
341 
342     assertThrows(
343         IllegalArgumentException.class, () -> InetAddresses.forUriString("[3ffe:0:0:0:0:0:0:1"));
344 
345     assertThrows(
346         IllegalArgumentException.class, () -> InetAddresses.forUriString("3ffe:0:0:0:0:0:0:1]"));
347 
348     assertThrows(
349         IllegalArgumentException.class, () -> InetAddresses.forUriString("3ffe:0:0:0:0:0:0:1"));
350 
351     assertThrows(
352         IllegalArgumentException.class, () -> InetAddresses.forUriString("::ffff:192.0.2.1"));
353   }
354 
testCompatIPv4Addresses()355   public void testCompatIPv4Addresses() {
356     ImmutableSet<String> nonCompatAddresses = ImmutableSet.of("3ffe::1", "::", "::1");
357 
358     for (String nonCompatAddress : nonCompatAddresses) {
359       InetAddress ip = InetAddresses.forString(nonCompatAddress);
360       assertFalse(InetAddresses.isCompatIPv4Address((Inet6Address) ip));
361       assertThrows(
362           "IllegalArgumentException expected for '" + nonCompatAddress + "'",
363           IllegalArgumentException.class,
364           () -> InetAddresses.getCompatIPv4Address((Inet6Address) ip));
365     }
366 
367     ImmutableSet<String> validCompatAddresses = ImmutableSet.of("::1.2.3.4", "::102:304");
368     String compatStr = "1.2.3.4";
369     InetAddress compat = InetAddresses.forString(compatStr);
370 
371     for (String validCompatAddress : validCompatAddresses) {
372       InetAddress ip = InetAddresses.forString(validCompatAddress);
373       assertTrue("checking '" + validCompatAddress + "'", ip instanceof Inet6Address);
374       assertTrue(
375           "checking '" + validCompatAddress + "'",
376           InetAddresses.isCompatIPv4Address((Inet6Address) ip));
377       assertEquals(
378           "checking '" + validCompatAddress + "'",
379           compat,
380           InetAddresses.getCompatIPv4Address((Inet6Address) ip));
381     }
382   }
383 
testMappedIPv4Addresses()384   public void testMappedIPv4Addresses() throws UnknownHostException {
385     /*
386      * Verify that it is not possible to instantiate an Inet6Address
387      * from an "IPv4 mapped" IPv6 address.  Our String-based method can
388      * at least identify them, however.
389      */
390     String mappedStr = "::ffff:192.168.0.1";
391     assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
392     InetAddress mapped = InetAddresses.forString(mappedStr);
393     assertThat(mapped).isNotInstanceOf(Inet6Address.class);
394     assertEquals(InetAddress.getByName("192.168.0.1"), mapped);
395 
396     // check upper case
397     mappedStr = "::FFFF:192.168.0.1";
398     assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
399     mapped = InetAddresses.forString(mappedStr);
400     assertThat(mapped).isNotInstanceOf(Inet6Address.class);
401     assertEquals(InetAddress.getByName("192.168.0.1"), mapped);
402 
403     mappedStr = "0:00:000:0000:0:ffff:1.2.3.4";
404     assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
405     mapped = InetAddresses.forString(mappedStr);
406     assertThat(mapped).isNotInstanceOf(Inet6Address.class);
407     assertEquals(InetAddress.getByName("1.2.3.4"), mapped);
408 
409     mappedStr = "::ffff:0102:0304";
410     assertTrue(InetAddresses.isMappedIPv4Address(mappedStr));
411     mapped = InetAddresses.forString(mappedStr);
412     assertThat(mapped).isNotInstanceOf(Inet6Address.class);
413     assertEquals(InetAddress.getByName("1.2.3.4"), mapped);
414 
415     assertFalse(InetAddresses.isMappedIPv4Address("::"));
416     assertFalse(InetAddresses.isMappedIPv4Address("::ffff"));
417     assertFalse(InetAddresses.isMappedIPv4Address("::ffff:0"));
418     assertFalse(InetAddresses.isMappedIPv4Address("::fffe:0:0"));
419     assertFalse(InetAddresses.isMappedIPv4Address("::1:ffff:0:0"));
420     assertFalse(InetAddresses.isMappedIPv4Address("foo"));
421     assertFalse(InetAddresses.isMappedIPv4Address("192.0.2.1"));
422   }
423 
test6to4Addresses()424   public void test6to4Addresses() {
425     ImmutableSet<String> non6to4Addresses = ImmutableSet.of("::1.2.3.4", "3ffe::1", "::", "::1");
426 
427     for (String non6to4Address : non6to4Addresses) {
428       InetAddress ip = InetAddresses.forString(non6to4Address);
429       assertFalse(InetAddresses.is6to4Address((Inet6Address) ip));
430       assertThrows(
431           "IllegalArgumentException expected for '" + non6to4Address + "'",
432           IllegalArgumentException.class,
433           () -> InetAddresses.get6to4IPv4Address((Inet6Address) ip));
434     }
435 
436     String valid6to4Address = "2002:0102:0304::1";
437     String ipv4Str = "1.2.3.4";
438 
439     InetAddress ipv4 = InetAddresses.forString(ipv4Str);
440     InetAddress ip = InetAddresses.forString(valid6to4Address);
441     assertTrue(InetAddresses.is6to4Address((Inet6Address) ip));
442     assertEquals(ipv4, InetAddresses.get6to4IPv4Address((Inet6Address) ip));
443   }
444 
testTeredoAddresses()445   public void testTeredoAddresses() {
446     ImmutableSet<String> nonTeredoAddresses = ImmutableSet.of("::1.2.3.4", "3ffe::1", "::", "::1");
447 
448     for (String nonTeredoAddress : nonTeredoAddresses) {
449       InetAddress ip = InetAddresses.forString(nonTeredoAddress);
450       assertFalse(InetAddresses.isTeredoAddress((Inet6Address) ip));
451       assertThrows(
452           "IllegalArgumentException expected for '" + nonTeredoAddress + "'",
453           IllegalArgumentException.class,
454           () -> InetAddresses.getTeredoInfo((Inet6Address) ip));
455     }
456 
457     String validTeredoAddress = "2001:0000:4136:e378:8000:63bf:3fff:fdd2";
458     String serverStr = "65.54.227.120";
459     String clientStr = "192.0.2.45";
460     int port = 40000;
461     int flags = 0x8000;
462 
463     InetAddress ip = InetAddresses.forString(validTeredoAddress);
464     assertTrue(InetAddresses.isTeredoAddress((Inet6Address) ip));
465     InetAddresses.TeredoInfo teredo = InetAddresses.getTeredoInfo((Inet6Address) ip);
466 
467     InetAddress server = InetAddresses.forString(serverStr);
468     assertEquals(server, teredo.getServer());
469 
470     InetAddress client = InetAddresses.forString(clientStr);
471     assertEquals(client, teredo.getClient());
472 
473     assertEquals(port, teredo.getPort());
474     assertEquals(flags, teredo.getFlags());
475   }
476 
testTeredoAddress_nullServer()477   public void testTeredoAddress_nullServer() {
478     InetAddresses.TeredoInfo info = new InetAddresses.TeredoInfo(null, null, 80, 1000);
479     assertEquals(InetAddresses.forString("0.0.0.0"), info.getServer());
480     assertEquals(InetAddresses.forString("0.0.0.0"), info.getClient());
481     assertEquals(80, info.getPort());
482     assertEquals(1000, info.getFlags());
483   }
484 
testIsatapAddresses()485   public void testIsatapAddresses() {
486     InetAddress ipv4 = InetAddresses.forString("1.2.3.4");
487     ImmutableSet<String> validIsatapAddresses =
488         ImmutableSet.of(
489             "2001:db8::5efe:102:304",
490             "2001:db8::100:5efe:102:304", // Private Multicast? Not likely.
491             "2001:db8::200:5efe:102:304",
492             "2001:db8::300:5efe:102:304" // Public Multicast? Also unlikely.
493             );
494     ImmutableSet<String> nonIsatapAddresses =
495         ImmutableSet.of(
496             "::1.2.3.4",
497             "3ffe::1",
498             "::",
499             "::1",
500             "2001:db8::0040:5efe:102:304",
501             "2001:db8::5ffe:102:304",
502             "2001:db8::5eff:102:304",
503             "2001:0:102:203:200:5efe:506:708" // Teredo address; not ISATAP
504             );
505 
506     for (String validIsatapAddress : validIsatapAddresses) {
507       InetAddress ip = InetAddresses.forString(validIsatapAddress);
508       assertTrue(InetAddresses.isIsatapAddress((Inet6Address) ip));
509       assertEquals(
510           "checking '" + validIsatapAddress + "'",
511           ipv4,
512           InetAddresses.getIsatapIPv4Address((Inet6Address) ip));
513     }
514     for (String nonIsatapAddress : nonIsatapAddresses) {
515       InetAddress ip = InetAddresses.forString(nonIsatapAddress);
516       assertFalse(InetAddresses.isIsatapAddress((Inet6Address) ip));
517       assertThrows(
518           "IllegalArgumentException expected for '" + nonIsatapAddress + "'",
519           IllegalArgumentException.class,
520           () -> InetAddresses.getIsatapIPv4Address((Inet6Address) ip));
521     }
522   }
523 
testGetEmbeddedIPv4ClientAddress()524   public void testGetEmbeddedIPv4ClientAddress() {
525     Inet6Address testIp;
526 
527     // Test regular global unicast address.
528     testIp = (Inet6Address) InetAddresses.forString("2001:db8::1");
529     assertFalse(InetAddresses.hasEmbeddedIPv4ClientAddress(testIp));
530 
531     // Test ISATAP address.
532     testIp = (Inet6Address) InetAddresses.forString("2001:db8::5efe:102:304");
533     assertFalse(InetAddresses.hasEmbeddedIPv4ClientAddress(testIp));
534 
535     // Test compat address.
536     testIp = (Inet6Address) InetAddresses.forString("::1.2.3.4");
537     assertTrue(InetAddresses.hasEmbeddedIPv4ClientAddress(testIp));
538     InetAddress ipv4 = InetAddresses.forString("1.2.3.4");
539     assertEquals(ipv4, InetAddresses.getEmbeddedIPv4ClientAddress(testIp));
540 
541     // Test 6to4 address.
542     testIp = (Inet6Address) InetAddresses.forString("2002:0102:0304::1");
543     assertTrue(InetAddresses.hasEmbeddedIPv4ClientAddress(testIp));
544     ipv4 = InetAddresses.forString("1.2.3.4");
545     assertEquals(ipv4, InetAddresses.getEmbeddedIPv4ClientAddress(testIp));
546 
547     // Test Teredo address.
548     testIp = (Inet6Address) InetAddresses.forString("2001:0000:4136:e378:8000:63bf:3fff:fdd2");
549     assertTrue(InetAddresses.hasEmbeddedIPv4ClientAddress(testIp));
550     ipv4 = InetAddresses.forString("192.0.2.45");
551     assertEquals(ipv4, InetAddresses.getEmbeddedIPv4ClientAddress(testIp));
552   }
553 
testGetCoercedIPv4Address()554   public void testGetCoercedIPv4Address() {
555     // Check that a coerced IPv4 address is unaltered.
556     assertThat(InetAddresses.getCoercedIPv4Address(InetAddresses.forString("127.0.0.1")))
557         .isEqualTo(InetAddresses.forString("127.0.0.1"));
558 
559     // ::1 special case
560     assertThat(InetAddresses.getCoercedIPv4Address(InetAddresses.forString("::1")))
561         .isEqualTo(InetAddresses.forString("127.0.0.1"));
562 
563     // :: special case
564     assertThat(InetAddresses.getCoercedIPv4Address(InetAddresses.forString("::")))
565         .isEqualTo(InetAddresses.forString("0.0.0.0"));
566 
567     // test compat address (should be hashed)
568     assertThat(InetAddresses.getCoercedIPv4Address(InetAddresses.forString("::1.2.3.4")))
569         .isNotEqualTo(InetAddresses.forString("1.2.3.4"));
570 
571     // test 6to4 address (should be hashed)
572     assertThat(InetAddresses.getCoercedIPv4Address(InetAddresses.forString("2002:0102:0304::1")))
573         .isNotEqualTo(InetAddresses.forString("1.2.3.4"));
574 
575     // 2 6to4 addresses differing in the embedded IPv4 address should
576     // hash to the different values.
577     assertThat(InetAddresses.getCoercedIPv4Address(InetAddresses.forString("2002:0102:0304::1")))
578         .isNotEqualTo(
579             InetAddresses.getCoercedIPv4Address(InetAddresses.forString("2002:0506:0708::1")));
580 
581     // 2 6to4 addresses NOT differing in the embedded IPv4 address should
582     // hash to the same value.
583     assertThat(InetAddresses.getCoercedIPv4Address(InetAddresses.forString("2002:0102:0304::1")))
584         .isEqualTo(
585             InetAddresses.getCoercedIPv4Address(InetAddresses.forString("2002:0102:0304::2")));
586 
587     // test Teredo address (should be hashed)
588     assertThat(
589             InetAddresses.getCoercedIPv4Address(
590                 InetAddresses.forString("2001:0000:4136:e378:8000:63bf:3fff:fdd2")))
591         .isNotEqualTo(InetAddresses.forString("192.0.2.45"));
592 
593     // 2 Teredo addresses differing in their embedded IPv4 addresses should hash to different
594     // values.
595     assertThat(
596             InetAddresses.getCoercedIPv4Address(
597                 InetAddresses.forString("2001:0000:4136:e378:8000:63bf:3fff:fdd2")))
598         .isNotEqualTo(
599             InetAddresses.getCoercedIPv4Address(
600                 InetAddresses.forString("2001:0000:4136:e378:8000:63bf:3fff:fdd3")));
601 
602     // 2 Teredo addresses NOT differing in their embedded IPv4 addresses should hash to the same
603     // value.
604     assertThat(
605             InetAddresses.getCoercedIPv4Address(
606                 InetAddresses.forString("2001:0000:4136:e378:8000:63bf:3fff:fdd2")))
607         .isEqualTo(
608             InetAddresses.getCoercedIPv4Address(
609                 InetAddresses.forString("2001:0000:5136:f378:9000:73bf:3fff:fdd2")));
610 
611     // Test that an address hashes in to the 224.0.0.0/3 number-space.
612     int coercedInt =
613         InetAddresses.coerceToInteger(
614             InetAddresses.getCoercedIPv4Address(InetAddresses.forString("2001:4860::1")));
615     assertThat(coercedInt).isAtLeast(0xe0000000);
616     assertThat(coercedInt).isAtMost(0xfffffffe);
617   }
618 
testCoerceToInteger()619   public void testCoerceToInteger() {
620     assertThat(InetAddresses.coerceToInteger(InetAddresses.forString("127.0.0.1")))
621         .isEqualTo(0x7f000001);
622   }
623 
testFromInteger()624   public void testFromInteger() {
625     assertThat(InetAddresses.fromInteger(0x7f000001))
626         .isEqualTo(InetAddresses.forString("127.0.0.1"));
627   }
628 
testFromLittleEndianByteArray()629   public void testFromLittleEndianByteArray() throws UnknownHostException {
630     assertEquals(
631         InetAddresses.fromLittleEndianByteArray(new byte[] {1, 2, 3, 4}),
632         InetAddress.getByAddress(new byte[] {4, 3, 2, 1}));
633 
634     assertEquals(
635         InetAddresses.fromLittleEndianByteArray(
636             new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}),
637         InetAddress.getByAddress(
638             new byte[] {16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}));
639 
640     assertThrows(
641         UnknownHostException.class, () -> InetAddresses.fromLittleEndianByteArray(new byte[3]));
642   }
643 
testIsMaximum()644   public void testIsMaximum() throws UnknownHostException {
645     InetAddress address = InetAddress.getByName("255.255.255.254");
646     assertFalse(InetAddresses.isMaximum(address));
647 
648     address = InetAddress.getByName("255.255.255.255");
649     assertTrue(InetAddresses.isMaximum(address));
650 
651     address = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffe");
652     assertFalse(InetAddresses.isMaximum(address));
653 
654     address = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
655     assertTrue(InetAddresses.isMaximum(address));
656   }
657 
testIncrementIPv4()658   public void testIncrementIPv4() throws UnknownHostException {
659     InetAddress address_66_0 = InetAddress.getByName("172.24.66.0");
660     InetAddress address_66_255 = InetAddress.getByName("172.24.66.255");
661     InetAddress address_67_0 = InetAddress.getByName("172.24.67.0");
662 
663     InetAddress address = address_66_0;
664     for (int i = 0; i < 255; i++) {
665       address = InetAddresses.increment(address);
666     }
667     assertEquals(address_66_255, address);
668 
669     address = InetAddresses.increment(address);
670     assertEquals(address_67_0, address);
671 
672     InetAddress address_ffffff = InetAddress.getByName("255.255.255.255");
673     assertThrows(IllegalArgumentException.class, () -> InetAddresses.increment(address_ffffff));
674   }
675 
testIncrementIPv6()676   public void testIncrementIPv6() throws UnknownHostException {
677     InetAddress addressV6_66_0 = InetAddress.getByName("2001:db8::6600");
678     InetAddress addressV6_66_ff = InetAddress.getByName("2001:db8::66ff");
679     InetAddress addressV6_67_0 = InetAddress.getByName("2001:db8::6700");
680 
681     InetAddress address = addressV6_66_0;
682     for (int i = 0; i < 255; i++) {
683       address = InetAddresses.increment(address);
684     }
685     assertEquals(addressV6_66_ff, address);
686 
687     address = InetAddresses.increment(address);
688     assertEquals(addressV6_67_0, address);
689 
690     InetAddress addressV6_ffffff = InetAddress.getByName("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");
691     assertThrows(IllegalArgumentException.class, () -> InetAddresses.increment(addressV6_ffffff));
692   }
693 
testDecrementIPv4()694   public void testDecrementIPv4() throws UnknownHostException {
695     InetAddress address660 = InetAddress.getByName("172.24.66.0");
696     InetAddress address66255 = InetAddress.getByName("172.24.66.255");
697     InetAddress address670 = InetAddress.getByName("172.24.67.0");
698 
699     InetAddress address = address670;
700     address = InetAddresses.decrement(address);
701 
702     assertEquals(address66255, address);
703 
704     for (int i = 0; i < 255; i++) {
705       address = InetAddresses.decrement(address);
706     }
707     assertEquals(address660, address);
708 
709     InetAddress address0000 = InetAddress.getByName("0.0.0.0");
710     assertThrows(IllegalArgumentException.class, () -> InetAddresses.decrement(address0000));
711   }
712 
testDecrementIPv6()713   public void testDecrementIPv6() throws UnknownHostException {
714     InetAddress addressV6660 = InetAddress.getByName("2001:db8::6600");
715     InetAddress addressV666ff = InetAddress.getByName("2001:db8::66ff");
716     InetAddress addressV6670 = InetAddress.getByName("2001:db8::6700");
717 
718     InetAddress address = addressV6670;
719     address = InetAddresses.decrement(address);
720 
721     assertEquals(addressV666ff, address);
722 
723     for (int i = 0; i < 255; i++) {
724       address = InetAddresses.decrement(address);
725     }
726     assertEquals(addressV6660, address);
727 
728     InetAddress addressV6000000 = InetAddress.getByName("0:0:0:0:0:0:0:0");
729     assertThrows(IllegalArgumentException.class, () -> InetAddresses.decrement(addressV6000000));
730   }
731 
testFromIpv4BigIntegerThrowsLessThanZero()732   public void testFromIpv4BigIntegerThrowsLessThanZero() {
733     IllegalArgumentException expected =
734         assertThrows(
735             IllegalArgumentException.class,
736             () -> InetAddresses.fromIPv4BigInteger(BigInteger.valueOf(-1L)));
737     assertEquals("BigInteger must be greater than or equal to 0", expected.getMessage());
738   }
739 
testFromIpv6BigIntegerThrowsLessThanZero()740   public void testFromIpv6BigIntegerThrowsLessThanZero() {
741     IllegalArgumentException expected =
742         assertThrows(
743             IllegalArgumentException.class,
744             () -> InetAddresses.fromIPv6BigInteger(BigInteger.valueOf(-1L)));
745     assertEquals("BigInteger must be greater than or equal to 0", expected.getMessage());
746   }
747 
testFromIpv4BigIntegerValid()748   public void testFromIpv4BigIntegerValid() {
749     checkBigIntegerConversion("0.0.0.0", BigInteger.ZERO);
750     checkBigIntegerConversion("0.0.0.1", BigInteger.ONE);
751     checkBigIntegerConversion("127.255.255.255", BigInteger.valueOf(Integer.MAX_VALUE));
752     checkBigIntegerConversion(
753         "255.255.255.254", BigInteger.valueOf(Integer.MAX_VALUE).multiply(BigInteger.valueOf(2)));
754     checkBigIntegerConversion(
755         "255.255.255.255", BigInteger.ONE.shiftLeft(32).subtract(BigInteger.ONE));
756   }
757 
testFromIpv6BigIntegerValid()758   public void testFromIpv6BigIntegerValid() {
759     checkBigIntegerConversion("::", BigInteger.ZERO);
760     checkBigIntegerConversion("::1", BigInteger.ONE);
761     checkBigIntegerConversion("::7fff:ffff", BigInteger.valueOf(Integer.MAX_VALUE));
762     checkBigIntegerConversion("::7fff:ffff:ffff:ffff", BigInteger.valueOf(Long.MAX_VALUE));
763     checkBigIntegerConversion(
764         "::ffff:ffff:ffff:ffff", BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE));
765     checkBigIntegerConversion(
766         "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
767         BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE));
768   }
769 
testFromIpv4BigIntegerInputTooLarge()770   public void testFromIpv4BigIntegerInputTooLarge() {
771     IllegalArgumentException expected =
772         assertThrows(
773             IllegalArgumentException.class,
774             () ->
775                 InetAddresses.fromIPv4BigInteger(BigInteger.ONE.shiftLeft(32).add(BigInteger.ONE)));
776     assertEquals(
777         "BigInteger cannot be converted to InetAddress because it has more than 4 bytes:"
778             + " 4294967297",
779         expected.getMessage());
780   }
781 
testFromIpv6BigIntegerInputTooLarge()782   public void testFromIpv6BigIntegerInputTooLarge() {
783     IllegalArgumentException expected =
784         assertThrows(
785             IllegalArgumentException.class,
786             () ->
787                 InetAddresses.fromIPv6BigInteger(
788                     BigInteger.ONE.shiftLeft(128).add(BigInteger.ONE)));
789     assertEquals(
790         "BigInteger cannot be converted to InetAddress because it has more than 16 bytes:"
791             + " 340282366920938463463374607431768211457",
792         expected.getMessage());
793   }
794 
795   /** Checks that the IP converts to the big integer and the big integer converts to the IP. */
checkBigIntegerConversion(String ip, BigInteger bigIntegerIp)796   private static void checkBigIntegerConversion(String ip, BigInteger bigIntegerIp) {
797     InetAddress address = InetAddresses.forString(ip);
798     boolean isIpv6 = address instanceof Inet6Address;
799     assertEquals(bigIntegerIp, InetAddresses.toBigInteger(address));
800     assertEquals(
801         address,
802         isIpv6
803             ? InetAddresses.fromIPv6BigInteger(bigIntegerIp)
804             : InetAddresses.fromIPv4BigInteger(bigIntegerIp));
805   }
806 }
807