blob: 3cc0e368d3812954aae0422ef18d7e1cadc93514 [file] [log] [blame]
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +09001/*
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
17package android.net;
18
Hugo Benichi207b7572016-11-10 22:45:56 +090019import static org.junit.Assert.assertArrayEquals;
20import static org.junit.Assert.assertEquals;
Hugo Benichi3054e102017-08-08 13:06:04 +090021import static org.junit.Assert.assertFalse;
22import static org.junit.Assert.assertNotEquals;
23import static org.junit.Assert.assertNotNull;
24import static org.junit.Assert.assertTrue;
25import static org.junit.Assert.fail;
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +090026
Hugo Benichi3054e102017-08-08 13:06:04 +090027import android.os.Parcel;
Brett Chabotab11bf12019-03-04 14:14:56 -080028
29import androidx.test.filters.SmallTest;
30import androidx.test.runner.AndroidJUnit4;
31
32import org.junit.Test;
33import org.junit.runner.RunWith;
Hugo Benichi3054e102017-08-08 13:06:04 +090034
35import java.net.InetAddress;
36import java.util.Random;
37
Hugo Benichi3054e102017-08-08 13:06:04 +090038@RunWith(AndroidJUnit4.class)
39@SmallTest
40public class IpPrefixTest {
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +090041
Erik Kline8a100e32015-04-13 15:33:34 +090042 private static InetAddress Address(String addr) {
43 return InetAddress.parseNumericAddress(addr);
44 }
45
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +090046 // Explicitly cast everything to byte because "error: possible loss of precision".
47 private static final byte[] IPV4_BYTES = { (byte) 192, (byte) 0, (byte) 2, (byte) 4};
48 private static final byte[] IPV6_BYTES = {
49 (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
50 (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef,
51 (byte) 0x0f, (byte) 0x00, (byte) 0x00, (byte) 0x00,
52 (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xa0
53 };
54
Hugo Benichi3054e102017-08-08 13:06:04 +090055 @Test
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +090056 public void testConstructor() {
57 IpPrefix p;
58 try {
59 p = new IpPrefix((byte[]) null, 9);
60 fail("Expected NullPointerException: null byte array");
61 } catch(RuntimeException expected) {}
62
63 try {
64 p = new IpPrefix((InetAddress) null, 10);
65 fail("Expected NullPointerException: null InetAddress");
66 } catch(RuntimeException expected) {}
67
68 try {
69 p = new IpPrefix((String) null);
70 fail("Expected NullPointerException: null String");
71 } catch(RuntimeException expected) {}
72
73
74 try {
75 byte[] b2 = {1, 2, 3, 4, 5};
76 p = new IpPrefix(b2, 29);
77 fail("Expected IllegalArgumentException: invalid array length");
78 } catch(IllegalArgumentException expected) {}
79
80 try {
81 p = new IpPrefix("1.2.3.4");
82 fail("Expected IllegalArgumentException: no prefix length");
83 } catch(IllegalArgumentException expected) {}
84
85 try {
86 p = new IpPrefix("1.2.3.4/");
87 fail("Expected IllegalArgumentException: empty prefix length");
88 } catch(IllegalArgumentException expected) {}
89
90 try {
91 p = new IpPrefix("foo/32");
92 fail("Expected IllegalArgumentException: invalid address");
93 } catch(IllegalArgumentException expected) {}
94
95 try {
96 p = new IpPrefix("1/32");
97 fail("Expected IllegalArgumentException: deprecated IPv4 format");
98 } catch(IllegalArgumentException expected) {}
99
100 try {
101 p = new IpPrefix("1.2.3.256/32");
102 fail("Expected IllegalArgumentException: invalid IPv4 address");
103 } catch(IllegalArgumentException expected) {}
104
105 try {
106 p = new IpPrefix("foo/32");
107 fail("Expected IllegalArgumentException: non-address");
108 } catch(IllegalArgumentException expected) {}
109
110 try {
111 p = new IpPrefix("f00:::/32");
112 fail("Expected IllegalArgumentException: invalid IPv6 address");
113 } catch(IllegalArgumentException expected) {}
114 }
115
Hugo Benichi3054e102017-08-08 13:06:04 +0900116 @Test
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900117 public void testTruncation() {
118 IpPrefix p;
119
120 p = new IpPrefix(IPV4_BYTES, 32);
121 assertEquals("192.0.2.4/32", p.toString());
122
123 p = new IpPrefix(IPV4_BYTES, 29);
124 assertEquals("192.0.2.0/29", p.toString());
125
126 p = new IpPrefix(IPV4_BYTES, 8);
127 assertEquals("192.0.0.0/8", p.toString());
128
129 p = new IpPrefix(IPV4_BYTES, 0);
130 assertEquals("0.0.0.0/0", p.toString());
131
132 try {
133 p = new IpPrefix(IPV4_BYTES, 33);
134 fail("Expected IllegalArgumentException: invalid prefix length");
135 } catch(RuntimeException expected) {}
136
137 try {
138 p = new IpPrefix(IPV4_BYTES, 128);
139 fail("Expected IllegalArgumentException: invalid prefix length");
140 } catch(RuntimeException expected) {}
141
142 try {
143 p = new IpPrefix(IPV4_BYTES, -1);
144 fail("Expected IllegalArgumentException: negative prefix length");
145 } catch(RuntimeException expected) {}
146
147 p = new IpPrefix(IPV6_BYTES, 128);
148 assertEquals("2001:db8:dead:beef:f00::a0/128", p.toString());
149
150 p = new IpPrefix(IPV6_BYTES, 122);
151 assertEquals("2001:db8:dead:beef:f00::80/122", p.toString());
152
153 p = new IpPrefix(IPV6_BYTES, 64);
154 assertEquals("2001:db8:dead:beef::/64", p.toString());
155
156 p = new IpPrefix(IPV6_BYTES, 3);
157 assertEquals("2000::/3", p.toString());
158
159 p = new IpPrefix(IPV6_BYTES, 0);
160 assertEquals("::/0", p.toString());
161
162 try {
163 p = new IpPrefix(IPV6_BYTES, -1);
164 fail("Expected IllegalArgumentException: negative prefix length");
165 } catch(RuntimeException expected) {}
166
167 try {
168 p = new IpPrefix(IPV6_BYTES, 129);
169 fail("Expected IllegalArgumentException: negative prefix length");
170 } catch(RuntimeException expected) {}
171
172 }
173
174 private void assertAreEqual(Object o1, Object o2) {
175 assertTrue(o1.equals(o2));
176 assertTrue(o2.equals(o1));
177 }
178
179 private void assertAreNotEqual(Object o1, Object o2) {
180 assertFalse(o1.equals(o2));
181 assertFalse(o2.equals(o1));
182 }
183
Hugo Benichi3054e102017-08-08 13:06:04 +0900184 @Test
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900185 public void testEquals() {
186 IpPrefix p1, p2;
187
188 p1 = new IpPrefix("192.0.2.251/23");
189 p2 = new IpPrefix(new byte[]{(byte) 192, (byte) 0, (byte) 2, (byte) 251}, 23);
190 assertAreEqual(p1, p2);
191
192 p1 = new IpPrefix("192.0.2.5/23");
193 assertAreEqual(p1, p2);
194
195 p1 = new IpPrefix("192.0.2.5/24");
196 assertAreNotEqual(p1, p2);
197
198 p1 = new IpPrefix("192.0.4.5/23");
199 assertAreNotEqual(p1, p2);
200
201
202 p1 = new IpPrefix("2001:db8:dead:beef:f00::80/122");
203 p2 = new IpPrefix(IPV6_BYTES, 122);
204 assertEquals("2001:db8:dead:beef:f00::80/122", p2.toString());
205 assertAreEqual(p1, p2);
206
207 p1 = new IpPrefix("2001:db8:dead:beef:f00::bf/122");
208 assertAreEqual(p1, p2);
209
210 p1 = new IpPrefix("2001:db8:dead:beef:f00::8:0/123");
211 assertAreNotEqual(p1, p2);
212
213 p1 = new IpPrefix("2001:db8:dead:beef::/122");
214 assertAreNotEqual(p1, p2);
215
216 // 192.0.2.4/32 != c000:0204::/32.
217 byte[] ipv6bytes = new byte[16];
218 System.arraycopy(IPV4_BYTES, 0, ipv6bytes, 0, IPV4_BYTES.length);
219 p1 = new IpPrefix(ipv6bytes, 32);
220 assertAreEqual(p1, new IpPrefix("c000:0204::/32"));
221
222 p2 = new IpPrefix(IPV4_BYTES, 32);
223 assertAreNotEqual(p1, p2);
224 }
225
Hugo Benichi3054e102017-08-08 13:06:04 +0900226 @Test
Chalard Jean687546e2018-02-26 11:52:46 +0900227 public void testContainsInetAddress() {
Erik Kline8a100e32015-04-13 15:33:34 +0900228 IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127");
229 assertTrue(p.contains(Address("2001:db8:f00::ace:d00c")));
230 assertTrue(p.contains(Address("2001:db8:f00::ace:d00d")));
231 assertFalse(p.contains(Address("2001:db8:f00::ace:d00e")));
232 assertFalse(p.contains(Address("2001:db8:f00::bad:d00d")));
233 assertFalse(p.contains(Address("2001:4868:4860::8888")));
Chalard Jean687546e2018-02-26 11:52:46 +0900234 assertFalse(p.contains((InetAddress)null));
Erik Kline8a100e32015-04-13 15:33:34 +0900235 assertFalse(p.contains(Address("8.8.8.8")));
236
237 p = new IpPrefix("192.0.2.0/23");
238 assertTrue(p.contains(Address("192.0.2.43")));
239 assertTrue(p.contains(Address("192.0.3.21")));
240 assertFalse(p.contains(Address("192.0.0.21")));
241 assertFalse(p.contains(Address("8.8.8.8")));
242 assertFalse(p.contains(Address("2001:4868:4860::8888")));
243
244 IpPrefix ipv6Default = new IpPrefix("::/0");
245 assertTrue(ipv6Default.contains(Address("2001:db8::f00")));
246 assertFalse(ipv6Default.contains(Address("192.0.2.1")));
247
248 IpPrefix ipv4Default = new IpPrefix("0.0.0.0/0");
249 assertTrue(ipv4Default.contains(Address("255.255.255.255")));
250 assertTrue(ipv4Default.contains(Address("192.0.2.1")));
251 assertFalse(ipv4Default.contains(Address("2001:db8::f00")));
252 }
253
Hugo Benichi3054e102017-08-08 13:06:04 +0900254 @Test
Chalard Jean687546e2018-02-26 11:52:46 +0900255 public void testContainsIpPrefix() {
256 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("0.0.0.0/0")));
257 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/0")));
258 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/8")));
259 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/24")));
260 assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/23")));
261
262 assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.2.3.4/8")));
263 assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.254.12.9/8")));
264 assertTrue(new IpPrefix("1.2.3.4/21").containsPrefix(new IpPrefix("1.2.3.4/21")));
265 assertTrue(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.4/32")));
266
267 assertTrue(new IpPrefix("1.2.3.4/20").containsPrefix(new IpPrefix("1.2.3.0/24")));
268
269 assertFalse(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.5/32")));
270 assertFalse(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("2.2.3.4/8")));
271 assertFalse(new IpPrefix("0.0.0.0/16").containsPrefix(new IpPrefix("0.0.0.0/15")));
272 assertFalse(new IpPrefix("100.0.0.0/8").containsPrefix(new IpPrefix("99.0.0.0/8")));
273
274 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("::/0")));
275 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/1")));
276 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("3d8a:661:a0::770/8")));
277 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/8")));
278 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/64")));
279 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/113")));
280 assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/128")));
281
282 assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
283 new IpPrefix("2001:db8:f00::ace:d00d/64")));
284 assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
285 new IpPrefix("2001:db8:f00::ace:d00d/120")));
286 assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
287 new IpPrefix("2001:db8:f00::ace:d00d/32")));
288 assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
289 new IpPrefix("2006:db8:f00::ace:d00d/96")));
290
291 assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
292 new IpPrefix("2001:db8:f00::ace:d00d/128")));
293 assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/100").containsPrefix(
294 new IpPrefix("2001:db8:f00::ace:ccaf/110")));
295
296 assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
297 new IpPrefix("2001:db8:f00::ace:d00e/128")));
298 assertFalse(new IpPrefix("::/30").containsPrefix(new IpPrefix("::/29")));
299 }
300
301 @Test
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900302 public void testHashCode() {
Hugo Benichi207b7572016-11-10 22:45:56 +0900303 IpPrefix p = new IpPrefix(new byte[4], 0);
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900304 Random random = new Random();
305 for (int i = 0; i < 100; i++) {
Hugo Benichi207b7572016-11-10 22:45:56 +0900306 final IpPrefix oldP = p;
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900307 if (random.nextBoolean()) {
308 // IPv4.
309 byte[] b = new byte[4];
310 random.nextBytes(b);
311 p = new IpPrefix(b, random.nextInt(33));
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900312 } else {
313 // IPv6.
314 byte[] b = new byte[16];
315 random.nextBytes(b);
316 p = new IpPrefix(b, random.nextInt(129));
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900317 }
Hugo Benichi207b7572016-11-10 22:45:56 +0900318 if (p.equals(oldP)) {
319 assertEquals(p.hashCode(), oldP.hashCode());
320 }
321 if (p.hashCode() != oldP.hashCode()) {
Hugo Benichi3054e102017-08-08 13:06:04 +0900322 assertNotEquals(p, oldP);
Hugo Benichi207b7572016-11-10 22:45:56 +0900323 }
324 }
325 }
326
Hugo Benichi3054e102017-08-08 13:06:04 +0900327 @Test
Hugo Benichi207b7572016-11-10 22:45:56 +0900328 public void testHashCodeIsNotConstant() {
329 IpPrefix[] prefixes = {
330 new IpPrefix("2001:db8:f00::ace:d00d/127"),
331 new IpPrefix("192.0.2.0/23"),
332 new IpPrefix("::/0"),
333 new IpPrefix("0.0.0.0/0"),
334 };
335 for (int i = 0; i < prefixes.length; i++) {
336 for (int j = i + 1; j < prefixes.length; j++) {
Hugo Benichi3054e102017-08-08 13:06:04 +0900337 assertNotEquals(prefixes[i].hashCode(), prefixes[j].hashCode());
Hugo Benichi207b7572016-11-10 22:45:56 +0900338 }
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900339 }
340 }
341
Hugo Benichi3054e102017-08-08 13:06:04 +0900342 @Test
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900343 public void testMappedAddressesAreBroken() {
344 // 192.0.2.0/24 != ::ffff:c000:0204/120, but because we use InetAddress,
345 // we are unable to comprehend that.
346 byte[] ipv6bytes = {
347 (byte) 0, (byte) 0, (byte) 0, (byte) 0,
348 (byte) 0, (byte) 0, (byte) 0, (byte) 0,
349 (byte) 0, (byte) 0, (byte) 0xff, (byte) 0xff,
350 (byte) 192, (byte) 0, (byte) 2, (byte) 0};
351 IpPrefix p = new IpPrefix(ipv6bytes, 120);
352 assertEquals(16, p.getRawAddress().length); // Fine.
353 assertArrayEquals(ipv6bytes, p.getRawAddress()); // Fine.
354
355 // Broken.
356 assertEquals("192.0.2.0/120", p.toString());
357 assertEquals(InetAddress.parseNumericAddress("192.0.2.0"), p.getAddress());
358 }
359
360 public IpPrefix passThroughParcel(IpPrefix p) {
361 Parcel parcel = Parcel.obtain();
362 IpPrefix p2 = null;
363 try {
364 p.writeToParcel(parcel, 0);
365 parcel.setDataPosition(0);
366 p2 = IpPrefix.CREATOR.createFromParcel(parcel);
367 } finally {
368 parcel.recycle();
369 }
370 assertNotNull(p2);
371 return p2;
372 }
373
374 public void assertParcelingIsLossless(IpPrefix p) {
375 IpPrefix p2 = passThroughParcel(p);
376 assertEquals(p, p2);
377 }
378
Hugo Benichi3054e102017-08-08 13:06:04 +0900379 @Test
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900380 public void testParceling() {
381 IpPrefix p;
382
383 p = new IpPrefix("2001:4860:db8::/64");
384 assertParcelingIsLossless(p);
Hugo Benichi3054e102017-08-08 13:06:04 +0900385 assertTrue(p.isIPv6());
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900386
387 p = new IpPrefix("192.0.2.0/25");
388 assertParcelingIsLossless(p);
Hugo Benichi3054e102017-08-08 13:06:04 +0900389 assertTrue(p.isIPv4());
Lorenzo Colitti2e9b1232014-06-12 13:41:17 +0900390 }
391}