LinkPropertiesTest.java revision d920134258e385250f37d73205139b477beb7afc
14e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang/*
24e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang * Copyright (C) 2010 The Android Open Source Project
34e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang *
44e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang * Licensed under the Apache License, Version 2.0 (the "License");
54e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang * you may not use this file except in compliance with the License.
64e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang * You may obtain a copy of the License at
74e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang *
84e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang *      http://www.apache.org/licenses/LICENSE-2.0
94e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang *
104e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang * Unless required by applicable law or agreed to in writing, software
114e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang * distributed under the License is distributed on an "AS IS" BASIS,
124e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang * See the License for the specific language governing permissions and
144e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang * limitations under the License.
154e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang */
164e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
174e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wangpackage android.net;
184e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
19da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport static org.junit.Assert.assertEquals;
20da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport static org.junit.Assert.assertFalse;
21da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport static org.junit.Assert.assertTrue;
22da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport static org.junit.Assert.fail;
23da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
24b36a3131d1b05efa176f79d318197499b2c45380Erik Klineimport android.net.IpPrefix;
25b36a3131d1b05efa176f79d318197499b2c45380Erik Klineimport android.net.LinkAddress;
264e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wangimport android.net.LinkProperties;
272fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xuimport android.net.LinkProperties.CompareResult;
28cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Klineimport android.net.LinkProperties.ProvisioningChange;
29aa70f101e08098ed9cb190abe2d7f952561026b8Robert Greenwaltimport android.net.RouteInfo;
30da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport android.support.test.filters.SmallTest;
31da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport android.support.test.runner.AndroidJUnit4;
3234385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.system.OsConstants;
331bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport android.util.ArraySet;
341bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
354e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wangimport java.net.InetAddress;
362fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xuimport java.util.ArrayList;
371bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport java.util.Arrays;
381bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport java.util.Collection;
391bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport java.util.Collections;
402fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xuimport java.util.List;
411bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport java.util.Set;
424e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
43da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport org.junit.Test;
44da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport org.junit.runner.RunWith;
45b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
46da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi@RunWith(AndroidJUnit4.class)
47da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi@SmallTest
48da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichipublic class LinkPropertiesTest {
493f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1");
503f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress(
513f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti            "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
523f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress DNS1 = NetworkUtils.numericToInetAddress("75.208.7.1");
533f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress DNS2 = NetworkUtils.numericToInetAddress("69.78.7.1");
54d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    private static InetAddress DNS6 = NetworkUtils.numericToInetAddress("2001:4860:4860::8888");
553f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1");
563f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1");
57cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    private static InetAddress GATEWAY61 = NetworkUtils.numericToInetAddress("fe80::6:0000:613");
58cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    private static InetAddress GATEWAY62 = NetworkUtils.numericToInetAddress("fe80::6:2222");
594e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    private static String NAME = "qmi0";
609d9b74a900696191048aa97cc3c854072640428bsy.yun    private static int MTU = 1500;
614e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
623f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
633f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
6476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    private static LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
653f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti
6689b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti    // TODO: replace all calls to NetworkUtils.numericToInetAddress with calls to this method.
6789b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti    private InetAddress Address(String addrString) {
6889b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        return NetworkUtils.numericToInetAddress(addrString);
6989b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti    }
7089b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
71213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti    public void assertLinkPropertiesEqual(LinkProperties source, LinkProperties target) {
72213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        // Check implementation of equals(), element by element.
73213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalInterfaceName(target));
74213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalInterfaceName(source));
75213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
76213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalAddresses(target));
77213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalAddresses(source));
78213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
79213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalDnses(target));
80213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalDnses(source));
81213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
82d920134258e385250f37d73205139b477beb7afcdalyk        assertTrue(source.isIdenticalPrivateDns(target));
83d920134258e385250f37d73205139b477beb7afcdalyk        assertTrue(target.isIdenticalPrivateDns(source));
84d920134258e385250f37d73205139b477beb7afcdalyk
85213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalRoutes(target));
86213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalRoutes(source));
87213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
88213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalHttpProxy(target));
89213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalHttpProxy(source));
90213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
91213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalStackedLinks(target));
92213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalStackedLinks(source));
93213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
949d9b74a900696191048aa97cc3c854072640428bsy.yun        assertTrue(source.isIdenticalMtu(target));
959d9b74a900696191048aa97cc3c854072640428bsy.yun        assertTrue(target.isIdenticalMtu(source));
969d9b74a900696191048aa97cc3c854072640428bsy.yun
97d920134258e385250f37d73205139b477beb7afcdalyk        assertTrue(source.isIdenticalTcpBufferSizes(target));
98d920134258e385250f37d73205139b477beb7afcdalyk        assertTrue(target.isIdenticalTcpBufferSizes(source));
99d920134258e385250f37d73205139b477beb7afcdalyk
100213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        // Check result of equals().
101213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.equals(target));
102213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.equals(source));
103213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
104213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        // Check hashCode.
105213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertEquals(source.hashCode(), target.hashCode());
106213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti    }
107213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
108da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
1094e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    public void testEqualsNull() {
1104e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        LinkProperties source = new LinkProperties();
1114e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        LinkProperties target = new LinkProperties();
1124e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
1134e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        assertFalse(source == target);
114213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertLinkPropertiesEqual(source, target);
1154e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
1164e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
117da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
118da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    public void testEqualsSameOrder() throws Exception {
119da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties source = new LinkProperties();
120da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.setInterfaceName(NAME);
121da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 link addresses
122da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV4);
123da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV6);
124da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 dnses
125da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addDnsServer(DNS1);
126da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addDnsServer(DNS2);
127da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 gateways
128da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addRoute(new RouteInfo(GATEWAY1));
129da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addRoute(new RouteInfo(GATEWAY2));
130da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.setMtu(MTU);
131da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
132da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties target = new LinkProperties();
133da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
134da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // All fields are same
135da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
136da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
137da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
138da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
139da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
140da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
141da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
142da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
143da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
144da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertLinkPropertiesEqual(source, target);
145da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
146da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
147da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change Interface Name
148da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName("qmi1");
149da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
150da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
151da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
152da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
153da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
154da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
155da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
156da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
157da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
158da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
159da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
160da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change link addresses
161da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(new LinkAddress(
162da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi                NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
163da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
164da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
165da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
166da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
167da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
168da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
169da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
170da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
171da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
172da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
173da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
174da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
175da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change dnses
176da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
177da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
178da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
179da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
180da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
181da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
182da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
183da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
184da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
185da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
186da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
187da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
188da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
189da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change gateway
190da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
191da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
192da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
193da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
194da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
195da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
196da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
197da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
198da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
199da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
200da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
201da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
202da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
203da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change mtu
204da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(1440);
205da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
2064e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
2074e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
208da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
209da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    public void testEqualsDifferentOrder() throws Exception {
210da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties source = new LinkProperties();
211da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.setInterfaceName(NAME);
212da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 link addresses
213da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV4);
214da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV6);
215da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 dnses
216da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addDnsServer(DNS1);
217da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addDnsServer(DNS2);
218da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 gateways
219da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addRoute(new RouteInfo(GATEWAY1));
220da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addRoute(new RouteInfo(GATEWAY2));
221da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.setMtu(MTU);
222da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
223da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties target = new LinkProperties();
224da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // Exchange order
225da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
226da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
227da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
228da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
229da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
230da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
231da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
232da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
233da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
234da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertLinkPropertiesEqual(source, target);
2354e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
2364e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
237da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
238da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    public void testEqualsDuplicated() throws Exception {
239da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties source = new LinkProperties();
240da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 3 link addresses, eg, [A, A, B]
241da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV4);
242da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV4);
243da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV6);
244da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
245da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties target = new LinkProperties();
246da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 3 link addresses, eg, [A, B, B]
247da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
248da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
249da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
250da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
251da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertLinkPropertiesEqual(source, target);
2524e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
2534e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
2541994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti    private void assertAllRoutesHaveInterface(String iface, LinkProperties lp) {
2551994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        for (RouteInfo r : lp.getRoutes()) {
2561994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti            assertEquals(iface, r.getInterface());
2571994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        }
2581994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti    }
2591994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
260da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
2611994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti    public void testRouteInterfaces() {
2621994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        LinkAddress prefix = new LinkAddress(
2631994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti            NetworkUtils.numericToInetAddress("2001:db8::"), 32);
2643f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti        InetAddress address = ADDRV6;
2651994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2661994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Add a route with no interface to a LinkProperties with no interface. No errors.
2671994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        LinkProperties lp = new LinkProperties();
2681994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        RouteInfo r = new RouteInfo(prefix, address, null);
2691603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        assertTrue(lp.addRoute(r));
2701994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertEquals(1, lp.getRoutes().size());
2711994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface(null, lp);
2721994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2731603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        // Adding the same route twice has no effect.
2741603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        assertFalse(lp.addRoute(r));
2751603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        assertEquals(1, lp.getRoutes().size());
2761603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti
2771603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        // Add a route with an interface. Expect an exception.
2781994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        r = new RouteInfo(prefix, address, "wlan0");
2791994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        try {
2801994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti          lp.addRoute(r);
2811994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti          fail("Adding wlan0 route to LP with no interface, expect exception");
2821994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        } catch (IllegalArgumentException expected) {}
2831994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2841994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Change the interface name. All the routes should change their interface name too.
2851994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp.setInterfaceName("rmnet0");
2861994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("rmnet0", lp);
2871994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2881994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Now add a route with the wrong interface. This causes an exception too.
2891994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        try {
2901994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti          lp.addRoute(r);
2911994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti          fail("Adding wlan0 route to rmnet0 LP, expect exception");
2921994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        } catch (IllegalArgumentException expected) {}
2931994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2941994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // If the interface name matches, the route is added.
2951603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        r = new RouteInfo(prefix, null, "wlan0");
2961994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp.setInterfaceName("wlan0");
2971994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp.addRoute(r);
2981994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertEquals(2, lp.getRoutes().size());
2991994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("wlan0", lp);
3001994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
3011994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Routes with null interfaces are converted to wlan0.
3023f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti        r = RouteInfo.makeHostRoute(ADDRV6, null);
3031994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp.addRoute(r);
3041994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertEquals(3, lp.getRoutes().size());
3051994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("wlan0", lp);
3061994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
3071994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Check comparisons work.
3081994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        LinkProperties lp2 = new LinkProperties(lp);
3091994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("wlan0", lp);
310d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(0, lp.compareAllRoutes(lp2).added.size());
311d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(0, lp.compareAllRoutes(lp2).removed.size());
3121994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
3131994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp2.setInterfaceName("p2p0");
3141994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("p2p0", lp2);
315d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(3, lp.compareAllRoutes(lp2).added.size());
316d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
317b91e50c266a7eb9dd6f8171deb497931ef7aef76Lorenzo Colitti    }
318419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
319da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
320419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public void testStackedInterfaces() {
321419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        LinkProperties rmnet0 = new LinkProperties();
322419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        rmnet0.setInterfaceName("rmnet0");
3233f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti        rmnet0.addLinkAddress(LINKADDRV6);
324419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
325419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        LinkProperties clat4 = new LinkProperties();
326419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        clat4.setInterfaceName("clat4");
3273f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti        clat4.addLinkAddress(LINKADDRV4);
328419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
329419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        assertEquals(0, rmnet0.getStackedLinks().size());
330d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAddresses().size());
331d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getLinkAddresses().size());
332d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAllAddresses().size());
333d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAllLinkAddresses().size());
334d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
335419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        rmnet0.addStackedLink(clat4);
336419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        assertEquals(1, rmnet0.getStackedLinks().size());
337d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAddresses().size());
338d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getLinkAddresses().size());
339d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(2, rmnet0.getAllAddresses().size());
340d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(2, rmnet0.getAllLinkAddresses().size());
341d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
342419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        rmnet0.addStackedLink(clat4);
343419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        assertEquals(1, rmnet0.getStackedLinks().size());
344d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAddresses().size());
345d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getLinkAddresses().size());
346d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(2, rmnet0.getAllAddresses().size());
347d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(2, rmnet0.getAllLinkAddresses().size());
348d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
349419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        assertEquals(0, clat4.getStackedLinks().size());
350419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
351419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        // Modify an item in the returned collection to see what happens.
352419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties link : rmnet0.getStackedLinks()) {
353419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            if (link.getInterfaceName().equals("clat4")) {
354419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti               link.setInterfaceName("newname");
355419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
356419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
357419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties link : rmnet0.getStackedLinks()) {
358419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            assertFalse("newname".equals(link.getInterfaceName()));
359419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
3604faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
361f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti        assertTrue(rmnet0.removeStackedLink("clat4"));
3624faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(0, rmnet0.getStackedLinks().size());
3634faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(1, rmnet0.getAddresses().size());
3644faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(1, rmnet0.getLinkAddresses().size());
3654faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(1, rmnet0.getAllAddresses().size());
3664faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(1, rmnet0.getAllLinkAddresses().size());
3674faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
368f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti        assertFalse(rmnet0.removeStackedLink("clat4"));
3694faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    }
3704faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
37164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private LinkAddress getFirstLinkAddress(LinkProperties lp) {
37264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        return lp.getLinkAddresses().iterator().next();
37364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    }
37464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
375da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
3764faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public void testAddressMethods() {
3774faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        LinkProperties lp = new LinkProperties();
3784faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
3794faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // No addresses.
3804faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
38176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
3824faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
3834faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Addresses on stacked links don't count.
3844faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        LinkProperties stacked = new LinkProperties();
3854faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        stacked.setInterfaceName("stacked");
3864faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        lp.addStackedLink(stacked);
3874faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        stacked.addLinkAddress(LINKADDRV4);
3884faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        stacked.addLinkAddress(LINKADDRV6);
3894faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(stacked.hasIPv4Address());
39076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(stacked.hasGlobalIPv6Address());
3914faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
39276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
393f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti        lp.removeStackedLink("stacked");
3944faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
39576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
3964faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
3974faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Addresses on the base link.
3984faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Check the return values of hasIPvXAddress and ensure the add/remove methods return true
3994faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // iff something changes.
40064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(0, lp.getLinkAddresses().size());
4014faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.addLinkAddress(LINKADDRV6));
40264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
4034faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
40476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.hasGlobalIPv6Address());
4054faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
4064faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.removeLinkAddress(LINKADDRV6));
40764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(0, lp.getLinkAddresses().size());
40876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
40976ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.addLinkAddress(LINKADDRV6LINKLOCAL));
41064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
41176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
41276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
41376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.addLinkAddress(LINKADDRV4));
41476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertEquals(2, lp.getLinkAddresses().size());
4154faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.hasIPv4Address());
41676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
4174faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
4184faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.addLinkAddress(LINKADDRV6));
41976ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertEquals(3, lp.getLinkAddresses().size());
42076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.hasIPv4Address());
42176ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.hasGlobalIPv6Address());
42276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
42376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.removeLinkAddress(LINKADDRV6LINKLOCAL));
42464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(2, lp.getLinkAddresses().size());
4254faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.hasIPv4Address());
42676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.hasGlobalIPv6Address());
4274faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
4284faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Adding an address twice has no effect.
4294faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Removing an address that's not present has no effect.
4304faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.addLinkAddress(LINKADDRV4));
43164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(2, lp.getLinkAddresses().size());
4324faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.hasIPv4Address());
4334faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.removeLinkAddress(LINKADDRV4));
43464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
4354faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
4364faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.removeLinkAddress(LINKADDRV4));
43764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
43864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
43964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Adding an address that's already present but with different properties causes the
44064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // existing address to be updated and returns true.
44164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Start with only LINKADDRV6.
44264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
44364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(LINKADDRV6, getFirstLinkAddress(lp));
44464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
44564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Create a LinkAddress object for the same address, but with different flags.
44664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        LinkAddress deprecated = new LinkAddress(ADDRV6, 128,
44764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti                OsConstants.IFA_F_DEPRECATED, OsConstants.RT_SCOPE_UNIVERSE);
44864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertTrue(deprecated.isSameAddressAs(LINKADDRV6));
44964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertFalse(deprecated.equals(LINKADDRV6));
45064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
45164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Check that adding it updates the existing address instead of adding a new one.
45264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertTrue(lp.addLinkAddress(deprecated));
45364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
45464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(deprecated, getFirstLinkAddress(lp));
45564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertFalse(LINKADDRV6.equals(getFirstLinkAddress(lp)));
45664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
45764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Removing LINKADDRV6 removes deprecated, because removing addresses ignores properties.
45864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertTrue(lp.removeLinkAddress(LINKADDRV6));
45964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(0, lp.getLinkAddresses().size());
4601994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti    }
46122f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
462da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
46322f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    public void testSetLinkAddresses() {
46422f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        LinkProperties lp = new LinkProperties();
46522f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        lp.addLinkAddress(LINKADDRV4);
46622f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        lp.addLinkAddress(LINKADDRV6);
46722f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
46822f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        LinkProperties lp2 = new LinkProperties();
46922f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        lp2.addLinkAddress(LINKADDRV6);
47022f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
47122f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        assertFalse(lp.equals(lp2));
47222f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
47322f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        lp2.setLinkAddresses(lp.getLinkAddresses());
47422f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        assertTrue(lp.equals(lp));
47522f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    }
476d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
477da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
478d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    public void testIsProvisioned() {
479d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        LinkProperties lp4 = new LinkProperties();
480d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v4only:empty", lp4.isProvisioned());
481d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp4.addLinkAddress(LINKADDRV4);
482d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v4only:addr-only", lp4.isProvisioned());
483d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp4.addDnsServer(DNS1);
484d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v4only:addr+dns", lp4.isProvisioned());
485d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp4.addRoute(new RouteInfo(GATEWAY1));
486d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("v4only:addr+dns+route", lp4.isProvisioned());
487cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("v4only:addr+dns+route", lp4.isIPv4Provisioned());
488cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("v4only:addr+dns+route", lp4.isIPv6Provisioned());
489d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
490d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        LinkProperties lp6 = new LinkProperties();
491d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v6only:empty", lp6.isProvisioned());
492d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp6.addLinkAddress(LINKADDRV6LINKLOCAL);
493d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v6only:fe80-only", lp6.isProvisioned());
494d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp6.addDnsServer(DNS6);
495d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v6only:fe80+dns", lp6.isProvisioned());
496cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        lp6.addRoute(new RouteInfo(GATEWAY61));
497d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v6only:fe80+dns+route", lp6.isProvisioned());
498d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp6.addLinkAddress(LINKADDRV6);
499cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("v6only:fe80+global+dns+route", lp6.isIPv6Provisioned());
500d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned());
501d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp6.removeLinkAddress(LINKADDRV6LINKLOCAL);
502cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("v6only:global+dns+route", lp6.isIPv4Provisioned());
503cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("v6only:global+dns+route", lp6.isIPv6Provisioned());
504d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("v6only:global+dns+route", lp6.isProvisioned());
505d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
506d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        LinkProperties lp46 = new LinkProperties();
507d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addLinkAddress(LINKADDRV4);
508d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addLinkAddress(LINKADDRV6);
509d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addDnsServer(DNS1);
510d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addDnsServer(DNS6);
511d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("dualstack:missing-routes", lp46.isProvisioned());
512d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addRoute(new RouteInfo(GATEWAY1));
513cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("dualstack:v4-provisioned", lp46.isIPv4Provisioned());
514cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("dualstack:v4-provisioned", lp46.isIPv6Provisioned());
515d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("dualstack:v4-provisioned", lp46.isProvisioned());
516cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        lp46.addRoute(new RouteInfo(GATEWAY61));
517cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("dualstack:both-provisioned", lp46.isIPv4Provisioned());
518cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("dualstack:both-provisioned", lp46.isIPv6Provisioned());
519d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("dualstack:both-provisioned", lp46.isProvisioned());
520d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
521d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        // A link with an IPv6 address and default route, but IPv4 DNS server.
522d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        LinkProperties mixed = new LinkProperties();
523d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        mixed.addLinkAddress(LINKADDRV6);
524d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        mixed.addDnsServer(DNS1);
525cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        mixed.addRoute(new RouteInfo(GATEWAY61));
526cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("mixed:addr6+route6+dns4", mixed.isIPv4Provisioned());
527cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("mixed:addr6+route6+dns4", mixed.isIPv6Provisioned());
528d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned());
529d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    }
530cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
531da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
532cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    public void testCompareProvisioning() {
533cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v4lp = new LinkProperties();
534cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v4lp.addLinkAddress(LINKADDRV4);
535cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v4lp.addRoute(new RouteInfo(GATEWAY1));
536cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v4lp.addDnsServer(DNS1);
537cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v4lp.isProvisioned());
538cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
539cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v4r = new LinkProperties(v4lp);
540cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v4r.removeDnsServer(DNS1);
541cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse(v4r.isProvisioned());
542cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
543cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_NOT_PROVISIONED,
544cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v4r, v4r));
545cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.LOST_PROVISIONING,
546cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v4lp, v4r));
547cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.GAINED_PROVISIONING,
548cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v4r, v4lp));
549cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
550cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v4lp, v4lp));
551cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
552cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        // Check that losing IPv4 provisioning on a dualstack network is
553cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        // seen as a total loss of provisioning.
554cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v6lp = new LinkProperties();
555cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v6lp.addLinkAddress(LINKADDRV6);
556cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v6lp.addRoute(new RouteInfo(GATEWAY61));
557cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v6lp.addDnsServer(DNS6);
558cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse(v6lp.isIPv4Provisioned());
559cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v6lp.isIPv6Provisioned());
560cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v6lp.isProvisioned());
561cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
562cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v46lp = new LinkProperties(v6lp);
563cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v46lp.addLinkAddress(LINKADDRV4);
564cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v46lp.addRoute(new RouteInfo(GATEWAY1));
565cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v46lp.addDnsServer(DNS1);
566cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v46lp.isIPv4Provisioned());
567cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v46lp.isIPv6Provisioned());
568cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v46lp.isProvisioned());
569cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
570cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
5711ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline                LinkProperties.compareProvisioning(v4lp, v46lp));
5721ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
573cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v6lp, v46lp));
574cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.LOST_PROVISIONING,
575cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v46lp, v6lp));
5761ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline        assertEquals(ProvisioningChange.LOST_PROVISIONING,
5771ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline                LinkProperties.compareProvisioning(v46lp, v4lp));
578cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
579cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        // Check that losing and gaining a secondary router does not change
580cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        // the provisioning status.
581cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v6lp2 = new LinkProperties(v6lp);
582cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v6lp2.addRoute(new RouteInfo(GATEWAY62));
583cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v6lp2.isProvisioned());
584cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
585cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
586cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v6lp2, v6lp));
587cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
588cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v6lp, v6lp2));
589cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    }
590b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
591da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
592b36a3131d1b05efa176f79d318197499b2c45380Erik Kline    public void testIsReachable() {
593b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final LinkProperties v4lp = new LinkProperties();
594b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS1));
595b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS2));
596b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
597b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add an on-link route, making the on-link DNS server reachable,
598b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // but there is still no IPv4 address.
599b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.addRoute(new RouteInfo(
600b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16))));
601b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS1));
602b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS2));
603b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
604b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Adding an IPv4 address (right now, any IPv4 address) means we use
605b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // the routes to compute likely reachability.
606b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.addLinkAddress(new LinkAddress(ADDRV4, 16)));
607b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.isReachable(DNS1));
608b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS2));
609b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
610b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Adding a default route makes the off-link DNS server reachable.
611b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.addRoute(new RouteInfo(GATEWAY1)));
612b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.isReachable(DNS1));
613b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.isReachable(DNS2));
614b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
615b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final LinkProperties v6lp = new LinkProperties();
616b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final InetAddress kLinkLocalDns = NetworkUtils.numericToInetAddress("fe80::6:1");
617b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final InetAddress kLinkLocalDnsWithScope = NetworkUtils.numericToInetAddress("fe80::6:2%43");
618b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final InetAddress kOnLinkDns = NetworkUtils.numericToInetAddress("2001:db8:85a3::53");
619b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
620b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
621b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kOnLinkDns));
622b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
623b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
624b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add a link-local route, making the link-local DNS servers reachable. Because
625b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // we assume the presence of an IPv6 link-local address, link-local DNS servers
626b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // are considered reachable, but only those with a non-zero scope identifier.
627b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addRoute(new RouteInfo(
628b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                new IpPrefix(NetworkUtils.numericToInetAddress("fe80::"), 64))));
629b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
630b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
631b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kOnLinkDns));
632b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
633b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
634b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add a link-local address--nothing changes.
635b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addLinkAddress(LINKADDRV6LINKLOCAL));
636b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
637b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
638b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kOnLinkDns));
639b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
640b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
641b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add a global route on link, but no global address yet. DNS servers reachable
642b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // via a route that doesn't require a gateway: give them the benefit of the
643b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // doubt and hope the link-local source address suffices for communication.
644b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addRoute(new RouteInfo(
645b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                new IpPrefix(NetworkUtils.numericToInetAddress("2001:db8:85a3::"), 64))));
646b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
647b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
648b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kOnLinkDns));
649b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
650b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
651b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add a global address; the on-link global address DNS server is (still)
652b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // presumed reachable.
653b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addLinkAddress(new LinkAddress(ADDRV6, 64)));
654b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
655b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
656b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kOnLinkDns));
657b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
658b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
659b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Adding a default route makes the off-link DNS server reachable.
660b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addRoute(new RouteInfo(GATEWAY62)));
661b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
662b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
663b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kOnLinkDns));
664b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(DNS6));
66589b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
66689b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        // Check isReachable on stacked links. This requires that the source IP address be assigned
66789b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        // on the interface returned by the route lookup.
66889b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        LinkProperties stacked = new LinkProperties();
66989b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
67089b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        // Can't add a stacked link without an interface name.
67189b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        stacked.setInterfaceName("v4-test0");
67289b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        v6lp.addStackedLink(stacked);
67389b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
67489b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        InetAddress stackedAddress = Address("192.0.0.4");
67589b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32);
67689b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertFalse(v6lp.isReachable(stackedAddress));
67789b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        stacked.addLinkAddress(stackedLinkAddress);
67889b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertFalse(v6lp.isReachable(stackedAddress));
67989b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        stacked.addRoute(new RouteInfo(stackedLinkAddress));
68089b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertTrue(stacked.isReachable(stackedAddress));
68189b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertTrue(v6lp.isReachable(stackedAddress));
68289b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
68389b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertFalse(v6lp.isReachable(DNS1));
68489b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        stacked.addRoute(new RouteInfo((IpPrefix) null, stackedAddress));
68589b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertTrue(v6lp.isReachable(DNS1));
686b36a3131d1b05efa176f79d318197499b2c45380Erik Kline    }
6871bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
688da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
6891bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu    public void testLinkPropertiesEnsureDirectlyConnectedRoutes() {
6901bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // IPv4 case: no route added initially
6911bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        LinkProperties rmnet0 = new LinkProperties();
6921bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet0.setInterfaceName("rmnet0");
6931bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet0.addLinkAddress(new LinkAddress("10.0.0.2/8"));
6941bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo directRoute0 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
6951bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet0.getInterfaceName());
6961bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
6971bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // Since no routes is added explicitly, getAllRoutes() should return empty.
6981bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertTrue(rmnet0.getAllRoutes().isEmpty());
6991bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet0.ensureDirectlyConnectedRoutes();
7001bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // ensureDirectlyConnectedRoutes() should have added the missing local route.
7011bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Collections.singletonList(directRoute0), rmnet0.getAllRoutes());
7021bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7031bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // IPv4 case: both direct and default routes added initially
7041bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        LinkProperties rmnet1 = new LinkProperties();
7051bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.setInterfaceName("rmnet1");
7061bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
7071bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null,
7081bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                NetworkUtils.numericToInetAddress("10.0.0.1"), rmnet1.getInterfaceName());
7091bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
7101bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet1.getInterfaceName());
7111bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.addRoute(defaultRoute1);
7121bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.addRoute(directRoute1);
7131bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7141bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // Check added routes
7151bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
7161bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // ensureDirectlyConnectedRoutes() shouldn't change the routes since direct connected
7171bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // route is already part of the configuration.
7181bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.ensureDirectlyConnectedRoutes();
7191bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
7201bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7211bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // IPv6 case: only default routes added initially
7221bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        LinkProperties rmnet2 = new LinkProperties();
7231bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.setInterfaceName("rmnet2");
7241bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
7251bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
7261bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null,
7271bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                NetworkUtils.numericToInetAddress("2001:db8::1"), rmnet2.getInterfaceName());
7281bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
7291bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet2.getInterfaceName());
7301bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo linkLocalRoute2 = new RouteInfo(new IpPrefix("fe80::/64"), null,
7311bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet2.getInterfaceName());
7321bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.addRoute(defaultRoute2);
7331bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7341bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Arrays.asList(defaultRoute2), rmnet2.getAllRoutes());
7351bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.ensureDirectlyConnectedRoutes();
7361bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Arrays.asList(defaultRoute2, directRoute2, linkLocalRoute2),
7371bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet2.getAllRoutes());
7381bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7391bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // Corner case: no interface name
7401bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        LinkProperties rmnet3 = new LinkProperties();
7411bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet3.addLinkAddress(new LinkAddress("192.168.0.2/24"));
7421bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo directRoute3 = new RouteInfo(new IpPrefix("192.168.0.0/24"), null,
7431bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet3.getInterfaceName());
7441bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7451bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertTrue(rmnet3.getAllRoutes().isEmpty());
7461bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet3.ensureDirectlyConnectedRoutes();
7471bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Collections.singletonList(directRoute3), rmnet3.getAllRoutes());
7481bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7491bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu    }
7501bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
751da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
7522fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu    public void testCompareResult() {
7532fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        // Either adding or removing items
754da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1),
7552fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu                Arrays.asList(2, 3, 4), new ArrayList<>());
756da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2), Arrays.asList(3, 2, 1, 4),
7572fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu                new ArrayList<>(), Arrays.asList(3, 4));
7582fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
7592fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
7602fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        // adding and removing items at the same time
761da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(2, 3, 4, 5),
7622fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu                Arrays.asList(1), Arrays.asList(5));
763da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6),
7642fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu                Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6));
7652fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
7662fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        // null cases
767da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2, 3), null, Arrays.asList(1, 2, 3), new ArrayList<>());
768da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(null, Arrays.asList(3, 2, 1), new ArrayList<>(), Arrays.asList(1, 2, 3));
769da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(null, null, new ArrayList<>(), new ArrayList<>());
7702fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu    }
7712fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
7721bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu    private void assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual) {
7731bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        Set<RouteInfo> expectedSet = new ArraySet<>(expected);
7741bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        Set<RouteInfo> actualSet = new ArraySet<>(actual);
7751bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // Duplicated entries in actual routes are considered failures
7761bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEquals(actual.size(), actualSet.size());
7771bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7781bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEquals(expectedSet, actualSet);
7791bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu    }
7802fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
781da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    private <T> void compareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved,
7829dac106b13ecd96de97c5b5ac41c6c3a55c3cea3Rubin Xu            List<T> expectAdded) {
7839dac106b13ecd96de97c5b5ac41c6c3a55c3cea3Rubin Xu        CompareResult<T> result = new CompareResult<>(oldItems, newItems);
7842fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        assertEquals(new ArraySet<>(expectAdded), new ArraySet<>(result.added));
7852fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        assertEquals(new ArraySet<>(expectRemoved), (new ArraySet<>(result.removed)));
7862fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu    }
7874e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang}
788