1 /* 2 * Copyright (C) 2020 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 org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotSame; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.mockito.ArgumentMatchers.any; 25 import static org.mockito.ArgumentMatchers.anyString; 26 import static org.mockito.ArgumentMatchers.argThat; 27 import static org.mockito.ArgumentMatchers.eq; 28 import static org.mockito.Mockito.clearInvocations; 29 import static org.mockito.Mockito.doAnswer; 30 import static org.mockito.Mockito.never; 31 import static org.mockito.Mockito.verify; 32 import static org.mockito.Mockito.when; 33 34 import android.annotation.NonNull; 35 import android.app.test.MockAnswerUtil.AnswerWithArguments; 36 import android.content.Context; 37 import android.content.res.Resources; 38 import android.net.ConnectivityManager; 39 import android.net.EthernetNetworkSpecifier; 40 import android.net.IpConfiguration; 41 import android.net.LinkAddress; 42 import android.net.LinkProperties; 43 import android.net.Network; 44 import android.net.NetworkAgentConfig; 45 import android.net.NetworkCapabilities; 46 import android.net.NetworkProvider; 47 import android.net.NetworkProvider.NetworkOfferCallback; 48 import android.net.NetworkRequest; 49 import android.net.StaticIpConfiguration; 50 import android.net.ip.IpClientCallbacks; 51 import android.net.ip.IpClientManager; 52 import android.os.Build; 53 import android.os.Handler; 54 import android.os.Looper; 55 import android.os.test.TestLooper; 56 57 import androidx.test.filters.SmallTest; 58 59 import com.android.net.module.util.InterfaceParams; 60 import com.android.testutils.DevSdkIgnoreRule; 61 import com.android.testutils.DevSdkIgnoreRunner; 62 63 import org.junit.After; 64 import org.junit.Before; 65 import org.junit.Test; 66 import org.junit.runner.RunWith; 67 import org.mockito.ArgumentCaptor; 68 import org.mockito.Mock; 69 import org.mockito.MockitoAnnotations; 70 71 import java.util.Objects; 72 73 @SmallTest 74 @RunWith(DevSdkIgnoreRunner.class) 75 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2) 76 public class EthernetNetworkFactoryTest { 77 private static final int TIMEOUT_MS = 2_000; 78 private static final String TEST_IFACE = "test123"; 79 private static final String IP_ADDR = "192.0.2.2/25"; 80 private static final LinkAddress LINK_ADDR = new LinkAddress(IP_ADDR); 81 private static final String HW_ADDR = "01:02:03:04:05:06"; 82 private TestLooper mLooper; 83 private Handler mHandler; 84 private EthernetNetworkFactory mNetFactory = null; 85 private IpClientCallbacks mIpClientCallbacks; 86 private NetworkOfferCallback mNetworkOfferCallback; 87 private NetworkRequest mRequestToKeepNetworkUp; 88 @Mock private Context mContext; 89 @Mock private Resources mResources; 90 @Mock private EthernetNetworkFactory.Dependencies mDeps; 91 @Mock private IpClientManager mIpClient; 92 @Mock private EthernetNetworkAgent mNetworkAgent; 93 @Mock private InterfaceParams mInterfaceParams; 94 @Mock private Network mMockNetwork; 95 @Mock private NetworkProvider mNetworkProvider; 96 97 @Before setUp()98 public void setUp() throws Exception { 99 MockitoAnnotations.initMocks(this); 100 setupNetworkAgentMock(); 101 setupIpClientMock(); 102 setupContext(); 103 } 104 105 //TODO: Move away from usage of TestLooper in order to move this logic back into @Before. initEthernetNetworkFactory()106 private void initEthernetNetworkFactory() { 107 mLooper = new TestLooper(); 108 mHandler = new Handler(mLooper.getLooper()); 109 mNetFactory = new EthernetNetworkFactory(mHandler, mContext, mNetworkProvider, mDeps); 110 } 111 setupNetworkAgentMock()112 private void setupNetworkAgentMock() { 113 when(mDeps.makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any())) 114 .thenAnswer(new AnswerWithArguments() { 115 public EthernetNetworkAgent answer( 116 Context context, 117 Looper looper, 118 NetworkCapabilities nc, 119 LinkProperties lp, 120 NetworkAgentConfig config, 121 NetworkProvider provider, 122 EthernetNetworkAgent.Callbacks cb) { 123 when(mNetworkAgent.getCallbacks()).thenReturn(cb); 124 when(mNetworkAgent.getNetwork()) 125 .thenReturn(mMockNetwork); 126 return mNetworkAgent; 127 } 128 } 129 ); 130 } 131 setupIpClientMock()132 private void setupIpClientMock() throws Exception { 133 doAnswer(inv -> { 134 // these tests only support one concurrent IpClient, so make sure we do not accidentally 135 // create a mess. 136 assertNull("An IpClient has already been created.", mIpClientCallbacks); 137 138 mIpClientCallbacks = inv.getArgument(2); 139 mIpClientCallbacks.onIpClientCreated(null); 140 mLooper.dispatchAll(); 141 return null; 142 }).when(mDeps).makeIpClient(any(Context.class), anyString(), any()); 143 144 doAnswer(inv -> { 145 mIpClientCallbacks.onQuit(); 146 mLooper.dispatchAll(); 147 mIpClientCallbacks = null; 148 return null; 149 }).when(mIpClient).shutdown(); 150 151 when(mDeps.makeIpClientManager(any())).thenReturn(mIpClient); 152 } 153 triggerOnProvisioningSuccess()154 private void triggerOnProvisioningSuccess() { 155 mIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); 156 mLooper.dispatchAll(); 157 } 158 triggerOnProvisioningFailure()159 private void triggerOnProvisioningFailure() { 160 mIpClientCallbacks.onProvisioningFailure(new LinkProperties()); 161 mLooper.dispatchAll(); 162 } 163 triggerOnReachabilityLost()164 private void triggerOnReachabilityLost() { 165 mIpClientCallbacks.onReachabilityLost("ReachabilityLost"); 166 mLooper.dispatchAll(); 167 } 168 setupContext()169 private void setupContext() { 170 when(mDeps.getTcpBufferSizesFromResource(eq(mContext))).thenReturn(""); 171 } 172 173 @After tearDown()174 public void tearDown() { 175 // looper is shared with the network agents, so there may still be messages to dispatch on 176 // tear down. 177 mLooper.dispatchAll(); 178 } 179 createDefaultFilterCaps()180 private NetworkCapabilities createDefaultFilterCaps() { 181 return NetworkCapabilities.Builder.withoutDefaultCapabilities() 182 .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) 183 .build(); 184 } 185 createInterfaceCapsBuilder(final int transportType)186 private NetworkCapabilities.Builder createInterfaceCapsBuilder(final int transportType) { 187 return new NetworkCapabilities.Builder() 188 .addTransportType(transportType) 189 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) 190 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); 191 } 192 createDefaultRequestBuilder()193 private NetworkRequest.Builder createDefaultRequestBuilder() { 194 return new NetworkRequest.Builder() 195 .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET) 196 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 197 } 198 createDefaultRequest()199 private NetworkRequest createDefaultRequest() { 200 return createDefaultRequestBuilder().build(); 201 } 202 createDefaultIpConfig()203 private IpConfiguration createDefaultIpConfig() { 204 IpConfiguration ipConfig = new IpConfiguration(); 205 ipConfig.setIpAssignment(IpConfiguration.IpAssignment.DHCP); 206 ipConfig.setProxySettings(IpConfiguration.ProxySettings.NONE); 207 return ipConfig; 208 } 209 210 /** 211 * Create an {@link IpConfiguration} with an associated {@link StaticIpConfiguration}. 212 * 213 * @return {@link IpConfiguration} with its {@link StaticIpConfiguration} set. 214 */ createStaticIpConfig()215 private IpConfiguration createStaticIpConfig() { 216 final IpConfiguration ipConfig = new IpConfiguration(); 217 ipConfig.setIpAssignment(IpConfiguration.IpAssignment.STATIC); 218 ipConfig.setStaticIpConfiguration( 219 new StaticIpConfiguration.Builder().setIpAddress(LINK_ADDR).build()); 220 return ipConfig; 221 } 222 223 // creates an interface with provisioning in progress (since updating the interface link state 224 // automatically starts the provisioning process) createInterfaceUndergoingProvisioning(String iface)225 private void createInterfaceUndergoingProvisioning(String iface) { 226 // Default to the ethernet transport type. 227 createInterfaceUndergoingProvisioning(iface, NetworkCapabilities.TRANSPORT_ETHERNET); 228 } 229 createInterfaceUndergoingProvisioning( @onNull final String iface, final int transportType)230 private void createInterfaceUndergoingProvisioning( 231 @NonNull final String iface, final int transportType) { 232 final IpConfiguration ipConfig = createDefaultIpConfig(); 233 mNetFactory.addInterface(iface, HW_ADDR, ipConfig, 234 createInterfaceCapsBuilder(transportType).build()); 235 assertTrue(mNetFactory.updateInterfaceLinkState(iface, true)); 236 237 ArgumentCaptor<NetworkOfferCallback> captor = ArgumentCaptor.forClass( 238 NetworkOfferCallback.class); 239 verify(mNetworkProvider).registerNetworkOffer(any(), any(), any(), captor.capture()); 240 mRequestToKeepNetworkUp = createDefaultRequest(); 241 mNetworkOfferCallback = captor.getValue(); 242 mNetworkOfferCallback.onNetworkNeeded(mRequestToKeepNetworkUp); 243 244 verifyStart(ipConfig); 245 clearInvocations(mDeps); 246 clearInvocations(mIpClient); 247 clearInvocations(mNetworkProvider); 248 } 249 250 // creates a provisioned interface createAndVerifyProvisionedInterface(String iface)251 private void createAndVerifyProvisionedInterface(String iface) throws Exception { 252 // Default to the ethernet transport type. 253 createAndVerifyProvisionedInterface(iface, NetworkCapabilities.TRANSPORT_ETHERNET, 254 ConnectivityManager.TYPE_ETHERNET); 255 } 256 createVerifyAndRemoveProvisionedInterface(final int transportType, final int expectedLegacyType)257 private void createVerifyAndRemoveProvisionedInterface(final int transportType, 258 final int expectedLegacyType) throws Exception { 259 createAndVerifyProvisionedInterface(TEST_IFACE, transportType, 260 expectedLegacyType); 261 mNetFactory.removeInterface(TEST_IFACE); 262 } 263 createAndVerifyProvisionedInterface( @onNull final String iface, final int transportType, final int expectedLegacyType)264 private void createAndVerifyProvisionedInterface( 265 @NonNull final String iface, final int transportType, final int expectedLegacyType) 266 throws Exception { 267 createInterfaceUndergoingProvisioning(iface, transportType); 268 triggerOnProvisioningSuccess(); 269 // provisioning succeeded, verify that the network agent is created, registered, marked 270 // as connected and legacy type are correctly set. 271 final ArgumentCaptor<NetworkCapabilities> ncCaptor = ArgumentCaptor.forClass( 272 NetworkCapabilities.class); 273 verify(mDeps).makeEthernetNetworkAgent(any(), any(), ncCaptor.capture(), any(), 274 argThat(x -> x.getLegacyType() == expectedLegacyType), any(), any()); 275 assertEquals( 276 new EthernetNetworkSpecifier(iface), ncCaptor.getValue().getNetworkSpecifier()); 277 verifyNetworkAgentRegistersAndConnects(); 278 clearInvocations(mDeps); 279 clearInvocations(mNetworkAgent); 280 } 281 282 // creates an unprovisioned interface createUnprovisionedInterface(String iface)283 private void createUnprovisionedInterface(String iface) throws Exception { 284 // To create an unprovisioned interface, provision and then "stop" it, i.e. stop its 285 // NetworkAgent and IpClient. One way this can be done is by provisioning an interface and 286 // then calling onNetworkUnwanted. 287 mNetFactory.addInterface(iface, HW_ADDR, createDefaultIpConfig(), 288 createInterfaceCapsBuilder(NetworkCapabilities.TRANSPORT_ETHERNET).build()); 289 assertTrue(mNetFactory.updateInterfaceLinkState(iface, true)); 290 291 clearInvocations(mIpClient); 292 clearInvocations(mNetworkAgent); 293 } 294 295 @Test testUpdateInterfaceLinkStateForActiveProvisioningInterface()296 public void testUpdateInterfaceLinkStateForActiveProvisioningInterface() throws Exception { 297 initEthernetNetworkFactory(); 298 createInterfaceUndergoingProvisioning(TEST_IFACE); 299 300 // verify that the IpClient gets shut down when interface state changes to down. 301 final boolean ret = mNetFactory.updateInterfaceLinkState(TEST_IFACE, false /* up */); 302 303 assertTrue(ret); 304 verify(mIpClient).shutdown(); 305 } 306 307 @Test testUpdateInterfaceLinkStateForNonExistingInterface()308 public void testUpdateInterfaceLinkStateForNonExistingInterface() throws Exception { 309 initEthernetNetworkFactory(); 310 311 // if interface was never added, link state cannot be updated. 312 final boolean ret = mNetFactory.updateInterfaceLinkState(TEST_IFACE, true /* up */); 313 314 assertFalse(ret); 315 verifyNoStopOrStart(); 316 } 317 318 @Test testProvisioningLoss()319 public void testProvisioningLoss() throws Exception { 320 initEthernetNetworkFactory(); 321 when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); 322 createAndVerifyProvisionedInterface(TEST_IFACE); 323 324 triggerOnProvisioningFailure(); 325 verifyStop(); 326 // provisioning loss should trigger a retry, since the interface is still there 327 verify(mIpClient).startProvisioning(any()); 328 } 329 330 @Test testProvisioningLossForDisappearedInterface()331 public void testProvisioningLossForDisappearedInterface() throws Exception { 332 initEthernetNetworkFactory(); 333 // mocked method returns null by default, but just to be explicit in the test: 334 when(mDeps.getNetworkInterfaceByName(eq(TEST_IFACE))).thenReturn(null); 335 336 createAndVerifyProvisionedInterface(TEST_IFACE); 337 triggerOnProvisioningFailure(); 338 339 // the interface disappeared and getNetworkInterfaceByName returns null, we should not retry 340 verify(mIpClient, never()).startProvisioning(any()); 341 verifyNoStopOrStart(); 342 } 343 verifyNoStopOrStart()344 private void verifyNoStopOrStart() { 345 verify(mNetworkAgent, never()).register(); 346 verify(mIpClient, never()).shutdown(); 347 verify(mNetworkAgent, never()).unregister(); 348 verify(mIpClient, never()).startProvisioning(any()); 349 } 350 351 @Test testNetworkUnwanted()352 public void testNetworkUnwanted() throws Exception { 353 initEthernetNetworkFactory(); 354 createAndVerifyProvisionedInterface(TEST_IFACE); 355 356 mNetworkAgent.getCallbacks().onNetworkUnwanted(); 357 mLooper.dispatchAll(); 358 verifyStop(); 359 } 360 361 @Test testNetworkUnwantedWithStaleNetworkAgent()362 public void testNetworkUnwantedWithStaleNetworkAgent() throws Exception { 363 initEthernetNetworkFactory(); 364 // ensures provisioning is restarted after provisioning loss 365 when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); 366 createAndVerifyProvisionedInterface(TEST_IFACE); 367 368 EthernetNetworkAgent.Callbacks oldCbs = mNetworkAgent.getCallbacks(); 369 // replace network agent in EthernetNetworkFactory 370 // Loss of provisioning will restart the ip client and network agent. 371 triggerOnProvisioningFailure(); 372 verify(mDeps).makeIpClient(any(), any(), any()); 373 374 triggerOnProvisioningSuccess(); 375 verify(mDeps).makeEthernetNetworkAgent(any(), any(), any(), any(), any(), any(), any()); 376 377 // verify that unwanted is ignored 378 clearInvocations(mIpClient); 379 clearInvocations(mNetworkAgent); 380 oldCbs.onNetworkUnwanted(); 381 verify(mIpClient, never()).shutdown(); 382 verify(mNetworkAgent, never()).unregister(); 383 } 384 385 @Test testTransportOverrideIsCorrectlySet()386 public void testTransportOverrideIsCorrectlySet() throws Exception { 387 initEthernetNetworkFactory(); 388 // createProvisionedInterface() has verifications in place for transport override 389 // functionality which for EthernetNetworkFactory is network score and legacy type mappings. 390 createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_ETHERNET, 391 ConnectivityManager.TYPE_ETHERNET); 392 createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_BLUETOOTH, 393 ConnectivityManager.TYPE_BLUETOOTH); 394 createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_WIFI, 395 ConnectivityManager.TYPE_WIFI); 396 createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_CELLULAR, 397 ConnectivityManager.TYPE_MOBILE); 398 createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_LOWPAN, 399 ConnectivityManager.TYPE_NONE); 400 createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_WIFI_AWARE, 401 ConnectivityManager.TYPE_NONE); 402 createVerifyAndRemoveProvisionedInterface(NetworkCapabilities.TRANSPORT_TEST, 403 ConnectivityManager.TYPE_NONE); 404 } 405 406 @Test testReachabilityLoss()407 public void testReachabilityLoss() throws Exception { 408 initEthernetNetworkFactory(); 409 createAndVerifyProvisionedInterface(TEST_IFACE); 410 411 triggerOnReachabilityLost(); 412 413 // Reachability loss should trigger a stop and start, since the interface is still there 414 verifyRestart(createDefaultIpConfig()); 415 } 416 getStaleIpClientCallbacks()417 private IpClientCallbacks getStaleIpClientCallbacks() throws Exception { 418 createAndVerifyProvisionedInterface(TEST_IFACE); 419 final IpClientCallbacks staleIpClientCallbacks = mIpClientCallbacks; 420 mNetFactory.removeInterface(TEST_IFACE); 421 verifyStop(); 422 assertNotSame(mIpClientCallbacks, staleIpClientCallbacks); 423 return staleIpClientCallbacks; 424 } 425 426 @Test testIgnoreOnIpLayerStartedCallbackForStaleCallback()427 public void testIgnoreOnIpLayerStartedCallbackForStaleCallback() throws Exception { 428 initEthernetNetworkFactory(); 429 final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks(); 430 431 staleIpClientCallbacks.onProvisioningSuccess(new LinkProperties()); 432 mLooper.dispatchAll(); 433 434 verify(mIpClient, never()).startProvisioning(any()); 435 verify(mNetworkAgent, never()).register(); 436 } 437 438 @Test testIgnoreOnIpLayerStoppedCallbackForStaleCallback()439 public void testIgnoreOnIpLayerStoppedCallbackForStaleCallback() throws Exception { 440 initEthernetNetworkFactory(); 441 when(mDeps.getNetworkInterfaceByName(TEST_IFACE)).thenReturn(mInterfaceParams); 442 final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks(); 443 444 staleIpClientCallbacks.onProvisioningFailure(new LinkProperties()); 445 mLooper.dispatchAll(); 446 447 verify(mIpClient, never()).startProvisioning(any()); 448 } 449 450 @Test testIgnoreLinkPropertiesCallbackForStaleCallback()451 public void testIgnoreLinkPropertiesCallbackForStaleCallback() throws Exception { 452 initEthernetNetworkFactory(); 453 final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks(); 454 final LinkProperties lp = new LinkProperties(); 455 456 staleIpClientCallbacks.onLinkPropertiesChange(lp); 457 mLooper.dispatchAll(); 458 459 verify(mNetworkAgent, never()).sendLinkPropertiesImpl(eq(lp)); 460 } 461 462 @Test testIgnoreNeighborLossCallbackForStaleCallback()463 public void testIgnoreNeighborLossCallbackForStaleCallback() throws Exception { 464 initEthernetNetworkFactory(); 465 final IpClientCallbacks staleIpClientCallbacks = getStaleIpClientCallbacks(); 466 467 staleIpClientCallbacks.onReachabilityLost("Neighbor Lost"); 468 mLooper.dispatchAll(); 469 470 verify(mIpClient, never()).startProvisioning(any()); 471 verify(mNetworkAgent, never()).register(); 472 } 473 verifyRestart(@onNull final IpConfiguration ipConfig)474 private void verifyRestart(@NonNull final IpConfiguration ipConfig) { 475 verifyStop(); 476 verifyStart(ipConfig); 477 } 478 verifyStart(@onNull final IpConfiguration ipConfig)479 private void verifyStart(@NonNull final IpConfiguration ipConfig) { 480 verify(mDeps).makeIpClient(any(Context.class), anyString(), any()); 481 verify(mIpClient).startProvisioning( 482 argThat(x -> Objects.equals(x.mStaticIpConfig, ipConfig.getStaticIpConfiguration())) 483 ); 484 } 485 verifyStop()486 private void verifyStop() { 487 verify(mIpClient).shutdown(); 488 verify(mNetworkAgent).unregister(); 489 } 490 verifyNetworkAgentRegistersAndConnects()491 private void verifyNetworkAgentRegistersAndConnects() { 492 verify(mNetworkAgent).register(); 493 verify(mNetworkAgent).markConnected(); 494 } 495 496 @Test testUpdateInterfaceRestartsAgentCorrectly()497 public void testUpdateInterfaceRestartsAgentCorrectly() throws Exception { 498 initEthernetNetworkFactory(); 499 createAndVerifyProvisionedInterface(TEST_IFACE); 500 final NetworkCapabilities capabilities = createDefaultFilterCaps(); 501 final IpConfiguration ipConfiguration = createStaticIpConfig(); 502 503 mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities); 504 triggerOnProvisioningSuccess(); 505 506 verify(mDeps).makeEthernetNetworkAgent(any(), any(), 507 eq(capabilities), any(), any(), any(), any()); 508 verifyRestart(ipConfiguration); 509 } 510 511 @Test testUpdateInterfaceForNonExistingInterface()512 public void testUpdateInterfaceForNonExistingInterface() throws Exception { 513 initEthernetNetworkFactory(); 514 // No interface exists due to not calling createAndVerifyProvisionedInterface(...). 515 final NetworkCapabilities capabilities = createDefaultFilterCaps(); 516 final IpConfiguration ipConfiguration = createStaticIpConfig(); 517 518 mNetFactory.updateInterface(TEST_IFACE, ipConfiguration, capabilities); 519 520 verifyNoStopOrStart(); 521 } 522 523 @Test testUpdateInterfaceWithNullIpConfiguration()524 public void testUpdateInterfaceWithNullIpConfiguration() throws Exception { 525 initEthernetNetworkFactory(); 526 createAndVerifyProvisionedInterface(TEST_IFACE); 527 528 final IpConfiguration initialIpConfig = createStaticIpConfig(); 529 mNetFactory.updateInterface(TEST_IFACE, initialIpConfig, null /*capabilities*/); 530 531 triggerOnProvisioningSuccess(); 532 verifyRestart(initialIpConfig); 533 534 // TODO: have verifyXyz functions clear invocations. 535 clearInvocations(mDeps); 536 clearInvocations(mIpClient); 537 clearInvocations(mNetworkAgent); 538 539 540 // verify that sending a null ipConfig does not update the current ipConfig. 541 mNetFactory.updateInterface(TEST_IFACE, null /*ipConfig*/, null /*capabilities*/); 542 triggerOnProvisioningSuccess(); 543 verifyRestart(initialIpConfig); 544 } 545 546 @Test testOnNetworkNeededOnStaleNetworkOffer()547 public void testOnNetworkNeededOnStaleNetworkOffer() throws Exception { 548 initEthernetNetworkFactory(); 549 createAndVerifyProvisionedInterface(TEST_IFACE); 550 mNetFactory.updateInterfaceLinkState(TEST_IFACE, false); 551 verify(mNetworkProvider).unregisterNetworkOffer(mNetworkOfferCallback); 552 // It is possible that even after a network offer is unregistered, CS still sends it 553 // onNetworkNeeded() callbacks. 554 mNetworkOfferCallback.onNetworkNeeded(createDefaultRequest()); 555 verify(mIpClient, never()).startProvisioning(any()); 556 } 557 558 @Test testGetMacAddressProvisionedInterface()559 public void testGetMacAddressProvisionedInterface() throws Exception { 560 initEthernetNetworkFactory(); 561 createAndVerifyProvisionedInterface(TEST_IFACE); 562 563 final String result = mNetFactory.getHwAddress(TEST_IFACE); 564 assertEquals(HW_ADDR, result); 565 } 566 567 @Test testGetMacAddressForNonExistingInterface()568 public void testGetMacAddressForNonExistingInterface() { 569 initEthernetNetworkFactory(); 570 571 final String result = mNetFactory.getHwAddress(TEST_IFACE); 572 // No interface exists due to not calling createAndVerifyProvisionedInterface(...). 573 assertNull(result); 574 } 575 } 576