• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 The Android Open Source Project
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 android.net;
18 
19 import static com.android.testutils.MiscAsserts.assertEqualBothWays;
20 import static com.android.testutils.MiscAsserts.assertNotEqualEitherWay;
21 import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
22 
23 import static org.junit.Assert.assertArrayEquals;
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertNotEquals;
27 import static org.junit.Assert.assertTrue;
28 import static org.junit.Assert.fail;
29 
30 import androidx.test.filters.SmallTest;
31 import androidx.test.runner.AndroidJUnit4;
32 
33 import com.android.testutils.ConnectivityModuleTest;
34 
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 
38 import java.net.InetAddress;
39 import java.util.Random;
40 
41 @RunWith(AndroidJUnit4.class)
42 @SmallTest
43 @ConnectivityModuleTest
44 public class IpPrefixTest {
45 
address(String addr)46     private static InetAddress address(String addr) {
47         return InetAddress.parseNumericAddress(addr);
48     }
49 
50     // Explicitly cast everything to byte because "error: possible loss of precision".
51     private static final byte[] IPV4_BYTES = { (byte) 192, (byte) 0, (byte) 2, (byte) 4};
52     private static final byte[] IPV6_BYTES = {
53         (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
54         (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef,
55         (byte) 0x0f, (byte) 0x00, (byte) 0x00, (byte) 0x00,
56         (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xa0
57     };
58 
59     @Test
testConstructor()60     public void testConstructor() {
61         IpPrefix p;
62         try {
63             p = new IpPrefix((byte[]) null, 9);
64             fail("Expected NullPointerException: null byte array");
65         } catch (RuntimeException expected) { }
66 
67         try {
68             p = new IpPrefix((InetAddress) null, 10);
69             fail("Expected NullPointerException: null InetAddress");
70         } catch (RuntimeException expected) { }
71 
72         try {
73             p = new IpPrefix((String) null);
74             fail("Expected NullPointerException: null String");
75         } catch (RuntimeException expected) { }
76 
77 
78         try {
79             byte[] b2 = {1, 2, 3, 4, 5};
80             p = new IpPrefix(b2, 29);
81             fail("Expected IllegalArgumentException: invalid array length");
82         } catch (IllegalArgumentException expected) { }
83 
84         try {
85             p = new IpPrefix("1.2.3.4");
86             fail("Expected IllegalArgumentException: no prefix length");
87         } catch (IllegalArgumentException expected) { }
88 
89         try {
90             p = new IpPrefix("1.2.3.4/");
91             fail("Expected IllegalArgumentException: empty prefix length");
92         } catch (IllegalArgumentException expected) { }
93 
94         try {
95             p = new IpPrefix("foo/32");
96             fail("Expected IllegalArgumentException: invalid address");
97         } catch (IllegalArgumentException expected) { }
98 
99         try {
100             p = new IpPrefix("1/32");
101             fail("Expected IllegalArgumentException: deprecated IPv4 format");
102         } catch (IllegalArgumentException expected) { }
103 
104         try {
105             p = new IpPrefix("1.2.3.256/32");
106             fail("Expected IllegalArgumentException: invalid IPv4 address");
107         } catch (IllegalArgumentException expected) { }
108 
109         try {
110             p = new IpPrefix("foo/32");
111             fail("Expected IllegalArgumentException: non-address");
112         } catch (IllegalArgumentException expected) { }
113 
114         try {
115             p = new IpPrefix("f00:::/32");
116             fail("Expected IllegalArgumentException: invalid IPv6 address");
117         } catch (IllegalArgumentException expected) { }
118 
119         p = new IpPrefix("/64");
120         assertEquals("::/64", p.toString());
121 
122         p = new IpPrefix("/128");
123         assertEquals("::1/128", p.toString());
124 
125         p = new IpPrefix("[2001:db8::123]/64");
126         assertEquals("2001:db8::/64", p.toString());
127 
128         p = new IpPrefix(InetAddresses.parseNumericAddress("::128"), 64);
129         assertEquals("::/64", p.toString());
130     }
131 
132     @Test
testTruncation()133     public void testTruncation() {
134         IpPrefix p;
135 
136         p = new IpPrefix(IPV4_BYTES, 32);
137         assertEquals("192.0.2.4/32", p.toString());
138 
139         p = new IpPrefix(IPV4_BYTES, 29);
140         assertEquals("192.0.2.0/29", p.toString());
141 
142         p = new IpPrefix(IPV4_BYTES, 8);
143         assertEquals("192.0.0.0/8", p.toString());
144 
145         p = new IpPrefix(IPV4_BYTES, 0);
146         assertEquals("0.0.0.0/0", p.toString());
147 
148         try {
149             p = new IpPrefix(IPV4_BYTES, 33);
150             fail("Expected IllegalArgumentException: invalid prefix length");
151         } catch (RuntimeException expected) { }
152 
153         try {
154             p = new IpPrefix(IPV4_BYTES, 128);
155             fail("Expected IllegalArgumentException: invalid prefix length");
156         } catch (RuntimeException expected) { }
157 
158         try {
159             p = new IpPrefix(IPV4_BYTES, -1);
160             fail("Expected IllegalArgumentException: negative prefix length");
161         } catch (RuntimeException expected) { }
162 
163         p = new IpPrefix(IPV6_BYTES, 128);
164         assertEquals("2001:db8:dead:beef:f00::a0/128", p.toString());
165 
166         p = new IpPrefix(IPV6_BYTES, 122);
167         assertEquals("2001:db8:dead:beef:f00::80/122", p.toString());
168 
169         p = new IpPrefix(IPV6_BYTES, 64);
170         assertEquals("2001:db8:dead:beef::/64", p.toString());
171 
172         p = new IpPrefix(IPV6_BYTES, 3);
173         assertEquals("2000::/3", p.toString());
174 
175         p = new IpPrefix(IPV6_BYTES, 0);
176         assertEquals("::/0", p.toString());
177 
178         try {
179             p = new IpPrefix(IPV6_BYTES, -1);
180             fail("Expected IllegalArgumentException: negative prefix length");
181         } catch (RuntimeException expected) { }
182 
183         try {
184             p = new IpPrefix(IPV6_BYTES, 129);
185             fail("Expected IllegalArgumentException: negative prefix length");
186         } catch (RuntimeException expected) { }
187 
188     }
189 
190     @Test
testEquals()191     public void testEquals() {
192         IpPrefix p1, p2;
193 
194         p1 = new IpPrefix("192.0.2.251/23");
195         p2 = new IpPrefix(new byte[]{(byte) 192, (byte) 0, (byte) 2, (byte) 251}, 23);
196         assertEqualBothWays(p1, p2);
197 
198         p1 = new IpPrefix("192.0.2.5/23");
199         assertEqualBothWays(p1, p2);
200 
201         p1 = new IpPrefix("192.0.2.5/24");
202         assertNotEqualEitherWay(p1, p2);
203 
204         p1 = new IpPrefix("192.0.4.5/23");
205         assertNotEqualEitherWay(p1, p2);
206 
207 
208         p1 = new IpPrefix("2001:db8:dead:beef:f00::80/122");
209         p2 = new IpPrefix(IPV6_BYTES, 122);
210         assertEquals("2001:db8:dead:beef:f00::80/122", p2.toString());
211         assertEqualBothWays(p1, p2);
212 
213         p1 = new IpPrefix("2001:db8:dead:beef:f00::bf/122");
214         assertEqualBothWays(p1, p2);
215 
216         p1 = new IpPrefix("2001:db8:dead:beef:f00::8:0/123");
217         assertNotEqualEitherWay(p1, p2);
218 
219         p1 = new IpPrefix("2001:db8:dead:beef::/122");
220         assertNotEqualEitherWay(p1, p2);
221 
222         // 192.0.2.4/32 != c000:0204::/32.
223         byte[] ipv6bytes = new byte[16];
224         System.arraycopy(IPV4_BYTES, 0, ipv6bytes, 0, IPV4_BYTES.length);
225         p1 = new IpPrefix(ipv6bytes, 32);
226         assertEqualBothWays(p1, new IpPrefix("c000:0204::/32"));
227 
228         p2 = new IpPrefix(IPV4_BYTES, 32);
229         assertNotEqualEitherWay(p1, p2);
230     }
231 
232     @Test
testContainsInetAddress()233     public void testContainsInetAddress() {
234         IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127");
235         assertTrue(p.contains(address("2001:db8:f00::ace:d00c")));
236         assertTrue(p.contains(address("2001:db8:f00::ace:d00d")));
237         assertFalse(p.contains(address("2001:db8:f00::ace:d00e")));
238         assertFalse(p.contains(address("2001:db8:f00::bad:d00d")));
239         assertFalse(p.contains(address("2001:4868:4860::8888")));
240         assertFalse(p.contains(address("8.8.8.8")));
241 
242         p = new IpPrefix("192.0.2.0/23");
243         assertTrue(p.contains(address("192.0.2.43")));
244         assertTrue(p.contains(address("192.0.3.21")));
245         assertFalse(p.contains(address("192.0.0.21")));
246         assertFalse(p.contains(address("8.8.8.8")));
247         assertFalse(p.contains(address("2001:4868:4860::8888")));
248 
249         IpPrefix ipv6Default = new IpPrefix("::/0");
250         assertTrue(ipv6Default.contains(address("2001:db8::f00")));
251         assertFalse(ipv6Default.contains(address("192.0.2.1")));
252 
253         IpPrefix ipv4Default = new IpPrefix("0.0.0.0/0");
254         assertTrue(ipv4Default.contains(address("255.255.255.255")));
255         assertTrue(ipv4Default.contains(address("192.0.2.1")));
256         assertFalse(ipv4Default.contains(address("2001:db8::f00")));
257     }
258 
259     @Test
testContainsIpPrefix()260     public void testContainsIpPrefix() {
261         assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("0.0.0.0/0")));
262         assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/0")));
263         assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/8")));
264         assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/24")));
265         assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/23")));
266 
267         assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.2.3.4/8")));
268         assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.254.12.9/8")));
269         assertTrue(new IpPrefix("1.2.3.4/21").containsPrefix(new IpPrefix("1.2.3.4/21")));
270         assertTrue(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.4/32")));
271 
272         assertTrue(new IpPrefix("1.2.3.4/20").containsPrefix(new IpPrefix("1.2.3.0/24")));
273 
274         assertFalse(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.5/32")));
275         assertFalse(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("2.2.3.4/8")));
276         assertFalse(new IpPrefix("0.0.0.0/16").containsPrefix(new IpPrefix("0.0.0.0/15")));
277         assertFalse(new IpPrefix("100.0.0.0/8").containsPrefix(new IpPrefix("99.0.0.0/8")));
278 
279         assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("::/0")));
280         assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/1")));
281         assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("3d8a:661:a0::770/8")));
282         assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/8")));
283         assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/64")));
284         assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/113")));
285         assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/128")));
286 
287         assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
288                 new IpPrefix("2001:db8:f00::ace:d00d/64")));
289         assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
290                 new IpPrefix("2001:db8:f00::ace:d00d/120")));
291         assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
292                 new IpPrefix("2001:db8:f00::ace:d00d/32")));
293         assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
294                 new IpPrefix("2006:db8:f00::ace:d00d/96")));
295 
296         assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
297                 new IpPrefix("2001:db8:f00::ace:d00d/128")));
298         assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/100").containsPrefix(
299                 new IpPrefix("2001:db8:f00::ace:ccaf/110")));
300 
301         assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
302                 new IpPrefix("2001:db8:f00::ace:d00e/128")));
303         assertFalse(new IpPrefix("::/30").containsPrefix(new IpPrefix("::/29")));
304     }
305 
306     @Test
testHashCode()307     public void testHashCode() {
308         IpPrefix p = new IpPrefix(new byte[4], 0);
309         Random random = new Random();
310         for (int i = 0; i < 100; i++) {
311             final IpPrefix oldP = p;
312             if (random.nextBoolean()) {
313                 // IPv4.
314                 byte[] b = new byte[4];
315                 random.nextBytes(b);
316                 p = new IpPrefix(b, random.nextInt(33));
317             } else {
318                 // IPv6.
319                 byte[] b = new byte[16];
320                 random.nextBytes(b);
321                 p = new IpPrefix(b, random.nextInt(129));
322             }
323             if (p.equals(oldP)) {
324                 assertEquals(p.hashCode(), oldP.hashCode());
325             }
326             if (p.hashCode() != oldP.hashCode()) {
327                 assertNotEquals(p, oldP);
328             }
329         }
330     }
331 
332     @Test
testHashCodeIsNotConstant()333     public void testHashCodeIsNotConstant() {
334         IpPrefix[] prefixes = {
335             new IpPrefix("2001:db8:f00::ace:d00d/127"),
336             new IpPrefix("192.0.2.0/23"),
337             new IpPrefix("::/0"),
338             new IpPrefix("0.0.0.0/0"),
339         };
340         for (int i = 0; i < prefixes.length; i++) {
341             for (int j = i + 1; j < prefixes.length; j++) {
342                 assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode());
343             }
344         }
345     }
346 
347     @Test
testMappedAddressesAreBroken()348     public void testMappedAddressesAreBroken() {
349         // 192.0.2.0/24 != ::ffff:c000:0204/120, but because we use InetAddress,
350         // we are unable to comprehend that.
351         byte[] ipv6bytes = {
352             (byte) 0, (byte) 0, (byte) 0, (byte) 0,
353             (byte) 0, (byte) 0, (byte) 0, (byte) 0,
354             (byte) 0, (byte) 0, (byte) 0xff, (byte) 0xff,
355             (byte) 192, (byte) 0, (byte) 2, (byte) 0};
356         IpPrefix p = new IpPrefix(ipv6bytes, 120);
357         assertEquals(16, p.getRawAddress().length);       // Fine.
358         assertArrayEquals(ipv6bytes, p.getRawAddress());  // Fine.
359 
360         // Broken.
361         assertEquals("192.0.2.0/120", p.toString());
362         assertEquals(InetAddress.parseNumericAddress("192.0.2.0"), p.getAddress());
363     }
364 
365     @Test
testParceling()366     public void testParceling() {
367         IpPrefix p;
368 
369         p = new IpPrefix("2001:4860:db8::/64");
370         assertParcelingIsLossless(p);
371         assertTrue(p.isIPv6());
372 
373         p = new IpPrefix("192.0.2.0/25");
374         assertParcelingIsLossless(p);
375         assertTrue(p.isIPv4());
376     }
377 }
378