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