Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2010 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.net.LinkAddress;
     21 import android.net.LinkProperties;
     22 import android.net.LinkProperties.ProvisioningChange;
     23 import android.net.RouteInfo;
     24 import android.system.OsConstants;
     25 import android.test.suitebuilder.annotation.SmallTest;
     26 import android.test.suitebuilder.annotation.Suppress;
     27 import junit.framework.TestCase;
     28 
     29 import java.net.InetAddress;
     30 import java.util.ArrayList;
     31 
     32 
     33 public class LinkPropertiesTest extends TestCase {
     34     private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1");
     35     private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress(
     36             "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
     37     private static InetAddress DNS1 = NetworkUtils.numericToInetAddress("75.208.7.1");
     38     private static InetAddress DNS2 = NetworkUtils.numericToInetAddress("69.78.7.1");
     39     private static InetAddress DNS6 = NetworkUtils.numericToInetAddress("2001:4860:4860::8888");
     40     private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1");
     41     private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1");
     42     private static InetAddress GATEWAY61 = NetworkUtils.numericToInetAddress("fe80::6:0000:613");
     43     private static InetAddress GATEWAY62 = NetworkUtils.numericToInetAddress("fe80::6:2222");
     44     private static String NAME = "qmi0";
     45     private static int MTU = 1500;
     46 
     47     private static LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
     48     private static LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
     49     private static LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
     50 
     51     // TODO: replace all calls to NetworkUtils.numericToInetAddress with calls to this method.
     52     private InetAddress Address(String addrString) {
     53         return NetworkUtils.numericToInetAddress(addrString);
     54     }
     55 
     56     public void assertLinkPropertiesEqual(LinkProperties source, LinkProperties target) {
     57         // Check implementation of equals(), element by element.
     58         assertTrue(source.isIdenticalInterfaceName(target));
     59         assertTrue(target.isIdenticalInterfaceName(source));
     60 
     61         assertTrue(source.isIdenticalAddresses(target));
     62         assertTrue(target.isIdenticalAddresses(source));
     63 
     64         assertTrue(source.isIdenticalDnses(target));
     65         assertTrue(target.isIdenticalDnses(source));
     66 
     67         assertTrue(source.isIdenticalRoutes(target));
     68         assertTrue(target.isIdenticalRoutes(source));
     69 
     70         assertTrue(source.isIdenticalHttpProxy(target));
     71         assertTrue(target.isIdenticalHttpProxy(source));
     72 
     73         assertTrue(source.isIdenticalStackedLinks(target));
     74         assertTrue(target.isIdenticalStackedLinks(source));
     75 
     76         assertTrue(source.isIdenticalMtu(target));
     77         assertTrue(target.isIdenticalMtu(source));
     78 
     79         // Check result of equals().
     80         assertTrue(source.equals(target));
     81         assertTrue(target.equals(source));
     82 
     83         // Check hashCode.
     84         assertEquals(source.hashCode(), target.hashCode());
     85     }
     86 
     87     @SmallTest
     88     public void testEqualsNull() {
     89         LinkProperties source = new LinkProperties();
     90         LinkProperties target = new LinkProperties();
     91 
     92         assertFalse(source == target);
     93         assertLinkPropertiesEqual(source, target);
     94     }
     95 
     96     @SmallTest
     97     public void testEqualsSameOrder() {
     98         try {
     99             LinkProperties source = new LinkProperties();
    100             source.setInterfaceName(NAME);
    101             // set 2 link addresses
    102             source.addLinkAddress(LINKADDRV4);
    103             source.addLinkAddress(LINKADDRV6);
    104             // set 2 dnses
    105             source.addDnsServer(DNS1);
    106             source.addDnsServer(DNS2);
    107             // set 2 gateways
    108             source.addRoute(new RouteInfo(GATEWAY1));
    109             source.addRoute(new RouteInfo(GATEWAY2));
    110             source.setMtu(MTU);
    111 
    112             LinkProperties target = new LinkProperties();
    113 
    114             // All fields are same
    115             target.setInterfaceName(NAME);
    116             target.addLinkAddress(LINKADDRV4);
    117             target.addLinkAddress(LINKADDRV6);
    118             target.addDnsServer(DNS1);
    119             target.addDnsServer(DNS2);
    120             target.addRoute(new RouteInfo(GATEWAY1));
    121             target.addRoute(new RouteInfo(GATEWAY2));
    122             target.setMtu(MTU);
    123 
    124             assertLinkPropertiesEqual(source, target);
    125 
    126             target.clear();
    127             // change Interface Name
    128             target.setInterfaceName("qmi1");
    129             target.addLinkAddress(LINKADDRV4);
    130             target.addLinkAddress(LINKADDRV6);
    131             target.addDnsServer(DNS1);
    132             target.addDnsServer(DNS2);
    133             target.addRoute(new RouteInfo(GATEWAY1));
    134             target.addRoute(new RouteInfo(GATEWAY2));
    135             target.setMtu(MTU);
    136             assertFalse(source.equals(target));
    137 
    138             target.clear();
    139             target.setInterfaceName(NAME);
    140             // change link addresses
    141             target.addLinkAddress(new LinkAddress(
    142                     NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
    143             target.addLinkAddress(LINKADDRV6);
    144             target.addDnsServer(DNS1);
    145             target.addDnsServer(DNS2);
    146             target.addRoute(new RouteInfo(GATEWAY1));
    147             target.addRoute(new RouteInfo(GATEWAY2));
    148             target.setMtu(MTU);
    149             assertFalse(source.equals(target));
    150 
    151             target.clear();
    152             target.setInterfaceName(NAME);
    153             target.addLinkAddress(LINKADDRV4);
    154             target.addLinkAddress(LINKADDRV6);
    155             // change dnses
    156             target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
    157             target.addDnsServer(DNS2);
    158             target.addRoute(new RouteInfo(GATEWAY1));
    159             target.addRoute(new RouteInfo(GATEWAY2));
    160             target.setMtu(MTU);
    161             assertFalse(source.equals(target));
    162 
    163             target.clear();
    164             target.setInterfaceName(NAME);
    165             target.addLinkAddress(LINKADDRV4);
    166             target.addLinkAddress(LINKADDRV6);
    167             target.addDnsServer(DNS1);
    168             target.addDnsServer(DNS2);
    169             // change gateway
    170             target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
    171             target.addRoute(new RouteInfo(GATEWAY2));
    172             target.setMtu(MTU);
    173             assertFalse(source.equals(target));
    174 
    175             target.clear();
    176             target.setInterfaceName(NAME);
    177             target.addLinkAddress(LINKADDRV4);
    178             target.addLinkAddress(LINKADDRV6);
    179             target.addDnsServer(DNS1);
    180             target.addDnsServer(DNS2);
    181             target.addRoute(new RouteInfo(GATEWAY1));
    182             target.addRoute(new RouteInfo(GATEWAY2));
    183             // change mtu
    184             target.setMtu(1440);
    185             assertFalse(source.equals(target));
    186 
    187         } catch (Exception e) {
    188             throw new RuntimeException(e.toString());
    189             //fail();
    190         }
    191     }
    192 
    193     @SmallTest
    194     public void testEqualsDifferentOrder() {
    195         try {
    196             LinkProperties source = new LinkProperties();
    197             source.setInterfaceName(NAME);
    198             // set 2 link addresses
    199             source.addLinkAddress(LINKADDRV4);
    200             source.addLinkAddress(LINKADDRV6);
    201             // set 2 dnses
    202             source.addDnsServer(DNS1);
    203             source.addDnsServer(DNS2);
    204             // set 2 gateways
    205             source.addRoute(new RouteInfo(GATEWAY1));
    206             source.addRoute(new RouteInfo(GATEWAY2));
    207             source.setMtu(MTU);
    208 
    209             LinkProperties target = new LinkProperties();
    210             // Exchange order
    211             target.setInterfaceName(NAME);
    212             target.addLinkAddress(LINKADDRV6);
    213             target.addLinkAddress(LINKADDRV4);
    214             target.addDnsServer(DNS2);
    215             target.addDnsServer(DNS1);
    216             target.addRoute(new RouteInfo(GATEWAY2));
    217             target.addRoute(new RouteInfo(GATEWAY1));
    218             target.setMtu(MTU);
    219 
    220             assertLinkPropertiesEqual(source, target);
    221         } catch (Exception e) {
    222             fail();
    223         }
    224     }
    225 
    226     @SmallTest
    227     public void testEqualsDuplicated() {
    228         try {
    229             LinkProperties source = new LinkProperties();
    230             // set 3 link addresses, eg, [A, A, B]
    231             source.addLinkAddress(LINKADDRV4);
    232             source.addLinkAddress(LINKADDRV4);
    233             source.addLinkAddress(LINKADDRV6);
    234 
    235             LinkProperties target = new LinkProperties();
    236             // set 3 link addresses, eg, [A, B, B]
    237             target.addLinkAddress(LINKADDRV4);
    238             target.addLinkAddress(LINKADDRV6);
    239             target.addLinkAddress(LINKADDRV6);
    240 
    241             assertLinkPropertiesEqual(source, target);
    242         } catch (Exception e) {
    243             fail();
    244         }
    245     }
    246 
    247     private void assertAllRoutesHaveInterface(String iface, LinkProperties lp) {
    248         for (RouteInfo r : lp.getRoutes()) {
    249             assertEquals(iface, r.getInterface());
    250         }
    251     }
    252 
    253     @SmallTest
    254     public void testRouteInterfaces() {
    255         LinkAddress prefix = new LinkAddress(
    256             NetworkUtils.numericToInetAddress("2001:db8::"), 32);
    257         InetAddress address = ADDRV6;
    258 
    259         // Add a route with no interface to a LinkProperties with no interface. No errors.
    260         LinkProperties lp = new LinkProperties();
    261         RouteInfo r = new RouteInfo(prefix, address, null);
    262         assertTrue(lp.addRoute(r));
    263         assertEquals(1, lp.getRoutes().size());
    264         assertAllRoutesHaveInterface(null, lp);
    265 
    266         // Adding the same route twice has no effect.
    267         assertFalse(lp.addRoute(r));
    268         assertEquals(1, lp.getRoutes().size());
    269 
    270         // Add a route with an interface. Expect an exception.
    271         r = new RouteInfo(prefix, address, "wlan0");
    272         try {
    273           lp.addRoute(r);
    274           fail("Adding wlan0 route to LP with no interface, expect exception");
    275         } catch (IllegalArgumentException expected) {}
    276 
    277         // Change the interface name. All the routes should change their interface name too.
    278         lp.setInterfaceName("rmnet0");
    279         assertAllRoutesHaveInterface("rmnet0", lp);
    280 
    281         // Now add a route with the wrong interface. This causes an exception too.
    282         try {
    283           lp.addRoute(r);
    284           fail("Adding wlan0 route to rmnet0 LP, expect exception");
    285         } catch (IllegalArgumentException expected) {}
    286 
    287         // If the interface name matches, the route is added.
    288         r = new RouteInfo(prefix, null, "wlan0");
    289         lp.setInterfaceName("wlan0");
    290         lp.addRoute(r);
    291         assertEquals(2, lp.getRoutes().size());
    292         assertAllRoutesHaveInterface("wlan0", lp);
    293 
    294         // Routes with null interfaces are converted to wlan0.
    295         r = RouteInfo.makeHostRoute(ADDRV6, null);
    296         lp.addRoute(r);
    297         assertEquals(3, lp.getRoutes().size());
    298         assertAllRoutesHaveInterface("wlan0", lp);
    299 
    300         // Check comparisons work.
    301         LinkProperties lp2 = new LinkProperties(lp);
    302         assertAllRoutesHaveInterface("wlan0", lp);
    303         assertEquals(0, lp.compareAllRoutes(lp2).added.size());
    304         assertEquals(0, lp.compareAllRoutes(lp2).removed.size());
    305 
    306         lp2.setInterfaceName("p2p0");
    307         assertAllRoutesHaveInterface("p2p0", lp2);
    308         assertEquals(3, lp.compareAllRoutes(lp2).added.size());
    309         assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
    310     }
    311 
    312     @SmallTest
    313     public void testStackedInterfaces() {
    314         LinkProperties rmnet0 = new LinkProperties();
    315         rmnet0.setInterfaceName("rmnet0");
    316         rmnet0.addLinkAddress(LINKADDRV6);
    317 
    318         LinkProperties clat4 = new LinkProperties();
    319         clat4.setInterfaceName("clat4");
    320         clat4.addLinkAddress(LINKADDRV4);
    321 
    322         assertEquals(0, rmnet0.getStackedLinks().size());
    323         assertEquals(1, rmnet0.getAddresses().size());
    324         assertEquals(1, rmnet0.getLinkAddresses().size());
    325         assertEquals(1, rmnet0.getAllAddresses().size());
    326         assertEquals(1, rmnet0.getAllLinkAddresses().size());
    327 
    328         rmnet0.addStackedLink(clat4);
    329         assertEquals(1, rmnet0.getStackedLinks().size());
    330         assertEquals(1, rmnet0.getAddresses().size());
    331         assertEquals(1, rmnet0.getLinkAddresses().size());
    332         assertEquals(2, rmnet0.getAllAddresses().size());
    333         assertEquals(2, rmnet0.getAllLinkAddresses().size());
    334 
    335         rmnet0.addStackedLink(clat4);
    336         assertEquals(1, rmnet0.getStackedLinks().size());
    337         assertEquals(1, rmnet0.getAddresses().size());
    338         assertEquals(1, rmnet0.getLinkAddresses().size());
    339         assertEquals(2, rmnet0.getAllAddresses().size());
    340         assertEquals(2, rmnet0.getAllLinkAddresses().size());
    341 
    342         assertEquals(0, clat4.getStackedLinks().size());
    343 
    344         // Modify an item in the returned collection to see what happens.
    345         for (LinkProperties link : rmnet0.getStackedLinks()) {
    346             if (link.getInterfaceName().equals("clat4")) {
    347                link.setInterfaceName("newname");
    348             }
    349         }
    350         for (LinkProperties link : rmnet0.getStackedLinks()) {
    351             assertFalse("newname".equals(link.getInterfaceName()));
    352         }
    353 
    354         assertTrue(rmnet0.removeStackedLink("clat4"));
    355         assertEquals(0, rmnet0.getStackedLinks().size());
    356         assertEquals(1, rmnet0.getAddresses().size());
    357         assertEquals(1, rmnet0.getLinkAddresses().size());
    358         assertEquals(1, rmnet0.getAllAddresses().size());
    359         assertEquals(1, rmnet0.getAllLinkAddresses().size());
    360 
    361         assertFalse(rmnet0.removeStackedLink("clat4"));
    362     }
    363 
    364     private LinkAddress getFirstLinkAddress(LinkProperties lp) {
    365         return lp.getLinkAddresses().iterator().next();
    366     }
    367 
    368     @SmallTest
    369     public void testAddressMethods() {
    370         LinkProperties lp = new LinkProperties();
    371 
    372         // No addresses.
    373         assertFalse(lp.hasIPv4Address());
    374         assertFalse(lp.hasGlobalIPv6Address());
    375 
    376         // Addresses on stacked links don't count.
    377         LinkProperties stacked = new LinkProperties();
    378         stacked.setInterfaceName("stacked");
    379         lp.addStackedLink(stacked);
    380         stacked.addLinkAddress(LINKADDRV4);
    381         stacked.addLinkAddress(LINKADDRV6);
    382         assertTrue(stacked.hasIPv4Address());
    383         assertTrue(stacked.hasGlobalIPv6Address());
    384         assertFalse(lp.hasIPv4Address());
    385         assertFalse(lp.hasGlobalIPv6Address());
    386         lp.removeStackedLink("stacked");
    387         assertFalse(lp.hasIPv4Address());
    388         assertFalse(lp.hasGlobalIPv6Address());
    389 
    390         // Addresses on the base link.
    391         // Check the return values of hasIPvXAddress and ensure the add/remove methods return true
    392         // iff something changes.
    393         assertEquals(0, lp.getLinkAddresses().size());
    394         assertTrue(lp.addLinkAddress(LINKADDRV6));
    395         assertEquals(1, lp.getLinkAddresses().size());
    396         assertFalse(lp.hasIPv4Address());
    397         assertTrue(lp.hasGlobalIPv6Address());
    398 
    399         assertTrue(lp.removeLinkAddress(LINKADDRV6));
    400         assertEquals(0, lp.getLinkAddresses().size());
    401 
    402         assertTrue(lp.addLinkAddress(LINKADDRV6LINKLOCAL));
    403         assertEquals(1, lp.getLinkAddresses().size());
    404         assertFalse(lp.hasGlobalIPv6Address());
    405 
    406         assertTrue(lp.addLinkAddress(LINKADDRV4));
    407         assertEquals(2, lp.getLinkAddresses().size());
    408         assertTrue(lp.hasIPv4Address());
    409         assertFalse(lp.hasGlobalIPv6Address());
    410 
    411         assertTrue(lp.addLinkAddress(LINKADDRV6));
    412         assertEquals(3, lp.getLinkAddresses().size());
    413         assertTrue(lp.hasIPv4Address());
    414         assertTrue(lp.hasGlobalIPv6Address());
    415 
    416         assertTrue(lp.removeLinkAddress(LINKADDRV6LINKLOCAL));
    417         assertEquals(2, lp.getLinkAddresses().size());
    418         assertTrue(lp.hasIPv4Address());
    419         assertTrue(lp.hasGlobalIPv6Address());
    420 
    421         // Adding an address twice has no effect.
    422         // Removing an address that's not present has no effect.
    423         assertFalse(lp.addLinkAddress(LINKADDRV4));
    424         assertEquals(2, lp.getLinkAddresses().size());
    425         assertTrue(lp.hasIPv4Address());
    426         assertTrue(lp.removeLinkAddress(LINKADDRV4));
    427         assertEquals(1, lp.getLinkAddresses().size());
    428         assertFalse(lp.hasIPv4Address());
    429         assertFalse(lp.removeLinkAddress(LINKADDRV4));
    430         assertEquals(1, lp.getLinkAddresses().size());
    431 
    432         // Adding an address that's already present but with different properties causes the
    433         // existing address to be updated and returns true.
    434         // Start with only LINKADDRV6.
    435         assertEquals(1, lp.getLinkAddresses().size());
    436         assertEquals(LINKADDRV6, getFirstLinkAddress(lp));
    437 
    438         // Create a LinkAddress object for the same address, but with different flags.
    439         LinkAddress deprecated = new LinkAddress(ADDRV6, 128,
    440                 OsConstants.IFA_F_DEPRECATED, OsConstants.RT_SCOPE_UNIVERSE);
    441         assertTrue(deprecated.isSameAddressAs(LINKADDRV6));
    442         assertFalse(deprecated.equals(LINKADDRV6));
    443 
    444         // Check that adding it updates the existing address instead of adding a new one.
    445         assertTrue(lp.addLinkAddress(deprecated));
    446         assertEquals(1, lp.getLinkAddresses().size());
    447         assertEquals(deprecated, getFirstLinkAddress(lp));
    448         assertFalse(LINKADDRV6.equals(getFirstLinkAddress(lp)));
    449 
    450         // Removing LINKADDRV6 removes deprecated, because removing addresses ignores properties.
    451         assertTrue(lp.removeLinkAddress(LINKADDRV6));
    452         assertEquals(0, lp.getLinkAddresses().size());
    453     }
    454 
    455     @SmallTest
    456     public void testSetLinkAddresses() {
    457         LinkProperties lp = new LinkProperties();
    458         lp.addLinkAddress(LINKADDRV4);
    459         lp.addLinkAddress(LINKADDRV6);
    460 
    461         LinkProperties lp2 = new LinkProperties();
    462         lp2.addLinkAddress(LINKADDRV6);
    463 
    464         assertFalse(lp.equals(lp2));
    465 
    466         lp2.setLinkAddresses(lp.getLinkAddresses());
    467         assertTrue(lp.equals(lp));
    468     }
    469 
    470     @SmallTest
    471     public void testIsProvisioned() {
    472         LinkProperties lp4 = new LinkProperties();
    473         assertFalse("v4only:empty", lp4.isProvisioned());
    474         lp4.addLinkAddress(LINKADDRV4);
    475         assertFalse("v4only:addr-only", lp4.isProvisioned());
    476         lp4.addDnsServer(DNS1);
    477         assertFalse("v4only:addr+dns", lp4.isProvisioned());
    478         lp4.addRoute(new RouteInfo(GATEWAY1));
    479         assertTrue("v4only:addr+dns+route", lp4.isProvisioned());
    480         assertTrue("v4only:addr+dns+route", lp4.isIPv4Provisioned());
    481         assertFalse("v4only:addr+dns+route", lp4.isIPv6Provisioned());
    482 
    483         LinkProperties lp6 = new LinkProperties();
    484         assertFalse("v6only:empty", lp6.isProvisioned());
    485         lp6.addLinkAddress(LINKADDRV6LINKLOCAL);
    486         assertFalse("v6only:fe80-only", lp6.isProvisioned());
    487         lp6.addDnsServer(DNS6);
    488         assertFalse("v6only:fe80+dns", lp6.isProvisioned());
    489         lp6.addRoute(new RouteInfo(GATEWAY61));
    490         assertFalse("v6only:fe80+dns+route", lp6.isProvisioned());
    491         lp6.addLinkAddress(LINKADDRV6);
    492         assertTrue("v6only:fe80+global+dns+route", lp6.isIPv6Provisioned());
    493         assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned());
    494         lp6.removeLinkAddress(LINKADDRV6LINKLOCAL);
    495         assertFalse("v6only:global+dns+route", lp6.isIPv4Provisioned());
    496         assertTrue("v6only:global+dns+route", lp6.isIPv6Provisioned());
    497         assertTrue("v6only:global+dns+route", lp6.isProvisioned());
    498 
    499         LinkProperties lp46 = new LinkProperties();
    500         lp46.addLinkAddress(LINKADDRV4);
    501         lp46.addLinkAddress(LINKADDRV6);
    502         lp46.addDnsServer(DNS1);
    503         lp46.addDnsServer(DNS6);
    504         assertFalse("dualstack:missing-routes", lp46.isProvisioned());
    505         lp46.addRoute(new RouteInfo(GATEWAY1));
    506         assertTrue("dualstack:v4-provisioned", lp46.isIPv4Provisioned());
    507         assertFalse("dualstack:v4-provisioned", lp46.isIPv6Provisioned());
    508         assertTrue("dualstack:v4-provisioned", lp46.isProvisioned());
    509         lp46.addRoute(new RouteInfo(GATEWAY61));
    510         assertTrue("dualstack:both-provisioned", lp46.isIPv4Provisioned());
    511         assertTrue("dualstack:both-provisioned", lp46.isIPv6Provisioned());
    512         assertTrue("dualstack:both-provisioned", lp46.isProvisioned());
    513 
    514         // A link with an IPv6 address and default route, but IPv4 DNS server.
    515         LinkProperties mixed = new LinkProperties();
    516         mixed.addLinkAddress(LINKADDRV6);
    517         mixed.addDnsServer(DNS1);
    518         mixed.addRoute(new RouteInfo(GATEWAY61));
    519         assertFalse("mixed:addr6+route6+dns4", mixed.isIPv4Provisioned());
    520         assertFalse("mixed:addr6+route6+dns4", mixed.isIPv6Provisioned());
    521         assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned());
    522     }
    523 
    524     @SmallTest
    525     public void testCompareProvisioning() {
    526         LinkProperties v4lp = new LinkProperties();
    527         v4lp.addLinkAddress(LINKADDRV4);
    528         v4lp.addRoute(new RouteInfo(GATEWAY1));
    529         v4lp.addDnsServer(DNS1);
    530         assertTrue(v4lp.isProvisioned());
    531 
    532         LinkProperties v4r = new LinkProperties(v4lp);
    533         v4r.removeDnsServer(DNS1);
    534         assertFalse(v4r.isProvisioned());
    535 
    536         assertEquals(ProvisioningChange.STILL_NOT_PROVISIONED,
    537                 LinkProperties.compareProvisioning(v4r, v4r));
    538         assertEquals(ProvisioningChange.LOST_PROVISIONING,
    539                 LinkProperties.compareProvisioning(v4lp, v4r));
    540         assertEquals(ProvisioningChange.GAINED_PROVISIONING,
    541                 LinkProperties.compareProvisioning(v4r, v4lp));
    542         assertEquals(ProvisioningChange.STILL_PROVISIONED,
    543                 LinkProperties.compareProvisioning(v4lp, v4lp));
    544 
    545         // Check that losing IPv4 provisioning on a dualstack network is
    546         // seen as a total loss of provisioning.
    547         LinkProperties v6lp = new LinkProperties();
    548         v6lp.addLinkAddress(LINKADDRV6);
    549         v6lp.addRoute(new RouteInfo(GATEWAY61));
    550         v6lp.addDnsServer(DNS6);
    551         assertFalse(v6lp.isIPv4Provisioned());
    552         assertTrue(v6lp.isIPv6Provisioned());
    553         assertTrue(v6lp.isProvisioned());
    554 
    555         LinkProperties v46lp = new LinkProperties(v6lp);
    556         v46lp.addLinkAddress(LINKADDRV4);
    557         v46lp.addRoute(new RouteInfo(GATEWAY1));
    558         v46lp.addDnsServer(DNS1);
    559         assertTrue(v46lp.isIPv4Provisioned());
    560         assertTrue(v46lp.isIPv6Provisioned());
    561         assertTrue(v46lp.isProvisioned());
    562 
    563         assertEquals(ProvisioningChange.STILL_PROVISIONED,
    564                 LinkProperties.compareProvisioning(v4lp, v46lp));
    565         assertEquals(ProvisioningChange.STILL_PROVISIONED,
    566                 LinkProperties.compareProvisioning(v6lp, v46lp));
    567         assertEquals(ProvisioningChange.LOST_PROVISIONING,
    568                 LinkProperties.compareProvisioning(v46lp, v6lp));
    569         assertEquals(ProvisioningChange.LOST_PROVISIONING,
    570                 LinkProperties.compareProvisioning(v46lp, v4lp));
    571 
    572         // Check that losing and gaining a secondary router does not change
    573         // the provisioning status.
    574         LinkProperties v6lp2 = new LinkProperties(v6lp);
    575         v6lp2.addRoute(new RouteInfo(GATEWAY62));
    576         assertTrue(v6lp2.isProvisioned());
    577 
    578         assertEquals(ProvisioningChange.STILL_PROVISIONED,
    579                 LinkProperties.compareProvisioning(v6lp2, v6lp));
    580         assertEquals(ProvisioningChange.STILL_PROVISIONED,
    581                 LinkProperties.compareProvisioning(v6lp, v6lp2));
    582     }
    583 
    584     @SmallTest
    585     @Suppress  // Failing.
    586     public void testIsReachable() {
    587         final LinkProperties v4lp = new LinkProperties();
    588         assertFalse(v4lp.isReachable(DNS1));
    589         assertFalse(v4lp.isReachable(DNS2));
    590 
    591         // Add an on-link route, making the on-link DNS server reachable,
    592         // but there is still no IPv4 address.
    593         assertTrue(v4lp.addRoute(new RouteInfo(
    594                 new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16))));
    595         assertFalse(v4lp.isReachable(DNS1));
    596         assertFalse(v4lp.isReachable(DNS2));
    597 
    598         // Adding an IPv4 address (right now, any IPv4 address) means we use
    599         // the routes to compute likely reachability.
    600         assertTrue(v4lp.addLinkAddress(new LinkAddress(ADDRV4, 16)));
    601         assertTrue(v4lp.isReachable(DNS1));
    602         assertFalse(v4lp.isReachable(DNS2));
    603 
    604         // Adding a default route makes the off-link DNS server reachable.
    605         assertTrue(v4lp.addRoute(new RouteInfo(GATEWAY1)));
    606         assertTrue(v4lp.isReachable(DNS1));
    607         assertTrue(v4lp.isReachable(DNS2));
    608 
    609         final LinkProperties v6lp = new LinkProperties();
    610         final InetAddress kLinkLocalDns = NetworkUtils.numericToInetAddress("fe80::6:1");
    611         final InetAddress kLinkLocalDnsWithScope = NetworkUtils.numericToInetAddress("fe80::6:2%43");
    612         final InetAddress kOnLinkDns = NetworkUtils.numericToInetAddress("2001:db8:85a3::53");
    613         assertFalse(v6lp.isReachable(kLinkLocalDns));
    614         assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
    615         assertFalse(v6lp.isReachable(kOnLinkDns));
    616         assertFalse(v6lp.isReachable(DNS6));
    617 
    618         // Add a link-local route, making the link-local DNS servers reachable. Because
    619         // we assume the presence of an IPv6 link-local address, link-local DNS servers
    620         // are considered reachable, but only those with a non-zero scope identifier.
    621         assertTrue(v6lp.addRoute(new RouteInfo(
    622                 new IpPrefix(NetworkUtils.numericToInetAddress("fe80::"), 64))));
    623         assertFalse(v6lp.isReachable(kLinkLocalDns));
    624         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
    625         assertFalse(v6lp.isReachable(kOnLinkDns));
    626         assertFalse(v6lp.isReachable(DNS6));
    627 
    628         // Add a link-local address--nothing changes.
    629         assertTrue(v6lp.addLinkAddress(LINKADDRV6LINKLOCAL));
    630         assertFalse(v6lp.isReachable(kLinkLocalDns));
    631         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
    632         assertFalse(v6lp.isReachable(kOnLinkDns));
    633         assertFalse(v6lp.isReachable(DNS6));
    634 
    635         // Add a global route on link, but no global address yet. DNS servers reachable
    636         // via a route that doesn't require a gateway: give them the benefit of the
    637         // doubt and hope the link-local source address suffices for communication.
    638         assertTrue(v6lp.addRoute(new RouteInfo(
    639                 new IpPrefix(NetworkUtils.numericToInetAddress("2001:db8:85a3::"), 64))));
    640         assertFalse(v6lp.isReachable(kLinkLocalDns));
    641         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
    642         assertTrue(v6lp.isReachable(kOnLinkDns));
    643         assertFalse(v6lp.isReachable(DNS6));
    644 
    645         // Add a global address; the on-link global address DNS server is (still)
    646         // presumed reachable.
    647         assertTrue(v6lp.addLinkAddress(new LinkAddress(ADDRV6, 64)));
    648         assertFalse(v6lp.isReachable(kLinkLocalDns));
    649         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
    650         assertTrue(v6lp.isReachable(kOnLinkDns));
    651         assertFalse(v6lp.isReachable(DNS6));
    652 
    653         // Adding a default route makes the off-link DNS server reachable.
    654         assertTrue(v6lp.addRoute(new RouteInfo(GATEWAY62)));
    655         assertFalse(v6lp.isReachable(kLinkLocalDns));
    656         assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
    657         assertTrue(v6lp.isReachable(kOnLinkDns));
    658         assertTrue(v6lp.isReachable(DNS6));
    659 
    660         // Check isReachable on stacked links. This requires that the source IP address be assigned
    661         // on the interface returned by the route lookup.
    662         LinkProperties stacked = new LinkProperties();
    663 
    664         // Can't add a stacked link without an interface name.
    665         stacked.setInterfaceName("v4-test0");
    666         v6lp.addStackedLink(stacked);
    667 
    668         InetAddress stackedAddress = Address("192.0.0.4");
    669         LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32);
    670         assertFalse(v6lp.isReachable(stackedAddress));
    671         stacked.addLinkAddress(stackedLinkAddress);
    672         assertFalse(v6lp.isReachable(stackedAddress));
    673         stacked.addRoute(new RouteInfo(stackedLinkAddress));
    674         assertTrue(stacked.isReachable(stackedAddress));
    675         assertTrue(v6lp.isReachable(stackedAddress));
    676 
    677         assertFalse(v6lp.isReachable(DNS1));
    678         stacked.addRoute(new RouteInfo((IpPrefix) null, stackedAddress));
    679         assertTrue(v6lp.isReachable(DNS1));
    680     }
    681 }
    682