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 android.net.IpPrefix; 20 import android.os.Parcel; 21 import static android.test.MoreAsserts.assertNotEqual; 22 import android.test.suitebuilder.annotation.SmallTest; 23 24 import static org.junit.Assert.assertArrayEquals; 25 import java.net.InetAddress; 26 import java.util.Random; 27 import junit.framework.TestCase; 28 29 30 public 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