1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.net.module.util; 18 19 import static com.android.testutils.MiscAsserts.assertSameElements; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertTrue; 24 25 import android.annotation.SuppressLint; 26 import android.net.InetAddresses; 27 import android.net.IpPrefix; 28 import android.net.LinkAddress; 29 import android.net.LinkProperties; 30 import android.net.ProxyInfo; 31 import android.net.RouteInfo; 32 import android.util.ArraySet; 33 34 import androidx.test.runner.AndroidJUnit4; 35 36 import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult; 37 import com.android.net.module.util.LinkPropertiesUtils.CompareResult; 38 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 42 import java.net.InetAddress; 43 import java.util.ArrayList; 44 import java.util.Arrays; 45 import java.util.List; 46 import java.util.function.Function; 47 48 @RunWith(AndroidJUnit4.class) 49 public final class LinkPropertiesUtilsTest { 50 @SuppressLint("NewApi") 51 private static final IpPrefix PREFIX = new IpPrefix(toInetAddress("75.208.6.0"), 24); 52 private static final InetAddress V4_ADDR = toInetAddress("75.208.6.1"); 53 private static final InetAddress V6_ADDR = toInetAddress( 54 "2001:0db8:85a3:0000:0000:8a2e:0370:7334"); 55 private static final InetAddress DNS1 = toInetAddress("75.208.7.1"); 56 private static final InetAddress DNS2 = toInetAddress("69.78.7.1"); 57 58 private static final InetAddress GATEWAY1 = toInetAddress("75.208.8.1"); 59 private static final InetAddress GATEWAY2 = toInetAddress("69.78.8.1"); 60 61 private static final String IF_NAME = "wlan0"; 62 private static final LinkAddress V4_LINKADDR = new LinkAddress(V4_ADDR, 32); 63 private static final LinkAddress V6_LINKADDR = new LinkAddress(V6_ADDR, 128); 64 private static final RouteInfo RT_INFO1 = new RouteInfo(PREFIX, GATEWAY1, IF_NAME); 65 private static final RouteInfo RT_INFO2 = new RouteInfo(PREFIX, GATEWAY2, IF_NAME); 66 private static final String TEST_DOMAIN = "link.properties.com"; 67 toInetAddress(String addrString)68 private static InetAddress toInetAddress(String addrString) { 69 return InetAddresses.parseNumericAddress(addrString); 70 } 71 createTestObject()72 private LinkProperties createTestObject() { 73 final LinkProperties lp = new LinkProperties(); 74 lp.setInterfaceName(IF_NAME); 75 lp.addLinkAddress(V4_LINKADDR); 76 lp.addLinkAddress(V6_LINKADDR); 77 lp.addDnsServer(DNS1); 78 lp.addDnsServer(DNS2); 79 lp.setDomains(TEST_DOMAIN); 80 lp.addRoute(RT_INFO1); 81 lp.addRoute(RT_INFO2); 82 lp.setHttpProxy(ProxyInfo.buildDirectProxy("test", 8888)); 83 return lp; 84 } 85 86 @Test testLinkPropertiesIdenticalEqual()87 public void testLinkPropertiesIdenticalEqual() { 88 final LinkProperties source = createTestObject(); 89 final LinkProperties target = new LinkProperties(source); 90 91 assertTrue(LinkPropertiesUtils.isIdenticalInterfaceName(source, target)); 92 assertTrue(LinkPropertiesUtils.isIdenticalInterfaceName(target, source)); 93 94 assertTrue(LinkPropertiesUtils.isIdenticalAddresses(source, target)); 95 assertTrue(LinkPropertiesUtils.isIdenticalAddresses(target, source)); 96 97 assertTrue(LinkPropertiesUtils.isIdenticalAllLinkAddresses(source, target)); 98 assertTrue(LinkPropertiesUtils.isIdenticalAllLinkAddresses(target, source)); 99 100 assertTrue(LinkPropertiesUtils.isIdenticalDnses(source, target)); 101 assertTrue(LinkPropertiesUtils.isIdenticalDnses(target, source)); 102 103 assertTrue(LinkPropertiesUtils.isIdenticalRoutes(source, target)); 104 assertTrue(LinkPropertiesUtils.isIdenticalRoutes(target, source)); 105 106 assertTrue(LinkPropertiesUtils.isIdenticalHttpProxy(source, target)); 107 assertTrue(LinkPropertiesUtils.isIdenticalHttpProxy(target, source)); 108 109 // Test different interface name. 110 target.setInterfaceName("lo"); 111 assertFalse(LinkPropertiesUtils.isIdenticalInterfaceName(source, target)); 112 assertFalse(LinkPropertiesUtils.isIdenticalInterfaceName(target, source)); 113 // Restore interface name 114 target.setInterfaceName(IF_NAME); 115 116 // Compare addresses.size() not equals. 117 final LinkAddress testLinkAddr = new LinkAddress(toInetAddress("75.208.6.2"), 32); 118 target.addLinkAddress(testLinkAddr); 119 assertFalse(LinkPropertiesUtils.isIdenticalAddresses(source, target)); 120 assertFalse(LinkPropertiesUtils.isIdenticalAddresses(target, source)); 121 122 assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(source, target)); 123 assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(target, source)); 124 125 // Currently, target contains V4_LINKADDR, V6_LINKADDR and testLinkAddr. 126 // Compare addresses.size() equals but contains different address. 127 target.removeLinkAddress(V4_LINKADDR); 128 assertEquals(source.getAddresses().size(), target.getAddresses().size()); 129 assertFalse(LinkPropertiesUtils.isIdenticalAddresses(source, target)); 130 assertFalse(LinkPropertiesUtils.isIdenticalAddresses(target, source)); 131 assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(source, target)); 132 assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(target, source)); 133 // Restore link address 134 target.addLinkAddress(V4_LINKADDR); 135 target.removeLinkAddress(testLinkAddr); 136 137 // Compare size not equals. 138 target.addDnsServer(toInetAddress("75.208.10.1")); 139 assertFalse(LinkPropertiesUtils.isIdenticalDnses(source, target)); 140 assertFalse(LinkPropertiesUtils.isIdenticalDnses(target, source)); 141 142 // Compare the same servers but target has different domains. 143 target.removeDnsServer(toInetAddress("75.208.10.1")); 144 target.setDomains("test.com"); 145 assertFalse(LinkPropertiesUtils.isIdenticalDnses(source, target)); 146 assertFalse(LinkPropertiesUtils.isIdenticalDnses(target, source)); 147 148 // Test null domain. 149 target.setDomains(null); 150 assertFalse(LinkPropertiesUtils.isIdenticalDnses(source, target)); 151 assertFalse(LinkPropertiesUtils.isIdenticalDnses(target, source)); 152 // Restore domain 153 target.setDomains(TEST_DOMAIN); 154 155 // Compare size not equals. 156 final RouteInfo testRoute = new RouteInfo(toInetAddress("75.208.7.1")); 157 target.addRoute(testRoute); 158 assertFalse(LinkPropertiesUtils.isIdenticalRoutes(source, target)); 159 assertFalse(LinkPropertiesUtils.isIdenticalRoutes(target, source)); 160 161 // Currently, target contains RT_INFO1, RT_INFO2 and testRoute. 162 // Compare size equals but different routes. 163 target.removeRoute(RT_INFO1); 164 assertEquals(source.getRoutes().size(), target.getRoutes().size()); 165 assertFalse(LinkPropertiesUtils.isIdenticalRoutes(source, target)); 166 assertFalse(LinkPropertiesUtils.isIdenticalRoutes(target, source)); 167 // Restore route 168 target.addRoute(RT_INFO1); 169 target.removeRoute(testRoute); 170 171 // Test different proxy. 172 target.setHttpProxy(ProxyInfo.buildDirectProxy("hello", 8888)); 173 assertFalse(LinkPropertiesUtils.isIdenticalHttpProxy(source, target)); 174 assertFalse(LinkPropertiesUtils.isIdenticalHttpProxy(target, source)); 175 176 // Test null proxy. 177 target.setHttpProxy(null); 178 assertFalse(LinkPropertiesUtils.isIdenticalHttpProxy(source, target)); 179 assertFalse(LinkPropertiesUtils.isIdenticalHttpProxy(target, source)); 180 181 final LinkProperties stacked = new LinkProperties(); 182 stacked.setInterfaceName("v4-" + target.getInterfaceName()); 183 stacked.addLinkAddress(testLinkAddr); 184 target.addStackedLink(stacked); 185 assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(source, target)); 186 assertFalse(LinkPropertiesUtils.isIdenticalAllLinkAddresses(target, source)); 187 } 188 compareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved, List<T> expectAdded)189 private <T> void compareResult(List<T> oldItems, List<T> newItems, List<T> expectRemoved, 190 List<T> expectAdded) { 191 CompareResult<T> result = new CompareResult<>(oldItems, newItems); 192 assertEquals(new ArraySet<>(expectAdded), new ArraySet<>(result.added)); 193 assertEquals(new ArraySet<>(expectRemoved), (new ArraySet<>(result.removed))); 194 } 195 196 @Test testCompareResult()197 public void testCompareResult() { 198 // Either adding or removing items 199 compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(1), 200 Arrays.asList(2, 3, 4), new ArrayList<>()); 201 compareResult(Arrays.asList(1, 2), Arrays.asList(3, 2, 1, 4), 202 new ArrayList<>(), Arrays.asList(3, 4)); 203 204 205 // adding and removing items at the same time 206 compareResult(Arrays.asList(1, 2, 3, 4), Arrays.asList(2, 3, 4, 5), 207 Arrays.asList(1), Arrays.asList(5)); 208 compareResult(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6), 209 Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6)); 210 211 // null cases 212 compareResult(Arrays.asList(1, 2, 3), null, Arrays.asList(1, 2, 3), new ArrayList<>()); 213 compareResult(null, Arrays.asList(3, 2, 1), new ArrayList<>(), Arrays.asList(1, 2, 3)); 214 compareResult(null, null, new ArrayList<>(), new ArrayList<>()); 215 216 // Some more tests with strings 217 final ArrayList<String> list1 = new ArrayList<>(); 218 list1.add("string1"); 219 220 final ArrayList<String> list2 = new ArrayList<>(list1); 221 final CompareResult<String> cr1 = new CompareResult<>(list1, list2); 222 assertTrue(cr1.added.isEmpty()); 223 assertTrue(cr1.removed.isEmpty()); 224 225 list2.add("string2"); 226 final CompareResult<String> cr2 = new CompareResult<>(list1, list2); 227 assertEquals(Arrays.asList("string2"), cr2.added); 228 assertTrue(cr2.removed.isEmpty()); 229 230 list2.remove("string1"); 231 final CompareResult<String> cr3 = new CompareResult<>(list1, list2); 232 assertEquals(Arrays.asList("string2"), cr3.added); 233 assertEquals(Arrays.asList("string1"), cr3.removed); 234 235 list1.add("string2"); 236 final CompareResult<String> cr4 = new CompareResult<>(list1, list2); 237 assertTrue(cr4.added.isEmpty()); 238 assertEquals(Arrays.asList("string1"), cr3.removed); 239 } 240 241 @Test testCompareAddresses()242 public void testCompareAddresses() { 243 final LinkProperties source = createTestObject(); 244 final LinkProperties target = new LinkProperties(source); 245 final InetAddress addr1 = toInetAddress("75.208.6.2"); 246 final LinkAddress linkAddr1 = new LinkAddress(addr1, 32); 247 248 CompareResult<LinkAddress> results = LinkPropertiesUtils.compareAddresses(source, target); 249 assertEquals(0, results.removed.size()); 250 assertEquals(0, results.added.size()); 251 252 source.addLinkAddress(linkAddr1); 253 results = LinkPropertiesUtils.compareAddresses(source, target); 254 assertEquals(1, results.removed.size()); 255 assertEquals(linkAddr1, results.removed.get(0)); 256 assertEquals(0, results.added.size()); 257 258 final InetAddress addr2 = toInetAddress("75.208.6.3"); 259 final LinkAddress linkAddr2 = new LinkAddress(addr2, 32); 260 261 target.addLinkAddress(linkAddr2); 262 results = LinkPropertiesUtils.compareAddresses(source, target); 263 assertEquals(linkAddr1, results.removed.get(0)); 264 assertEquals(linkAddr2, results.added.get(0)); 265 } 266 assertCompareOrUpdateResult(CompareOrUpdateResult result, List<String> expectedAdded, List<String> expectedRemoved, List<String> expectedUpdated)267 private void assertCompareOrUpdateResult(CompareOrUpdateResult result, 268 List<String> expectedAdded, List<String> expectedRemoved, 269 List<String> expectedUpdated) { 270 assertSameElements(expectedAdded, result.added); 271 assertSameElements(expectedRemoved, result.removed); 272 assertSameElements(expectedUpdated, result.updated); 273 } 274 strArray(String... strs)275 private List<String> strArray(String... strs) { 276 return Arrays.asList(strs); 277 } 278 279 @Test testCompareOrUpdateResult()280 public void testCompareOrUpdateResult() { 281 // As the item type, use a simple string. An item is defined to be an update of another item 282 // if the string starts with the same alphabetical characters. 283 // Extracting the key from the object is just a regexp. 284 Function<String, String> extractPrefix = (s) -> s.replaceFirst("^([a-z]+).*", "$1"); 285 assertEquals("goodbye", extractPrefix.apply("goodbye1234")); 286 287 List<String> oldItems = strArray("hello123", "goodbye5678", "howareyou669"); 288 List<String> newItems = strArray("hello123", "goodbye000", "verywell"); 289 290 final List<String> emptyList = new ArrayList<>(); 291 292 // Items -> empty: everything removed. 293 CompareOrUpdateResult<String, String> result = 294 new CompareOrUpdateResult<String, String>(oldItems, emptyList, extractPrefix); 295 assertCompareOrUpdateResult(result, 296 emptyList, strArray("hello123", "howareyou669", "goodbye5678"), emptyList); 297 298 // Empty -> items: everything added. 299 result = new CompareOrUpdateResult<String, String>(emptyList, newItems, extractPrefix); 300 assertCompareOrUpdateResult(result, 301 strArray("hello123", "goodbye000", "verywell"), emptyList, emptyList); 302 303 // Empty -> empty: no change. 304 result = new CompareOrUpdateResult<String, String>(newItems, newItems, extractPrefix); 305 assertCompareOrUpdateResult(result, emptyList, emptyList, emptyList); 306 307 // Added, removed, updated at the same time. 308 result = new CompareOrUpdateResult<>(oldItems, newItems, extractPrefix); 309 assertCompareOrUpdateResult(result, 310 strArray("verywell"), strArray("howareyou669"), strArray("goodbye000")); 311 312 // Null -> items: everything added. 313 result = new CompareOrUpdateResult<String, String>(null, newItems, extractPrefix); 314 assertCompareOrUpdateResult(result, 315 strArray("hello123", "goodbye000", "verywell"), emptyList, emptyList); 316 317 // Items -> null: everything removed. 318 result = new CompareOrUpdateResult<String, String>(oldItems, null, extractPrefix); 319 assertCompareOrUpdateResult(result, 320 emptyList, strArray("hello123", "howareyou669", "goodbye5678"), emptyList); 321 322 // Null -> null: all lists empty. 323 result = new CompareOrUpdateResult<String, String>(null, null, extractPrefix); 324 assertCompareOrUpdateResult(result, emptyList, emptyList, emptyList); 325 } 326 } 327