1 /* 2 * Copyright (C) 2018 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.server.ethernet; 18 19 import static android.net.TestNetworkManager.TEST_TAP_PREFIX; 20 21 import static org.junit.Assert.assertEquals; 22 import static org.junit.Assert.assertFalse; 23 import static org.junit.Assert.assertThrows; 24 import static org.junit.Assert.assertTrue; 25 import static org.junit.Assert.fail; 26 import static org.mockito.ArgumentMatchers.anyBoolean; 27 import static org.mockito.ArgumentMatchers.anyString; 28 import static org.mockito.ArgumentMatchers.eq; 29 import static org.mockito.Mockito.doReturn; 30 import static org.mockito.Mockito.verify; 31 32 import android.content.Context; 33 import android.net.INetd; 34 import android.net.InetAddresses; 35 import android.net.IpConfiguration; 36 import android.net.IpConfiguration.IpAssignment; 37 import android.net.IpConfiguration.ProxySettings; 38 import android.net.LinkAddress; 39 import android.net.NetworkCapabilities; 40 import android.net.StaticIpConfiguration; 41 import android.os.Build; 42 import android.os.HandlerThread; 43 import android.os.RemoteException; 44 45 import androidx.test.filters.SmallTest; 46 47 import com.android.testutils.DevSdkIgnoreRule; 48 import com.android.testutils.DevSdkIgnoreRunner; 49 import com.android.testutils.HandlerUtils; 50 51 import org.junit.After; 52 import org.junit.Before; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.mockito.Mock; 56 import org.mockito.MockitoAnnotations; 57 58 import java.net.InetAddress; 59 import java.util.ArrayList; 60 61 @SmallTest 62 @RunWith(DevSdkIgnoreRunner.class) 63 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2) 64 public class EthernetTrackerTest { 65 private static final String TEST_IFACE = "test123"; 66 private static final int TIMEOUT_MS = 1_000; 67 private static final String THREAD_NAME = "EthernetServiceThread"; 68 private static final EthernetCallback NULL_CB = new EthernetCallback(null); 69 private EthernetTracker tracker; 70 private HandlerThread mHandlerThread; 71 @Mock private Context mContext; 72 @Mock private EthernetNetworkFactory mFactory; 73 @Mock private INetd mNetd; 74 @Mock private EthernetTracker.Dependencies mDeps; 75 76 @Before setUp()77 public void setUp() throws RemoteException { 78 MockitoAnnotations.initMocks(this); 79 initMockResources(); 80 doReturn(false).when(mFactory).updateInterfaceLinkState(anyString(), anyBoolean()); 81 doReturn(new String[0]).when(mNetd).interfaceGetList(); 82 mHandlerThread = new HandlerThread(THREAD_NAME); 83 mHandlerThread.start(); 84 tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd, 85 mDeps); 86 } 87 88 @After cleanUp()89 public void cleanUp() throws InterruptedException { 90 mHandlerThread.quitSafely(); 91 mHandlerThread.join(); 92 } 93 initMockResources()94 private void initMockResources() { 95 doReturn("").when(mDeps).getInterfaceRegexFromResource(eq(mContext)); 96 doReturn(new String[0]).when(mDeps).getInterfaceConfigFromResource(eq(mContext)); 97 } 98 waitForIdle()99 private void waitForIdle() { 100 HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS); 101 } 102 103 /** 104 * Test: Creation of various valid static IP configurations 105 */ 106 @Test createStaticIpConfiguration()107 public void createStaticIpConfiguration() { 108 // Empty gives default StaticIPConfiguration object 109 assertStaticConfiguration(new StaticIpConfiguration(), ""); 110 111 // Setting only the IP address properly cascades and assumes defaults 112 assertStaticConfiguration(new StaticIpConfiguration.Builder() 113 .setIpAddress(new LinkAddress("192.0.2.10/24")).build(), "ip=192.0.2.10/24"); 114 115 final ArrayList<InetAddress> dnsAddresses = new ArrayList<>(); 116 dnsAddresses.add(InetAddresses.parseNumericAddress("4.4.4.4")); 117 dnsAddresses.add(InetAddresses.parseNumericAddress("8.8.8.8")); 118 // Setting other fields properly cascades them 119 assertStaticConfiguration(new StaticIpConfiguration.Builder() 120 .setIpAddress(new LinkAddress("192.0.2.10/24")) 121 .setDnsServers(dnsAddresses) 122 .setGateway(InetAddresses.parseNumericAddress("192.0.2.1")) 123 .setDomains("android").build(), 124 "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android"); 125 126 // Verify order doesn't matter 127 assertStaticConfiguration(new StaticIpConfiguration.Builder() 128 .setIpAddress(new LinkAddress("192.0.2.10/24")) 129 .setDnsServers(dnsAddresses) 130 .setGateway(InetAddresses.parseNumericAddress("192.0.2.1")) 131 .setDomains("android").build(), 132 "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 "); 133 } 134 135 /** 136 * Test: Attempt creation of various bad static IP configurations 137 */ 138 @Test createStaticIpConfiguration_Bad()139 public void createStaticIpConfiguration_Bad() { 140 assertStaticConfigurationFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20"); // Unknown key 141 assertStaticConfigurationFails("ip=192.0.2.1"); // mask is missing 142 assertStaticConfigurationFails("ip=a.b.c"); // not a valid ip address 143 assertStaticConfigurationFails("dns=4.4.4.4,1.2.3.A"); // not valid ip address in dns 144 assertStaticConfigurationFails("="); // Key and value is empty 145 assertStaticConfigurationFails("ip="); // Value is empty 146 assertStaticConfigurationFails("ip=192.0.2.1/24 gateway="); // Gateway is empty 147 } 148 assertStaticConfigurationFails(String config)149 private void assertStaticConfigurationFails(String config) { 150 try { 151 EthernetTracker.parseStaticIpConfiguration(config); 152 fail("Expected to fail: " + config); 153 } catch (IllegalArgumentException e) { 154 // expected 155 } 156 } 157 assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig, String configAsString)158 private void assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig, 159 String configAsString) { 160 final IpConfiguration expectedIpConfiguration = new IpConfiguration(); 161 expectedIpConfiguration.setIpAssignment(IpAssignment.STATIC); 162 expectedIpConfiguration.setProxySettings(ProxySettings.NONE); 163 expectedIpConfiguration.setStaticIpConfiguration(expectedStaticIpConfig); 164 165 assertEquals(expectedIpConfiguration, 166 EthernetTracker.parseStaticIpConfiguration(configAsString)); 167 } 168 makeEthernetCapabilitiesBuilder(boolean clearAll)169 private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearAll) { 170 final NetworkCapabilities.Builder builder = 171 clearAll ? NetworkCapabilities.Builder.withoutDefaultCapabilities() 172 : new NetworkCapabilities.Builder(); 173 return builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING) 174 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED) 175 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED); 176 } 177 178 /** 179 * Test: Attempt to create a capabilties with various valid sets of capabilities/transports 180 */ 181 @Test createNetworkCapabilities()182 public void createNetworkCapabilities() { 183 184 // Particularly common expected results 185 NetworkCapabilities defaultEthernetCleared = 186 makeEthernetCapabilitiesBuilder(true /* clearAll */) 187 .setLinkUpstreamBandwidthKbps(100000) 188 .setLinkDownstreamBandwidthKbps(100000) 189 .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) 190 .build(); 191 192 NetworkCapabilities ethernetClearedWithCommonCaps = 193 makeEthernetCapabilitiesBuilder(true /* clearAll */) 194 .setLinkUpstreamBandwidthKbps(100000) 195 .setLinkDownstreamBandwidthKbps(100000) 196 .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) 197 .addCapability(12) 198 .addCapability(13) 199 .addCapability(14) 200 .addCapability(15) 201 .build(); 202 203 // Empty capabilities and transports lists with a "please clear defaults" should 204 // yield an empty capabilities set with TRANPORT_ETHERNET 205 assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", ""); 206 207 // Empty capabilities and transports without the clear defaults flag should return the 208 // default capabilities set with TRANSPORT_ETHERNET 209 assertParsedNetworkCapabilities( 210 makeEthernetCapabilitiesBuilder(false /* clearAll */) 211 .setLinkUpstreamBandwidthKbps(100000) 212 .setLinkDownstreamBandwidthKbps(100000) 213 .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) 214 .build(), 215 false, "", ""); 216 217 // A list of capabilities without the clear defaults flag should return the default 218 // capabilities, mixed with the desired capabilities, and TRANSPORT_ETHERNET 219 assertParsedNetworkCapabilities( 220 makeEthernetCapabilitiesBuilder(false /* clearAll */) 221 .setLinkUpstreamBandwidthKbps(100000) 222 .setLinkDownstreamBandwidthKbps(100000) 223 .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) 224 .addCapability(11) 225 .addCapability(12) 226 .build(), 227 false, "11,12", ""); 228 229 // Adding a list of capabilities with a clear defaults will leave exactly those capabilities 230 // with a default TRANSPORT_ETHERNET since no overrides are specified 231 assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15", ""); 232 233 // Adding any invalid capabilities to the list will cause them to be ignored 234 assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,65,73", ""); 235 assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,abcdefg", ""); 236 237 // Adding a valid override transport will remove the default TRANSPORT_ETHERNET transport 238 // and apply only the override to the capabiltities object 239 assertParsedNetworkCapabilities( 240 makeEthernetCapabilitiesBuilder(true /* clearAll */) 241 .setLinkUpstreamBandwidthKbps(100000) 242 .setLinkDownstreamBandwidthKbps(100000) 243 .addTransportType(0) 244 .build(), 245 true, "", "0"); 246 assertParsedNetworkCapabilities( 247 makeEthernetCapabilitiesBuilder(true /* clearAll */) 248 .setLinkUpstreamBandwidthKbps(100000) 249 .setLinkDownstreamBandwidthKbps(100000) 250 .addTransportType(1) 251 .build(), 252 true, "", "1"); 253 assertParsedNetworkCapabilities( 254 makeEthernetCapabilitiesBuilder(true /* clearAll */) 255 .setLinkUpstreamBandwidthKbps(100000) 256 .setLinkDownstreamBandwidthKbps(100000) 257 .addTransportType(2) 258 .build(), 259 true, "", "2"); 260 assertParsedNetworkCapabilities( 261 makeEthernetCapabilitiesBuilder(true /* clearAll */) 262 .setLinkUpstreamBandwidthKbps(100000) 263 .setLinkDownstreamBandwidthKbps(100000) 264 .addTransportType(3) 265 .build(), 266 true, "", "3"); 267 268 // "4" is TRANSPORT_VPN, which is unsupported. Should default back to TRANPORT_ETHERNET 269 assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "4"); 270 271 // "5" is TRANSPORT_WIFI_AWARE, which is currently supported due to no legacy TYPE_NONE 272 // conversion. When that becomes available, this test must be updated 273 assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "5"); 274 275 // "6" is TRANSPORT_LOWPAN, which is currently supported due to no legacy TYPE_NONE 276 // conversion. When that becomes available, this test must be updated 277 assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "6"); 278 279 // Adding an invalid override transport will leave the transport as TRANSPORT_ETHERNET 280 assertParsedNetworkCapabilities(defaultEthernetCleared,true, "", "100"); 281 assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "abcdefg"); 282 283 // Ensure the adding of both capabilities and transports work 284 assertParsedNetworkCapabilities( 285 makeEthernetCapabilitiesBuilder(true /* clearAll */) 286 .setLinkUpstreamBandwidthKbps(100000) 287 .setLinkDownstreamBandwidthKbps(100000) 288 .addCapability(12) 289 .addCapability(13) 290 .addCapability(14) 291 .addCapability(15) 292 .addTransportType(3) 293 .build(), 294 true, "12,13,14,15", "3"); 295 296 // Ensure order does not matter for capability list 297 assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "13,12,15,14", ""); 298 } 299 assertParsedNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities, boolean clearCapabilties, String configCapabiltiies,String configTransports)300 private void assertParsedNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities, 301 boolean clearCapabilties, String configCapabiltiies,String configTransports) { 302 assertEquals(expectedNetworkCapabilities, 303 EthernetTracker.createNetworkCapabilities(clearCapabilties, configCapabiltiies, 304 configTransports).build()); 305 } 306 307 @Test testCreateEthernetTrackerConfigReturnsCorrectValue()308 public void testCreateEthernetTrackerConfigReturnsCorrectValue() { 309 final String capabilities = "2"; 310 final String ipConfig = "3"; 311 final String transport = "4"; 312 final String configString = String.join(";", TEST_IFACE, capabilities, ipConfig, transport); 313 314 final EthernetTracker.EthernetTrackerConfig config = 315 EthernetTracker.createEthernetTrackerConfig(configString); 316 317 assertEquals(TEST_IFACE, config.mIface); 318 assertEquals(capabilities, config.mCapabilities); 319 assertEquals(ipConfig, config.mIpConfig); 320 assertEquals(transport, config.mTransport); 321 } 322 323 @Test testCreateEthernetTrackerConfigThrowsNpeWithNullInput()324 public void testCreateEthernetTrackerConfigThrowsNpeWithNullInput() { 325 assertThrows(NullPointerException.class, 326 () -> EthernetTracker.createEthernetTrackerConfig(null)); 327 } 328 329 @Test testUpdateConfiguration()330 public void testUpdateConfiguration() { 331 final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build(); 332 final LinkAddress linkAddr = new LinkAddress("192.0.2.2/25"); 333 final StaticIpConfiguration staticIpConfig = 334 new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build(); 335 final IpConfiguration ipConfig = 336 new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build(); 337 final EthernetCallback listener = new EthernetCallback(null); 338 339 tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener); 340 waitForIdle(); 341 342 verify(mFactory).updateInterface( 343 eq(TEST_IFACE), eq(ipConfig), eq(capabilities)); 344 } 345 346 @Test testIsValidTestInterfaceIsFalseWhenTestInterfacesAreNotIncluded()347 public void testIsValidTestInterfaceIsFalseWhenTestInterfacesAreNotIncluded() { 348 final String validIfaceName = TEST_TAP_PREFIX + "123"; 349 tracker.setIncludeTestInterfaces(false); 350 waitForIdle(); 351 352 final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName); 353 354 assertFalse(isValidTestInterface); 355 } 356 357 @Test testIsValidTestInterfaceIsFalseWhenTestInterfaceNameIsInvalid()358 public void testIsValidTestInterfaceIsFalseWhenTestInterfaceNameIsInvalid() { 359 final String invalidIfaceName = "123" + TEST_TAP_PREFIX; 360 tracker.setIncludeTestInterfaces(true); 361 waitForIdle(); 362 363 final boolean isValidTestInterface = tracker.isValidTestInterface(invalidIfaceName); 364 365 assertFalse(isValidTestInterface); 366 } 367 368 @Test testIsValidTestInterfaceIsTrueWhenTestInterfacesIncludedAndValidName()369 public void testIsValidTestInterfaceIsTrueWhenTestInterfacesIncludedAndValidName() { 370 final String validIfaceName = TEST_TAP_PREFIX + "123"; 371 tracker.setIncludeTestInterfaces(true); 372 waitForIdle(); 373 374 final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName); 375 376 assertTrue(isValidTestInterface); 377 } 378 } 379