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;
309419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jeanimport android.os.Parcel;
31da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport android.support.test.filters.SmallTest;
32da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport android.support.test.runner.AndroidJUnit4;
3334385d352da19805ae948215e2edbeedd16b7941Elliott Hughesimport android.system.OsConstants;
341bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport android.util.ArraySet;
351bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
364e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wangimport java.net.InetAddress;
372fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xuimport java.util.ArrayList;
381bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport java.util.Arrays;
391bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport java.util.Collection;
401bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport java.util.Collections;
412fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xuimport java.util.List;
421bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xuimport java.util.Set;
434e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
44da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport org.junit.Test;
45da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichiimport org.junit.runner.RunWith;
46b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
47da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi@RunWith(AndroidJUnit4.class)
48da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi@SmallTest
49da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichipublic class LinkPropertiesTest {
503f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1");
513f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress(
523f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti            "2001:0db8:85a3:0000:0000:8a2e:0370:7334");
533f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress DNS1 = NetworkUtils.numericToInetAddress("75.208.7.1");
543f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress DNS2 = NetworkUtils.numericToInetAddress("69.78.7.1");
55d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    private static InetAddress DNS6 = NetworkUtils.numericToInetAddress("2001:4860:4860::8888");
563f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress GATEWAY1 = NetworkUtils.numericToInetAddress("75.208.8.1");
573f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static InetAddress GATEWAY2 = NetworkUtils.numericToInetAddress("69.78.8.1");
58cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    private static InetAddress GATEWAY61 = NetworkUtils.numericToInetAddress("fe80::6:0000:613");
59cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    private static InetAddress GATEWAY62 = NetworkUtils.numericToInetAddress("fe80::6:2222");
604e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    private static String NAME = "qmi0";
619d9b74a900696191048aa97cc3c854072640428bsy.yun    private static int MTU = 1500;
624e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
633f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static LinkAddress LINKADDRV4 = new LinkAddress(ADDRV4, 32);
643f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti    private static LinkAddress LINKADDRV6 = new LinkAddress(ADDRV6, 128);
6576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti    private static LinkAddress LINKADDRV6LINKLOCAL = new LinkAddress("fe80::1/64");
663f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti
6789b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti    // TODO: replace all calls to NetworkUtils.numericToInetAddress with calls to this method.
6889b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti    private InetAddress Address(String addrString) {
6989b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        return NetworkUtils.numericToInetAddress(addrString);
7089b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti    }
7189b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
72213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti    public void assertLinkPropertiesEqual(LinkProperties source, LinkProperties target) {
73213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        // Check implementation of equals(), element by element.
74213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalInterfaceName(target));
75213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalInterfaceName(source));
76213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
77213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalAddresses(target));
78213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalAddresses(source));
79213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
80213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalDnses(target));
81213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalDnses(source));
82213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
83d920134258e385250f37d73205139b477beb7afcdalyk        assertTrue(source.isIdenticalPrivateDns(target));
84d920134258e385250f37d73205139b477beb7afcdalyk        assertTrue(target.isIdenticalPrivateDns(source));
85d920134258e385250f37d73205139b477beb7afcdalyk
869419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        assertTrue(source.isIdenticalValidatedPrivateDnses(target));
879419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        assertTrue(target.isIdenticalValidatedPrivateDnses(source));
889419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean
89213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalRoutes(target));
90213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalRoutes(source));
91213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
92213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalHttpProxy(target));
93213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalHttpProxy(source));
94213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
95213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.isIdenticalStackedLinks(target));
96213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.isIdenticalStackedLinks(source));
97213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
989d9b74a900696191048aa97cc3c854072640428bsy.yun        assertTrue(source.isIdenticalMtu(target));
999d9b74a900696191048aa97cc3c854072640428bsy.yun        assertTrue(target.isIdenticalMtu(source));
1009d9b74a900696191048aa97cc3c854072640428bsy.yun
101d920134258e385250f37d73205139b477beb7afcdalyk        assertTrue(source.isIdenticalTcpBufferSizes(target));
102d920134258e385250f37d73205139b477beb7afcdalyk        assertTrue(target.isIdenticalTcpBufferSizes(source));
103d920134258e385250f37d73205139b477beb7afcdalyk
104213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        // Check result of equals().
105213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(source.equals(target));
106213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertTrue(target.equals(source));
107213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
108213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        // Check hashCode.
109213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertEquals(source.hashCode(), target.hashCode());
110213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti    }
111213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti
112da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
1134e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    public void testEqualsNull() {
1144e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        LinkProperties source = new LinkProperties();
1154e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        LinkProperties target = new LinkProperties();
1164e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
1174e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang        assertFalse(source == target);
118213f98b6fe81c73f0d182fb5af312d4ce4a08041Lorenzo Colitti        assertLinkPropertiesEqual(source, target);
1194e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
1204e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
121da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
122da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    public void testEqualsSameOrder() throws Exception {
123da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties source = new LinkProperties();
124da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.setInterfaceName(NAME);
125da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 link addresses
126da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV4);
127da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV6);
128da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 dnses
129da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addDnsServer(DNS1);
130da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addDnsServer(DNS2);
131da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 gateways
132da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addRoute(new RouteInfo(GATEWAY1));
133da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addRoute(new RouteInfo(GATEWAY2));
134da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.setMtu(MTU);
135da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
136da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties target = new LinkProperties();
137da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
138da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // All fields are same
139da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
140da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
141da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
142da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
143da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
144da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
145da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
146da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
147da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
148da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertLinkPropertiesEqual(source, target);
149da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
150da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
151da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change Interface Name
152da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName("qmi1");
153da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
154da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
155da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
156da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
157da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
158da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
159da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
160da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
161da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
162da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
163da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
164da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change link addresses
165da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(new LinkAddress(
166da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi                NetworkUtils.numericToInetAddress("75.208.6.2"), 32));
167da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
168da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
169da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
170da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
171da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
172da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
173da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
174da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
175da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
176da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
177da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
178da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
179da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change dnses
180da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(NetworkUtils.numericToInetAddress("75.208.7.2"));
181da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
182da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
183da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
184da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
185da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
186da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
187da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
188da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
189da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
190da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
191da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
192da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
193da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change gateway
194da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(NetworkUtils.numericToInetAddress("75.208.8.2")));
195da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
196da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
197da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
198da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
199da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.clear();
200da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
201da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
202da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
203da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
204da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
205da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
206da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
207da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // change mtu
208da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(1440);
209da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertFalse(source.equals(target));
2104e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
2114e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
212da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
213da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    public void testEqualsDifferentOrder() throws Exception {
214da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties source = new LinkProperties();
215da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.setInterfaceName(NAME);
216da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 link addresses
217da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV4);
218da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV6);
219da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 dnses
220da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addDnsServer(DNS1);
221da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addDnsServer(DNS2);
222da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 2 gateways
223da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addRoute(new RouteInfo(GATEWAY1));
224da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addRoute(new RouteInfo(GATEWAY2));
225da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.setMtu(MTU);
226da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
227da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties target = new LinkProperties();
228da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // Exchange order
229da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setInterfaceName(NAME);
230da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
231da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
232da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS2);
233da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addDnsServer(DNS1);
234da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY2));
235da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addRoute(new RouteInfo(GATEWAY1));
236da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.setMtu(MTU);
237da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
238da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertLinkPropertiesEqual(source, target);
2394e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
2404e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
241da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
242da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    public void testEqualsDuplicated() throws Exception {
243da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties source = new LinkProperties();
244da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 3 link addresses, eg, [A, A, B]
245da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV4);
246da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV4);
247da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        source.addLinkAddress(LINKADDRV6);
248da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
249da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        LinkProperties target = new LinkProperties();
250da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        // set 3 link addresses, eg, [A, B, B]
251da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV4);
252da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
253da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        target.addLinkAddress(LINKADDRV6);
254da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi
255da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        assertLinkPropertiesEqual(source, target);
2564e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang    }
2574e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang
2581994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti    private void assertAllRoutesHaveInterface(String iface, LinkProperties lp) {
2591994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        for (RouteInfo r : lp.getRoutes()) {
2601994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti            assertEquals(iface, r.getInterface());
2611994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        }
2621994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti    }
2631994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
264da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
2651994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti    public void testRouteInterfaces() {
2661994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        LinkAddress prefix = new LinkAddress(
2671994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti            NetworkUtils.numericToInetAddress("2001:db8::"), 32);
2683f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti        InetAddress address = ADDRV6;
2691994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2701994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Add a route with no interface to a LinkProperties with no interface. No errors.
2711994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        LinkProperties lp = new LinkProperties();
2721994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        RouteInfo r = new RouteInfo(prefix, address, null);
2731603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        assertTrue(lp.addRoute(r));
2741994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertEquals(1, lp.getRoutes().size());
2751994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface(null, lp);
2761994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2771603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        // Adding the same route twice has no effect.
2781603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        assertFalse(lp.addRoute(r));
2791603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        assertEquals(1, lp.getRoutes().size());
2801603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti
2811603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        // Add a route with an interface. Expect an exception.
2821994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        r = new RouteInfo(prefix, address, "wlan0");
2831994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        try {
2841994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti          lp.addRoute(r);
2851994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti          fail("Adding wlan0 route to LP with no interface, expect exception");
2861994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        } catch (IllegalArgumentException expected) {}
2871994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2881994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Change the interface name. All the routes should change their interface name too.
2891994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp.setInterfaceName("rmnet0");
2901994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("rmnet0", lp);
2911994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2921994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Now add a route with the wrong interface. This causes an exception too.
2931994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        try {
2941994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti          lp.addRoute(r);
2951994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti          fail("Adding wlan0 route to rmnet0 LP, expect exception");
2961994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        } catch (IllegalArgumentException expected) {}
2971994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
2981994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // If the interface name matches, the route is added.
2991603eadc5ad2f6d3e912ca0f20ec1bbc0b81fe01Lorenzo Colitti        r = new RouteInfo(prefix, null, "wlan0");
3001994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp.setInterfaceName("wlan0");
3011994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp.addRoute(r);
3021994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertEquals(2, lp.getRoutes().size());
3031994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("wlan0", lp);
3041994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
3051994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Routes with null interfaces are converted to wlan0.
3063f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti        r = RouteInfo.makeHostRoute(ADDRV6, null);
3071994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp.addRoute(r);
3081994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertEquals(3, lp.getRoutes().size());
3091994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("wlan0", lp);
3101994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
3111994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        // Check comparisons work.
3121994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        LinkProperties lp2 = new LinkProperties(lp);
3131994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("wlan0", lp);
314d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(0, lp.compareAllRoutes(lp2).added.size());
315d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(0, lp.compareAllRoutes(lp2).removed.size());
3161994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti
3171994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        lp2.setInterfaceName("p2p0");
3181994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti        assertAllRoutesHaveInterface("p2p0", lp2);
319d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(3, lp.compareAllRoutes(lp2).added.size());
320d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(3, lp.compareAllRoutes(lp2).removed.size());
321b91e50c266a7eb9dd6f8171deb497931ef7aef76Lorenzo Colitti    }
322419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
323da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
324419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti    public void testStackedInterfaces() {
325419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        LinkProperties rmnet0 = new LinkProperties();
326419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        rmnet0.setInterfaceName("rmnet0");
3273f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti        rmnet0.addLinkAddress(LINKADDRV6);
328419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
329419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        LinkProperties clat4 = new LinkProperties();
330419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        clat4.setInterfaceName("clat4");
3313f1e1b2ce407684519f8bd070c931940fd33db4fLorenzo Colitti        clat4.addLinkAddress(LINKADDRV4);
332419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
333419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        assertEquals(0, rmnet0.getStackedLinks().size());
334d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAddresses().size());
335d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getLinkAddresses().size());
336d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAllAddresses().size());
337d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAllLinkAddresses().size());
338d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
339419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        rmnet0.addStackedLink(clat4);
340419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        assertEquals(1, rmnet0.getStackedLinks().size());
341d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAddresses().size());
342d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getLinkAddresses().size());
343d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(2, rmnet0.getAllAddresses().size());
344d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(2, rmnet0.getAllLinkAddresses().size());
345d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
346419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        rmnet0.addStackedLink(clat4);
347419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        assertEquals(1, rmnet0.getStackedLinks().size());
348d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getAddresses().size());
349d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(1, rmnet0.getLinkAddresses().size());
350d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(2, rmnet0.getAllAddresses().size());
351d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti        assertEquals(2, rmnet0.getAllLinkAddresses().size());
352d1e0fae2bc5c98b1f00b185d7be7219dc7e1d0f7Lorenzo Colitti
353419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        assertEquals(0, clat4.getStackedLinks().size());
354419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti
355419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        // Modify an item in the returned collection to see what happens.
356419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties link : rmnet0.getStackedLinks()) {
357419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            if (link.getInterfaceName().equals("clat4")) {
358419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti               link.setInterfaceName("newname");
359419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            }
360419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
361419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        for (LinkProperties link : rmnet0.getStackedLinks()) {
362419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti            assertFalse("newname".equals(link.getInterfaceName()));
363419a4ce9e461177d75eca5fd71fc8c275969e479Lorenzo Colitti        }
3644faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
365f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti        assertTrue(rmnet0.removeStackedLink("clat4"));
3664faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(0, rmnet0.getStackedLinks().size());
3674faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(1, rmnet0.getAddresses().size());
3684faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(1, rmnet0.getLinkAddresses().size());
3694faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(1, rmnet0.getAllAddresses().size());
3704faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertEquals(1, rmnet0.getAllLinkAddresses().size());
3714faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
372f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti        assertFalse(rmnet0.removeStackedLink("clat4"));
3734faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    }
3744faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
37564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    private LinkAddress getFirstLinkAddress(LinkProperties lp) {
37664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        return lp.getLinkAddresses().iterator().next();
37764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti    }
37864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
379da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
3804faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti    public void testAddressMethods() {
3814faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        LinkProperties lp = new LinkProperties();
3824faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
3834faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // No addresses.
3844faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
38576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
3864faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
3874faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Addresses on stacked links don't count.
3884faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        LinkProperties stacked = new LinkProperties();
3894faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        stacked.setInterfaceName("stacked");
3904faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        lp.addStackedLink(stacked);
3914faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        stacked.addLinkAddress(LINKADDRV4);
3924faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        stacked.addLinkAddress(LINKADDRV6);
3934faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(stacked.hasIPv4Address());
39476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(stacked.hasGlobalIPv6Address());
3954faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
39676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
397f3cab63ef2248aebf2c931cd1e84d5739791fa50Lorenzo Colitti        lp.removeStackedLink("stacked");
3984faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
39976ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
4004faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
4014faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Addresses on the base link.
4024faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Check the return values of hasIPvXAddress and ensure the add/remove methods return true
4034faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // iff something changes.
40464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(0, lp.getLinkAddresses().size());
4054faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.addLinkAddress(LINKADDRV6));
40664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
4074faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
40876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.hasGlobalIPv6Address());
4094faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
4104faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.removeLinkAddress(LINKADDRV6));
41164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(0, lp.getLinkAddresses().size());
41276ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
41376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.addLinkAddress(LINKADDRV6LINKLOCAL));
41464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
41576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
41676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
41776ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.addLinkAddress(LINKADDRV4));
41876ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertEquals(2, lp.getLinkAddresses().size());
4194faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.hasIPv4Address());
42076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertFalse(lp.hasGlobalIPv6Address());
4214faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
4224faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.addLinkAddress(LINKADDRV6));
42376ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertEquals(3, lp.getLinkAddresses().size());
42476ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.hasIPv4Address());
42576ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.hasGlobalIPv6Address());
42676ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti
42776ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.removeLinkAddress(LINKADDRV6LINKLOCAL));
42864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(2, lp.getLinkAddresses().size());
4294faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.hasIPv4Address());
43076ea6c68d3222441970ef98079ba30710ac8c595Lorenzo Colitti        assertTrue(lp.hasGlobalIPv6Address());
4314faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti
4324faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Adding an address twice has no effect.
4334faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        // Removing an address that's not present has no effect.
4344faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.addLinkAddress(LINKADDRV4));
43564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(2, lp.getLinkAddresses().size());
4364faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.hasIPv4Address());
4374faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertTrue(lp.removeLinkAddress(LINKADDRV4));
43864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
4394faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.hasIPv4Address());
4404faa027df03c241c92a12a437f20767ab4d6ee64Lorenzo Colitti        assertFalse(lp.removeLinkAddress(LINKADDRV4));
44164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
44264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
44364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Adding an address that's already present but with different properties causes the
44464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // existing address to be updated and returns true.
44564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Start with only LINKADDRV6.
44664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
44764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(LINKADDRV6, getFirstLinkAddress(lp));
44864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
44964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Create a LinkAddress object for the same address, but with different flags.
45064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        LinkAddress deprecated = new LinkAddress(ADDRV6, 128,
45164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti                OsConstants.IFA_F_DEPRECATED, OsConstants.RT_SCOPE_UNIVERSE);
45264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertTrue(deprecated.isSameAddressAs(LINKADDRV6));
45364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertFalse(deprecated.equals(LINKADDRV6));
45464483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
45564483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Check that adding it updates the existing address instead of adding a new one.
45664483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertTrue(lp.addLinkAddress(deprecated));
45764483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(1, lp.getLinkAddresses().size());
45864483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(deprecated, getFirstLinkAddress(lp));
45964483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertFalse(LINKADDRV6.equals(getFirstLinkAddress(lp)));
46064483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti
46164483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        // Removing LINKADDRV6 removes deprecated, because removing addresses ignores properties.
46264483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertTrue(lp.removeLinkAddress(LINKADDRV6));
46364483947fdb03bf838e317ac0a4af5e0f53a5bbfLorenzo Colitti        assertEquals(0, lp.getLinkAddresses().size());
4641994bc14ab9fd3a3c5dca8851cfc0042bcb25d46Lorenzo Colitti    }
46522f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
466da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
46722f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    public void testSetLinkAddresses() {
46822f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        LinkProperties lp = new LinkProperties();
46922f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        lp.addLinkAddress(LINKADDRV4);
47022f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        lp.addLinkAddress(LINKADDRV6);
47122f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
47222f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        LinkProperties lp2 = new LinkProperties();
47322f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        lp2.addLinkAddress(LINKADDRV6);
47422f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
47522f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        assertFalse(lp.equals(lp2));
47622f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti
47722f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        lp2.setLinkAddresses(lp.getLinkAddresses());
47822f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti        assertTrue(lp.equals(lp));
47922f407b11e11cfdb336e06e8c0d4a7ef1eafc783Lorenzo Colitti    }
480d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
481da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
482d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    public void testIsProvisioned() {
483d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        LinkProperties lp4 = new LinkProperties();
484d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v4only:empty", lp4.isProvisioned());
485d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp4.addLinkAddress(LINKADDRV4);
486d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v4only:addr-only", lp4.isProvisioned());
487d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp4.addDnsServer(DNS1);
488d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v4only:addr+dns", lp4.isProvisioned());
489d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp4.addRoute(new RouteInfo(GATEWAY1));
490d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("v4only:addr+dns+route", lp4.isProvisioned());
491cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("v4only:addr+dns+route", lp4.isIPv4Provisioned());
492cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("v4only:addr+dns+route", lp4.isIPv6Provisioned());
493d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
494d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        LinkProperties lp6 = new LinkProperties();
495d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v6only:empty", lp6.isProvisioned());
496d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp6.addLinkAddress(LINKADDRV6LINKLOCAL);
497d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v6only:fe80-only", lp6.isProvisioned());
498d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp6.addDnsServer(DNS6);
499d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v6only:fe80+dns", lp6.isProvisioned());
500cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        lp6.addRoute(new RouteInfo(GATEWAY61));
501d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("v6only:fe80+dns+route", lp6.isProvisioned());
502d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp6.addLinkAddress(LINKADDRV6);
503cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("v6only:fe80+global+dns+route", lp6.isIPv6Provisioned());
504d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("v6only:fe80+global+dns+route", lp6.isProvisioned());
505d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp6.removeLinkAddress(LINKADDRV6LINKLOCAL);
506cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("v6only:global+dns+route", lp6.isIPv4Provisioned());
507cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("v6only:global+dns+route", lp6.isIPv6Provisioned());
508d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("v6only:global+dns+route", lp6.isProvisioned());
509d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
510d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        LinkProperties lp46 = new LinkProperties();
511d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addLinkAddress(LINKADDRV4);
512d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addLinkAddress(LINKADDRV6);
513d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addDnsServer(DNS1);
514d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addDnsServer(DNS6);
515d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("dualstack:missing-routes", lp46.isProvisioned());
516d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        lp46.addRoute(new RouteInfo(GATEWAY1));
517cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("dualstack:v4-provisioned", lp46.isIPv4Provisioned());
518cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("dualstack:v4-provisioned", lp46.isIPv6Provisioned());
519d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("dualstack:v4-provisioned", lp46.isProvisioned());
520cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        lp46.addRoute(new RouteInfo(GATEWAY61));
521cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("dualstack:both-provisioned", lp46.isIPv4Provisioned());
522cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue("dualstack:both-provisioned", lp46.isIPv6Provisioned());
523d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertTrue("dualstack:both-provisioned", lp46.isProvisioned());
524d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline
525d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        // A link with an IPv6 address and default route, but IPv4 DNS server.
526d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        LinkProperties mixed = new LinkProperties();
527d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        mixed.addLinkAddress(LINKADDRV6);
528d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        mixed.addDnsServer(DNS1);
529cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        mixed.addRoute(new RouteInfo(GATEWAY61));
530cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("mixed:addr6+route6+dns4", mixed.isIPv4Provisioned());
531cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse("mixed:addr6+route6+dns4", mixed.isIPv6Provisioned());
532d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline        assertFalse("mixed:addr6+route6+dns4", mixed.isProvisioned());
533d3b9fd33c69fa4fb844238c90b1fd343052946d9Erik Kline    }
534cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
535da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
536cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    public void testCompareProvisioning() {
537cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v4lp = new LinkProperties();
538cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v4lp.addLinkAddress(LINKADDRV4);
539cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v4lp.addRoute(new RouteInfo(GATEWAY1));
540cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v4lp.addDnsServer(DNS1);
541cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v4lp.isProvisioned());
542cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
543cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v4r = new LinkProperties(v4lp);
544cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v4r.removeDnsServer(DNS1);
545cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse(v4r.isProvisioned());
546cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
547cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_NOT_PROVISIONED,
548cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v4r, v4r));
549cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.LOST_PROVISIONING,
550cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v4lp, v4r));
551cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.GAINED_PROVISIONING,
552cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v4r, v4lp));
553cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
554cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v4lp, v4lp));
555cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
556cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        // Check that losing IPv4 provisioning on a dualstack network is
557cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        // seen as a total loss of provisioning.
558cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v6lp = new LinkProperties();
559cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v6lp.addLinkAddress(LINKADDRV6);
560cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v6lp.addRoute(new RouteInfo(GATEWAY61));
561cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v6lp.addDnsServer(DNS6);
562cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertFalse(v6lp.isIPv4Provisioned());
563cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v6lp.isIPv6Provisioned());
564cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v6lp.isProvisioned());
565cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
566cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v46lp = new LinkProperties(v6lp);
567cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v46lp.addLinkAddress(LINKADDRV4);
568cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v46lp.addRoute(new RouteInfo(GATEWAY1));
569cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v46lp.addDnsServer(DNS1);
570cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v46lp.isIPv4Provisioned());
571cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v46lp.isIPv6Provisioned());
572cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v46lp.isProvisioned());
573cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
574cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
5751ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline                LinkProperties.compareProvisioning(v4lp, v46lp));
5761ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
577cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v6lp, v46lp));
578cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.LOST_PROVISIONING,
579cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v46lp, v6lp));
5801ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline        assertEquals(ProvisioningChange.LOST_PROVISIONING,
5811ad4e22534b3607ecca849b06efa4547dd58be63Erik Kline                LinkProperties.compareProvisioning(v46lp, v4lp));
582cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
583cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        // Check that losing and gaining a secondary router does not change
584cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        // the provisioning status.
585cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        LinkProperties v6lp2 = new LinkProperties(v6lp);
586cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        v6lp2.addRoute(new RouteInfo(GATEWAY62));
587cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertTrue(v6lp2.isProvisioned());
588cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline
589cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
590cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v6lp2, v6lp));
591cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline        assertEquals(ProvisioningChange.STILL_PROVISIONED,
592cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline                LinkProperties.compareProvisioning(v6lp, v6lp2));
593cd7ed16f00d243568e3b73b7fc7f0f94cfebe8ceErik Kline    }
594b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
595da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
596b36a3131d1b05efa176f79d318197499b2c45380Erik Kline    public void testIsReachable() {
597b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final LinkProperties v4lp = new LinkProperties();
598b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS1));
599b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS2));
600b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
601b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add an on-link route, making the on-link DNS server reachable,
602b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // but there is still no IPv4 address.
603b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.addRoute(new RouteInfo(
604b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                new IpPrefix(NetworkUtils.numericToInetAddress("75.208.0.0"), 16))));
605b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS1));
606b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS2));
607b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
608b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Adding an IPv4 address (right now, any IPv4 address) means we use
609b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // the routes to compute likely reachability.
610b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.addLinkAddress(new LinkAddress(ADDRV4, 16)));
611b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.isReachable(DNS1));
612b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v4lp.isReachable(DNS2));
613b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
614b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Adding a default route makes the off-link DNS server reachable.
615b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.addRoute(new RouteInfo(GATEWAY1)));
616b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.isReachable(DNS1));
617b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v4lp.isReachable(DNS2));
618b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
619b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final LinkProperties v6lp = new LinkProperties();
620b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final InetAddress kLinkLocalDns = NetworkUtils.numericToInetAddress("fe80::6:1");
621b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final InetAddress kLinkLocalDnsWithScope = NetworkUtils.numericToInetAddress("fe80::6:2%43");
622b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        final InetAddress kOnLinkDns = NetworkUtils.numericToInetAddress("2001:db8:85a3::53");
623b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
624b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDnsWithScope));
625b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kOnLinkDns));
626b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
627b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
628b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add a link-local route, making the link-local DNS servers reachable. Because
629b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // we assume the presence of an IPv6 link-local address, link-local DNS servers
630b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // are considered reachable, but only those with a non-zero scope identifier.
631b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addRoute(new RouteInfo(
632b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                new IpPrefix(NetworkUtils.numericToInetAddress("fe80::"), 64))));
633b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
634b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
635b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kOnLinkDns));
636b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
637b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
638b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add a link-local address--nothing changes.
639b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addLinkAddress(LINKADDRV6LINKLOCAL));
640b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
641b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
642b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kOnLinkDns));
643b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
644b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
645b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add a global route on link, but no global address yet. DNS servers reachable
646b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // via a route that doesn't require a gateway: give them the benefit of the
647b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // doubt and hope the link-local source address suffices for communication.
648b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addRoute(new RouteInfo(
649b36a3131d1b05efa176f79d318197499b2c45380Erik Kline                new IpPrefix(NetworkUtils.numericToInetAddress("2001:db8:85a3::"), 64))));
650b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
651b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
652b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kOnLinkDns));
653b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
654b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
655b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Add a global address; the on-link global address DNS server is (still)
656b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // presumed reachable.
657b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addLinkAddress(new LinkAddress(ADDRV6, 64)));
658b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
659b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
660b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kOnLinkDns));
661b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(DNS6));
662b36a3131d1b05efa176f79d318197499b2c45380Erik Kline
663b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        // Adding a default route makes the off-link DNS server reachable.
664b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.addRoute(new RouteInfo(GATEWAY62)));
665b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertFalse(v6lp.isReachable(kLinkLocalDns));
666b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kLinkLocalDnsWithScope));
667b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(kOnLinkDns));
668b36a3131d1b05efa176f79d318197499b2c45380Erik Kline        assertTrue(v6lp.isReachable(DNS6));
66989b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
67089b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        // Check isReachable on stacked links. This requires that the source IP address be assigned
67189b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        // on the interface returned by the route lookup.
67289b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        LinkProperties stacked = new LinkProperties();
67389b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
67489b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        // Can't add a stacked link without an interface name.
67589b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        stacked.setInterfaceName("v4-test0");
67689b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        v6lp.addStackedLink(stacked);
67789b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
67889b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        InetAddress stackedAddress = Address("192.0.0.4");
67989b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        LinkAddress stackedLinkAddress = new LinkAddress(stackedAddress, 32);
68089b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertFalse(v6lp.isReachable(stackedAddress));
68189b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        stacked.addLinkAddress(stackedLinkAddress);
68289b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertFalse(v6lp.isReachable(stackedAddress));
68389b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        stacked.addRoute(new RouteInfo(stackedLinkAddress));
68489b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertTrue(stacked.isReachable(stackedAddress));
68589b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertTrue(v6lp.isReachable(stackedAddress));
68689b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti
68789b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertFalse(v6lp.isReachable(DNS1));
68889b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        stacked.addRoute(new RouteInfo((IpPrefix) null, stackedAddress));
68989b6392046865e5ceaead5238b6f366cd5e9d3c5Lorenzo Colitti        assertTrue(v6lp.isReachable(DNS1));
690b36a3131d1b05efa176f79d318197499b2c45380Erik Kline    }
6911bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
692da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
6931bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu    public void testLinkPropertiesEnsureDirectlyConnectedRoutes() {
6941bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // IPv4 case: no route added initially
6951bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        LinkProperties rmnet0 = new LinkProperties();
6961bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet0.setInterfaceName("rmnet0");
6971bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet0.addLinkAddress(new LinkAddress("10.0.0.2/8"));
6981bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo directRoute0 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
6991bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet0.getInterfaceName());
7001bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7011bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // Since no routes is added explicitly, getAllRoutes() should return empty.
7021bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertTrue(rmnet0.getAllRoutes().isEmpty());
7031bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet0.ensureDirectlyConnectedRoutes();
7041bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // ensureDirectlyConnectedRoutes() should have added the missing local route.
7051bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Collections.singletonList(directRoute0), rmnet0.getAllRoutes());
7061bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7071bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // IPv4 case: both direct and default routes added initially
7081bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        LinkProperties rmnet1 = new LinkProperties();
7091bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.setInterfaceName("rmnet1");
7101bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.addLinkAddress(new LinkAddress("10.0.0.3/8"));
7111bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo defaultRoute1 = new RouteInfo((IpPrefix) null,
7121bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                NetworkUtils.numericToInetAddress("10.0.0.1"), rmnet1.getInterfaceName());
7131bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo directRoute1 = new RouteInfo(new IpPrefix("10.0.0.0/8"), null,
7141bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet1.getInterfaceName());
7151bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.addRoute(defaultRoute1);
7161bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.addRoute(directRoute1);
7171bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7181bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // Check added routes
7191bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
7201bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // ensureDirectlyConnectedRoutes() shouldn't change the routes since direct connected
7211bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // route is already part of the configuration.
7221bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet1.ensureDirectlyConnectedRoutes();
7231bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Arrays.asList(defaultRoute1, directRoute1), rmnet1.getAllRoutes());
7241bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7251bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // IPv6 case: only default routes added initially
7261bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        LinkProperties rmnet2 = new LinkProperties();
7271bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.setInterfaceName("rmnet2");
7281bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.addLinkAddress(new LinkAddress("fe80::cafe/64"));
7291bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.addLinkAddress(new LinkAddress("2001:db8::2/64"));
7301bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo defaultRoute2 = new RouteInfo((IpPrefix) null,
7311bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                NetworkUtils.numericToInetAddress("2001:db8::1"), rmnet2.getInterfaceName());
7321bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo directRoute2 = new RouteInfo(new IpPrefix("2001:db8::/64"), null,
7331bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet2.getInterfaceName());
7341bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo linkLocalRoute2 = new RouteInfo(new IpPrefix("fe80::/64"), null,
7351bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet2.getInterfaceName());
7361bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.addRoute(defaultRoute2);
7371bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7381bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Arrays.asList(defaultRoute2), rmnet2.getAllRoutes());
7391bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet2.ensureDirectlyConnectedRoutes();
7401bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Arrays.asList(defaultRoute2, directRoute2, linkLocalRoute2),
7411bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet2.getAllRoutes());
7421bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7431bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // Corner case: no interface name
7441bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        LinkProperties rmnet3 = new LinkProperties();
7451bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet3.addLinkAddress(new LinkAddress("192.168.0.2/24"));
7461bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        RouteInfo directRoute3 = new RouteInfo(new IpPrefix("192.168.0.0/24"), null,
7471bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu                rmnet3.getInterfaceName());
7481bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7491bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertTrue(rmnet3.getAllRoutes().isEmpty());
7501bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        rmnet3.ensureDirectlyConnectedRoutes();
7511bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEqualRoutes(Collections.singletonList(directRoute3), rmnet3.getAllRoutes());
7521bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7531bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu    }
7541bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
755da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    @Test
7562fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu    public void testCompareResult() {
7572fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        // Either adding or removing items
758da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1),
7592fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu                Arrays.asList(2, 3, 4), new ArrayList<>());
760da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2), Arrays.asList(3, 2, 1, 4),
7612fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu                new ArrayList<>(), Arrays.asList(3, 4));
7622fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
7632fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
7642fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        // adding and removing items at the same time
765da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(2, 3, 4, 5),
7662fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu                Arrays.asList(1), Arrays.asList(5));
767da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6),
7682fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu                Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6));
7692fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
7702fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        // null cases
771da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(Arrays.asList(1, 2, 3), null, Arrays.asList(1, 2, 3), new ArrayList<>());
772da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(null, Arrays.asList(3, 2, 1), new ArrayList<>(), Arrays.asList(1, 2, 3));
773da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi        compareResult(null, null, new ArrayList<>(), new ArrayList<>());
7742fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu    }
7752fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
7761bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu    private void assertEqualRoutes(Collection<RouteInfo> expected, Collection<RouteInfo> actual) {
7771bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        Set<RouteInfo> expectedSet = new ArraySet<>(expected);
7781bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        Set<RouteInfo> actualSet = new ArraySet<>(actual);
7791bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        // Duplicated entries in actual routes are considered failures
7801bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEquals(actual.size(), actualSet.size());
7811bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu
7821bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu        assertEquals(expectedSet, actualSet);
7831bb5c0818f0c4fb426e13b65a3ba3db7f36c3d88Rubin Xu    }
7842fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu
785da7edaff329e84ce7b9d3cb2b4699520aed21594Hugo Benichi    private <T> void compareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved,
7869dac106b13ecd96de97c5b5ac41c6c3a55c3cea3Rubin Xu            List<T> expectAdded) {
7879dac106b13ecd96de97c5b5ac41c6c3a55c3cea3Rubin Xu        CompareResult<T> result = new CompareResult<>(oldItems, newItems);
7882fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        assertEquals(new ArraySet<>(expectAdded), new ArraySet<>(result.added));
7892fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu        assertEquals(new ArraySet<>(expectRemoved), (new ArraySet<>(result.removed)));
7902fc72f72e5125287b006f6c5e69d64fbc2c245afRubin Xu    }
7919419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean
7929419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean    @Test
7939419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean    public void testLinkPropertiesParcelable() {
7949419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        LinkProperties source = new LinkProperties();
7959419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.setInterfaceName(NAME);
7969419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        // set 2 link addresses
7979419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.addLinkAddress(LINKADDRV4);
7989419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.addLinkAddress(LINKADDRV6);
7999419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        // set 2 dnses
8009419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.addDnsServer(DNS1);
8019419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.addDnsServer(DNS2);
8029419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        // set 2 gateways
8039419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.addRoute(new RouteInfo(GATEWAY1));
8049419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.addRoute(new RouteInfo(GATEWAY2));
8059419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        // set 2 validated private dnses
8069419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.addValidatedPrivateDnsServer(DNS6);
8079419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.addValidatedPrivateDnsServer(GATEWAY61);
8089419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean
8099419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.setMtu(MTU);
8109419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean
8119419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        Parcel p = Parcel.obtain();
8129419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        source.writeToParcel(p, /* flags */ 0);
8139419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        p.setDataPosition(0);
8149419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        final byte[] marshalled = p.marshall();
8159419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        p = Parcel.obtain();
8169419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        p.unmarshall(marshalled, 0, marshalled.length);
8179419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        p.setDataPosition(0);
8189419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        LinkProperties dest = LinkProperties.CREATOR.createFromParcel(p);
8199419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean
8209419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean        assertEquals(source, dest);
8219419b114582c50bebd2b02733a24cf34f6bf68e0Chalard Jean    }
8224e900091c4da26eb1c9f0d232ee0e50f4522cc69John Wang}
823