IpPrefixTest.java revision 8c6c2c3c929acad783b9a56b8d9efa597d0ae609
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
17package android.net;
18
19import android.net.IpPrefix;
20import android.os.Parcel;
21import static android.test.MoreAsserts.assertNotEqual;
22import android.test.suitebuilder.annotation.SmallTest;
23
24import static org.junit.Assert.assertArrayEquals;
25import java.net.InetAddress;
26import java.util.Random;
27import junit.framework.TestCase;
28
29
30public class IpPrefixTest extends TestCase {
31
32    // Explicitly cast everything to byte because "error: possible loss of precision".
33    private static final byte[] IPV4_BYTES = { (byte) 192, (byte) 0, (byte) 2, (byte) 4};
34    private static final byte[] IPV6_BYTES = {
35        (byte) 0x20, (byte) 0x01, (byte) 0x0d, (byte) 0xb8,
36        (byte) 0xde, (byte) 0xad, (byte) 0xbe, (byte) 0xef,
37        (byte) 0x0f, (byte) 0x00, (byte) 0x00, (byte) 0x00,
38        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xa0
39    };
40
41    @SmallTest
42    public void testConstructor() {
43        IpPrefix p;
44        try {
45            p = new IpPrefix((byte[]) null, 9);
46            fail("Expected NullPointerException: null byte array");
47        } catch(RuntimeException expected) {}
48
49        try {
50            p = new IpPrefix((InetAddress) null, 10);
51            fail("Expected NullPointerException: null InetAddress");
52        } catch(RuntimeException expected) {}
53
54        try {
55            p = new IpPrefix((String) null);
56            fail("Expected NullPointerException: null String");
57        } catch(RuntimeException expected) {}
58
59
60        try {
61            byte[] b2 = {1, 2, 3, 4, 5};
62            p = new IpPrefix(b2, 29);
63            fail("Expected IllegalArgumentException: invalid array length");
64        } catch(IllegalArgumentException expected) {}
65
66        try {
67            p = new IpPrefix("1.2.3.4");
68            fail("Expected IllegalArgumentException: no prefix length");
69        } catch(IllegalArgumentException expected) {}
70
71        try {
72            p = new IpPrefix("1.2.3.4/");
73            fail("Expected IllegalArgumentException: empty prefix length");
74        } catch(IllegalArgumentException expected) {}
75
76        try {
77            p = new IpPrefix("foo/32");
78            fail("Expected IllegalArgumentException: invalid address");
79        } catch(IllegalArgumentException expected) {}
80
81        try {
82            p = new IpPrefix("1/32");
83            fail("Expected IllegalArgumentException: deprecated IPv4 format");
84        } catch(IllegalArgumentException expected) {}
85
86        try {
87            p = new IpPrefix("1.2.3.256/32");
88            fail("Expected IllegalArgumentException: invalid IPv4 address");
89        } catch(IllegalArgumentException expected) {}
90
91        try {
92            p = new IpPrefix("foo/32");
93            fail("Expected IllegalArgumentException: non-address");
94        } catch(IllegalArgumentException expected) {}
95
96        try {
97            p = new IpPrefix("f00:::/32");
98            fail("Expected IllegalArgumentException: invalid IPv6 address");
99        } catch(IllegalArgumentException expected) {}
100    }
101
102    public void testTruncation() {
103        IpPrefix p;
104
105        p = new IpPrefix(IPV4_BYTES, 32);
106        assertEquals("192.0.2.4/32", p.toString());
107
108        p = new IpPrefix(IPV4_BYTES, 29);
109        assertEquals("192.0.2.0/29", p.toString());
110
111        p = new IpPrefix(IPV4_BYTES, 8);
112        assertEquals("192.0.0.0/8", p.toString());
113
114        p = new IpPrefix(IPV4_BYTES, 0);
115        assertEquals("0.0.0.0/0", p.toString());
116
117        try {
118            p = new IpPrefix(IPV4_BYTES, 33);
119            fail("Expected IllegalArgumentException: invalid prefix length");
120        } catch(RuntimeException expected) {}
121
122        try {
123            p = new IpPrefix(IPV4_BYTES, 128);
124            fail("Expected IllegalArgumentException: invalid prefix length");
125        } catch(RuntimeException expected) {}
126
127        try {
128            p = new IpPrefix(IPV4_BYTES, -1);
129            fail("Expected IllegalArgumentException: negative prefix length");
130        } catch(RuntimeException expected) {}
131
132        p = new IpPrefix(IPV6_BYTES, 128);
133        assertEquals("2001:db8:dead:beef:f00::a0/128", p.toString());
134
135        p = new IpPrefix(IPV6_BYTES, 122);
136        assertEquals("2001:db8:dead:beef:f00::80/122", p.toString());
137
138        p = new IpPrefix(IPV6_BYTES, 64);
139        assertEquals("2001:db8:dead:beef::/64", p.toString());
140
141        p = new IpPrefix(IPV6_BYTES, 3);
142        assertEquals("2000::/3", p.toString());
143
144        p = new IpPrefix(IPV6_BYTES, 0);
145        assertEquals("::/0", p.toString());
146
147        try {
148            p = new IpPrefix(IPV6_BYTES, -1);
149            fail("Expected IllegalArgumentException: negative prefix length");
150        } catch(RuntimeException expected) {}
151
152        try {
153            p = new IpPrefix(IPV6_BYTES, 129);
154            fail("Expected IllegalArgumentException: negative prefix length");
155        } catch(RuntimeException expected) {}
156
157    }
158
159    private void assertAreEqual(Object o1, Object o2) {
160        assertTrue(o1.equals(o2));
161        assertTrue(o2.equals(o1));
162    }
163
164    private void assertAreNotEqual(Object o1, Object o2) {
165        assertFalse(o1.equals(o2));
166        assertFalse(o2.equals(o1));
167    }
168
169    @SmallTest
170    public void testEquals() {
171        IpPrefix p1, p2;
172
173        p1 = new IpPrefix("192.0.2.251/23");
174        p2 = new IpPrefix(new byte[]{(byte) 192, (byte) 0, (byte) 2, (byte) 251}, 23);
175        assertAreEqual(p1, p2);
176
177        p1 = new IpPrefix("192.0.2.5/23");
178        assertAreEqual(p1, p2);
179
180        p1 = new IpPrefix("192.0.2.5/24");
181        assertAreNotEqual(p1, p2);
182
183        p1 = new IpPrefix("192.0.4.5/23");
184        assertAreNotEqual(p1, p2);
185
186
187        p1 = new IpPrefix("2001:db8:dead:beef:f00::80/122");
188        p2 = new IpPrefix(IPV6_BYTES, 122);
189        assertEquals("2001:db8:dead:beef:f00::80/122", p2.toString());
190        assertAreEqual(p1, p2);
191
192        p1 = new IpPrefix("2001:db8:dead:beef:f00::bf/122");
193        assertAreEqual(p1, p2);
194
195        p1 = new IpPrefix("2001:db8:dead:beef:f00::8:0/123");
196        assertAreNotEqual(p1, p2);
197
198        p1 = new IpPrefix("2001:db8:dead:beef::/122");
199        assertAreNotEqual(p1, p2);
200
201        // 192.0.2.4/32 != c000:0204::/32.
202        byte[] ipv6bytes = new byte[16];
203        System.arraycopy(IPV4_BYTES, 0, ipv6bytes, 0, IPV4_BYTES.length);
204        p1 = new IpPrefix(ipv6bytes, 32);
205        assertAreEqual(p1, new IpPrefix("c000:0204::/32"));
206
207        p2 = new IpPrefix(IPV4_BYTES, 32);
208        assertAreNotEqual(p1, p2);
209    }
210
211    @SmallTest
212    public void testHashCode() {
213        IpPrefix p;
214        int oldCode = -1;
215        Random random = new Random();
216        for (int i = 0; i < 100; i++) {
217            if (random.nextBoolean()) {
218                // IPv4.
219                byte[] b = new byte[4];
220                random.nextBytes(b);
221                p = new IpPrefix(b, random.nextInt(33));
222                assertNotEqual(oldCode, p.hashCode());
223                oldCode = p.hashCode();
224            } else {
225                // IPv6.
226                byte[] b = new byte[16];
227                random.nextBytes(b);
228                p = new IpPrefix(b, random.nextInt(129));
229                assertNotEqual(oldCode, p.hashCode());
230                oldCode = p.hashCode();
231            }
232        }
233    }
234
235    @SmallTest
236    public void testMappedAddressesAreBroken() {
237        // 192.0.2.0/24 != ::ffff:c000:0204/120, but because we use InetAddress,
238        // we are unable to comprehend that.
239        byte[] ipv6bytes = {
240            (byte) 0, (byte) 0, (byte) 0, (byte) 0,
241            (byte) 0, (byte) 0, (byte) 0, (byte) 0,
242            (byte) 0, (byte) 0, (byte) 0xff, (byte) 0xff,
243            (byte) 192, (byte) 0, (byte) 2, (byte) 0};
244        IpPrefix p = new IpPrefix(ipv6bytes, 120);
245        assertEquals(16, p.getRawAddress().length);       // Fine.
246        assertArrayEquals(ipv6bytes, p.getRawAddress());  // Fine.
247
248        // Broken.
249        assertEquals("192.0.2.0/120", p.toString());
250        assertEquals(InetAddress.parseNumericAddress("192.0.2.0"), p.getAddress());
251    }
252
253    public IpPrefix passThroughParcel(IpPrefix p) {
254        Parcel parcel = Parcel.obtain();
255        IpPrefix p2 = null;
256        try {
257            p.writeToParcel(parcel, 0);
258            parcel.setDataPosition(0);
259            p2 = IpPrefix.CREATOR.createFromParcel(parcel);
260        } finally {
261            parcel.recycle();
262        }
263        assertNotNull(p2);
264        return p2;
265    }
266
267    public void assertParcelingIsLossless(IpPrefix p) {
268      IpPrefix p2 = passThroughParcel(p);
269      assertEquals(p, p2);
270    }
271
272    public void testParceling() {
273        IpPrefix p;
274
275        p = new IpPrefix("2001:4860:db8::/64");
276        assertParcelingIsLossless(p);
277
278        p = new IpPrefix("192.0.2.0/25");
279        assertParcelingIsLossless(p);
280    }
281}
282