LinkAddressTest.java revision 00a0fd650b7a31dffb88c229242bb04fa0b487a4
1/* 2 * Copyright (C) 2013 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 java.net.Inet4Address; 20import java.net.Inet6Address; 21import java.net.InetAddress; 22import java.net.InterfaceAddress; 23import java.net.NetworkInterface; 24import java.net.SocketException; 25import java.util.Arrays; 26import java.util.Collections; 27import java.util.Comparator; 28import java.util.List; 29 30import android.net.LinkAddress; 31import android.os.Parcel; 32import android.test.AndroidTestCase; 33import android.test.suitebuilder.annotation.SmallTest; 34 35import static android.system.OsConstants.IFA_F_DEPRECATED; 36import static android.system.OsConstants.IFA_F_PERMANENT; 37import static android.system.OsConstants.IFA_F_TENTATIVE; 38import static android.system.OsConstants.RT_SCOPE_HOST; 39import static android.system.OsConstants.RT_SCOPE_LINK; 40import static android.system.OsConstants.RT_SCOPE_SITE; 41import static android.system.OsConstants.RT_SCOPE_UNIVERSE; 42 43/** 44 * Tests for {@link LinkAddress}. 45 */ 46public class LinkAddressTest extends AndroidTestCase { 47 48 private static final String V4 = "192.0.2.1"; 49 private static final String V6 = "2001:db8::1"; 50 private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4); 51 private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6); 52 53 public void testConstructors() throws SocketException { 54 LinkAddress address; 55 56 // Valid addresses work as expected. 57 address = new LinkAddress(V4_ADDRESS, 25); 58 assertEquals(V4_ADDRESS, address.getAddress()); 59 assertEquals(25, address.getPrefixLength()); 60 assertEquals(0, address.getFlags()); 61 assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); 62 63 address = new LinkAddress(V6_ADDRESS, 127); 64 assertEquals(V6_ADDRESS, address.getAddress()); 65 assertEquals(127, address.getPrefixLength()); 66 assertEquals(0, address.getFlags()); 67 assertEquals(RT_SCOPE_UNIVERSE, address.getScope()); 68 69 // Nonsensical flags/scopes or combinations thereof are acceptable. 70 address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK); 71 assertEquals(V6_ADDRESS, address.getAddress()); 72 assertEquals(64, address.getPrefixLength()); 73 assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags()); 74 assertEquals(RT_SCOPE_LINK, address.getScope()); 75 76 address = new LinkAddress(V4 + "/23", 123, 456); 77 assertEquals(V4_ADDRESS, address.getAddress()); 78 assertEquals(23, address.getPrefixLength()); 79 assertEquals(123, address.getFlags()); 80 assertEquals(456, address.getScope()); 81 82 // InterfaceAddress doesn't have a constructor. Fetch some from an interface. 83 List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses(); 84 85 // We expect to find 127.0.0.1/8 and ::1/128, in any order. 86 LinkAddress ipv4Loopback, ipv6Loopback; 87 assertEquals(2, addrs.size()); 88 if (addrs.get(0).getAddress() instanceof Inet4Address) { 89 ipv4Loopback = new LinkAddress(addrs.get(0)); 90 ipv6Loopback = new LinkAddress(addrs.get(1)); 91 } else { 92 ipv4Loopback = new LinkAddress(addrs.get(1)); 93 ipv6Loopback = new LinkAddress(addrs.get(0)); 94 } 95 96 assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress()); 97 assertEquals(8, ipv4Loopback.getPrefixLength()); 98 99 assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress()); 100 assertEquals(128, ipv6Loopback.getPrefixLength()); 101 102 // Null addresses are rejected. 103 try { 104 address = new LinkAddress(null, 24); 105 fail("Null InetAddress should cause IllegalArgumentException"); 106 } catch(IllegalArgumentException expected) {} 107 108 try { 109 address = new LinkAddress((String) null, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); 110 fail("Null string should cause IllegalArgumentException"); 111 } catch(IllegalArgumentException expected) {} 112 113 try { 114 address = new LinkAddress((InterfaceAddress) null); 115 fail("Null string should cause NullPointerException"); 116 } catch(NullPointerException expected) {} 117 118 // Invalid prefix lengths are rejected. 119 try { 120 address = new LinkAddress(V4_ADDRESS, -1); 121 fail("Negative IPv4 prefix length should cause IllegalArgumentException"); 122 } catch(IllegalArgumentException expected) {} 123 124 try { 125 address = new LinkAddress(V6_ADDRESS, -1); 126 fail("Negative IPv6 prefix length should cause IllegalArgumentException"); 127 } catch(IllegalArgumentException expected) {} 128 129 try { 130 address = new LinkAddress(V4_ADDRESS, 33); 131 fail("/33 IPv4 prefix length should cause IllegalArgumentException"); 132 } catch(IllegalArgumentException expected) {} 133 134 try { 135 address = new LinkAddress(V4 + "/33", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); 136 fail("/33 IPv4 prefix length should cause IllegalArgumentException"); 137 } catch(IllegalArgumentException expected) {} 138 139 140 try { 141 address = new LinkAddress(V6_ADDRESS, 129, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); 142 fail("/129 IPv6 prefix length should cause IllegalArgumentException"); 143 } catch(IllegalArgumentException expected) {} 144 145 try { 146 address = new LinkAddress(V6 + "/129", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE); 147 fail("/129 IPv6 prefix length should cause IllegalArgumentException"); 148 } catch(IllegalArgumentException expected) {} 149 150 // Multicast addresses are rejected. 151 try { 152 address = new LinkAddress("224.0.0.2/32"); 153 fail("IPv4 multicast address should cause IllegalArgumentException"); 154 } catch(IllegalArgumentException expected) {} 155 156 try { 157 address = new LinkAddress("ff02::1/128"); 158 fail("IPv6 multicast address should cause IllegalArgumentException"); 159 } catch(IllegalArgumentException expected) {} 160 } 161 162 public void testAddressScopes() { 163 assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope()); 164 assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope()); 165 166 assertEquals(RT_SCOPE_LINK, new LinkAddress("::1/128").getScope()); 167 assertEquals(RT_SCOPE_LINK, new LinkAddress("127.0.0.5/8").getScope()); 168 assertEquals(RT_SCOPE_LINK, new LinkAddress("fe80::ace:d00d/64").getScope()); 169 assertEquals(RT_SCOPE_LINK, new LinkAddress("169.254.5.12/16").getScope()); 170 171 assertEquals(RT_SCOPE_SITE, new LinkAddress("fec0::dead/64").getScope()); 172 173 assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("10.1.2.3/21").getScope()); 174 assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("192.0.2.1/25").getScope()); 175 assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("2001:db8::/64").getScope()); 176 assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("5000::/127").getScope()); 177 } 178 179 private void assertIsSameAddressAs(LinkAddress l1, LinkAddress l2) { 180 assertTrue(l1 + " unexpectedly does not have same address as " + l2, 181 l1.isSameAddressAs(l2)); 182 assertTrue(l2 + " unexpectedly does not have same address as " + l1, 183 l2.isSameAddressAs(l1)); 184 } 185 186 private void assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2) { 187 assertFalse(l1 + " unexpectedly has same address as " + l2, 188 l1.isSameAddressAs(l2)); 189 assertFalse(l2 + " unexpectedly has same address as " + l1, 190 l1.isSameAddressAs(l2)); 191 } 192 193 private void assertLinkAddressesEqual(LinkAddress l1, LinkAddress l2) { 194 assertTrue(l1 + " unexpectedly not equal to " + l2, l1.equals(l2)); 195 assertTrue(l2 + " unexpectedly not equal to " + l1, l2.equals(l1)); 196 assertEquals(l1.hashCode(), l2.hashCode()); 197 } 198 199 private void assertLinkAddressesNotEqual(LinkAddress l1, LinkAddress l2) { 200 assertFalse(l1 + " unexpectedly equal to " + l2, l1.equals(l2)); 201 assertFalse(l2 + " unexpectedly equal to " + l1, l2.equals(l1)); 202 } 203 204 public void testEqualsAndSameAddressAs() { 205 LinkAddress l1, l2, l3; 206 207 l1 = new LinkAddress("2001:db8::1/64"); 208 l2 = new LinkAddress("2001:db8::1/64"); 209 assertLinkAddressesEqual(l1, l2); 210 assertIsSameAddressAs(l1, l2); 211 212 l2 = new LinkAddress("2001:db8::1/65"); 213 assertLinkAddressesNotEqual(l1, l2); 214 assertIsNotSameAddressAs(l1, l2); 215 216 l2 = new LinkAddress("2001:db8::2/64"); 217 assertLinkAddressesNotEqual(l1, l2); 218 assertIsNotSameAddressAs(l1, l2); 219 220 221 l1 = new LinkAddress("192.0.2.1/24"); 222 l2 = new LinkAddress("192.0.2.1/24"); 223 assertLinkAddressesEqual(l1, l2); 224 assertIsSameAddressAs(l1, l2); 225 226 l2 = new LinkAddress("192.0.2.1/23"); 227 assertLinkAddressesNotEqual(l1, l2); 228 assertIsNotSameAddressAs(l1, l2); 229 230 l2 = new LinkAddress("192.0.2.2/24"); 231 assertLinkAddressesNotEqual(l1, l2); 232 assertIsNotSameAddressAs(l1, l2); 233 234 235 // Check equals() and isSameAddressAs() on identical addresses with different flags. 236 l1 = new LinkAddress(V6_ADDRESS, 64); 237 l2 = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE); 238 assertLinkAddressesEqual(l1, l2); 239 assertIsSameAddressAs(l1, l2); 240 241 l2 = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_UNIVERSE); 242 assertLinkAddressesNotEqual(l1, l2); 243 assertIsSameAddressAs(l1, l2); 244 245 // Check equals() and isSameAddressAs() on identical addresses with different scope. 246 l1 = new LinkAddress(V4_ADDRESS, 24); 247 l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_UNIVERSE); 248 assertLinkAddressesEqual(l1, l2); 249 assertIsSameAddressAs(l1, l2); 250 251 l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_HOST); 252 assertLinkAddressesNotEqual(l1, l2); 253 assertIsSameAddressAs(l1, l2); 254 255 // Addresses with the same start or end bytes aren't equal between families. 256 l1 = new LinkAddress("32.1.13.184/24"); 257 l2 = new LinkAddress("2001:db8::1/24"); 258 l3 = new LinkAddress("::2001:db8/24"); 259 260 byte[] ipv4Bytes = l1.getAddress().getAddress(); 261 byte[] l2FirstIPv6Bytes = Arrays.copyOf(l2.getAddress().getAddress(), 4); 262 byte[] l3LastIPv6Bytes = Arrays.copyOfRange(l3.getAddress().getAddress(), 12, 16); 263 assertTrue(Arrays.equals(ipv4Bytes, l2FirstIPv6Bytes)); 264 assertTrue(Arrays.equals(ipv4Bytes, l3LastIPv6Bytes)); 265 266 assertLinkAddressesNotEqual(l1, l2); 267 assertIsNotSameAddressAs(l1, l2); 268 269 assertLinkAddressesNotEqual(l1, l3); 270 assertIsNotSameAddressAs(l1, l3); 271 272 // Because we use InetAddress, an IPv4 address is equal to its IPv4-mapped address. 273 // TODO: Investigate fixing this. 274 String addressString = V4 + "/24"; 275 l1 = new LinkAddress(addressString); 276 l2 = new LinkAddress("::ffff:" + addressString); 277 assertLinkAddressesEqual(l1, l2); 278 assertIsSameAddressAs(l1, l2); 279 } 280 281 public void testHashCode() { 282 LinkAddress l; 283 284 l = new LinkAddress(V4_ADDRESS, 23); 285 assertEquals(-982787, l.hashCode()); 286 287 l = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST); 288 assertEquals(-971865, l.hashCode()); 289 290 l = new LinkAddress(V4_ADDRESS, 27); 291 assertEquals(-982743, l.hashCode()); 292 293 l = new LinkAddress(V6_ADDRESS, 64); 294 assertEquals(1076522926, l.hashCode()); 295 296 l = new LinkAddress(V6_ADDRESS, 128); 297 assertEquals(1076523630, l.hashCode()); 298 299 l = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE); 300 assertEquals(1076524846, l.hashCode()); 301 } 302 303 private LinkAddress passThroughParcel(LinkAddress l) { 304 Parcel p = Parcel.obtain(); 305 LinkAddress l2 = null; 306 try { 307 l.writeToParcel(p, 0); 308 p.setDataPosition(0); 309 l2 = LinkAddress.CREATOR.createFromParcel(p); 310 } finally { 311 p.recycle(); 312 } 313 assertNotNull(l2); 314 return l2; 315 } 316 317 private void assertParcelingIsLossless(LinkAddress l) { 318 LinkAddress l2 = passThroughParcel(l); 319 assertEquals(l, l2); 320 } 321 322 public void testParceling() { 323 LinkAddress l; 324 325 l = new LinkAddress(V6_ADDRESS, 64, 123, 456); 326 assertParcelingIsLossless(l); 327 328 l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK); 329 assertParcelingIsLossless(l); 330 } 331} 332