Add a test for upstream selection.
Currently, upstream selection is split between the Tethering and
UpstreamNetworkMonitor classes. The UpstreamNetworkMonitor bits
are unit tested, but there are no tests for the interaction of
the two. Add a simple test.
In order to do this, remove the code that controls the
UpstreamNetworkMonitor spy from prepareUsbTethering. This is so
that the new test can call prepareUsbTethering but still rely on
the behaviour of the actual UpstreamNetworkMonitor.
Bug: 173068192
Test: atest TetheringTests
Change-Id: If2ef9af82bc0cbff9172e575ad3d7686e5b492da
diff --git a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
index 40b7c55..0611086 100644
--- a/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
+++ b/Tethering/tests/unit/src/com/android/networkstack/tethering/TetheringTest.java
@@ -78,6 +78,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
@@ -165,6 +166,7 @@
import com.android.internal.util.StateMachine;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.networkstack.tethering.TestConnectivityManager.TestNetworkAgent;
import com.android.testutils.MiscAsserts;
import org.junit.After;
@@ -174,6 +176,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -501,6 +504,7 @@
prop.setInterfaceName(interfaceName);
if (withIPv4) {
+ prop.addLinkAddress(new LinkAddress("10.1.2.3/15"));
prop.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
InetAddresses.parseNumericAddress("10.0.0.1"),
interfaceName, RTN_UNICAST));
@@ -830,9 +834,7 @@
mTethering.interfaceStatusChanged(TEST_NCM_IFNAME, true);
}
- private void prepareUsbTethering(UpstreamNetworkState upstreamState) {
- initTetheringUpstream(upstreamState);
-
+ private void prepareUsbTethering() {
// Emulate pressing the USB tethering button in Settings UI.
final TetheringRequestParcel request = createTetheringRequestParcel(TETHERING_USB);
mTethering.startTethering(request, null);
@@ -847,7 +849,8 @@
@Test
public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
UpstreamNetworkState upstreamState = buildMobileIPv4UpstreamState();
- prepareUsbTethering(upstreamState);
+ initTetheringUpstream(upstreamState);
+ prepareUsbTethering();
// This should produce no activity of any kind.
verifyNoMoreInteractions(mNetd);
@@ -942,7 +945,8 @@
}
private void runUsbTethering(UpstreamNetworkState upstreamState) {
- prepareUsbTethering(upstreamState);
+ initTetheringUpstream(upstreamState);
+ prepareUsbTethering();
sendUsbBroadcast(true, true, true, TETHERING_USB);
mLooper.dispatchAll();
}
@@ -1083,6 +1087,73 @@
verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
}
+ @Test
+ public void testAutomaticUpstreamSelection() throws Exception {
+ // Enable automatic upstream selection.
+ when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(true);
+ sendConfigurationChanged();
+ mLooper.dispatchAll();
+
+ InOrder inOrder = inOrder(mCm, mUpstreamNetworkMonitor);
+
+ // Start USB tethering with no current upstream.
+ prepareUsbTethering();
+ sendUsbBroadcast(true, true, true, TETHERING_USB);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).startObserveAllNetworks();
+ inOrder.verify(mUpstreamNetworkMonitor).registerMobileNetworkRequest();
+
+ // Pretend cellular connected and expect the upstream to be set.
+ TestNetworkAgent mobile = new TestNetworkAgent(mCm, buildMobileDualStackUpstreamState());
+ mobile.fakeConnect();
+ mCm.makeDefaultNetwork(mobile);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+
+ // Switch upstreams a few times.
+ // TODO: there may be a race where if the effects of the CONNECTIVITY_ACTION happen before
+ // UpstreamNetworkMonitor gets onCapabilitiesChanged on CALLBACK_DEFAULT_INTERNET, the
+ // upstream does not change. Extend TestConnectivityManager to simulate this condition and
+ // write a test for this.
+ TestNetworkAgent wifi = new TestNetworkAgent(mCm, buildWifiUpstreamState());
+ wifi.fakeConnect();
+ mCm.makeDefaultNetwork(wifi);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(wifi.networkId);
+
+ mCm.makeDefaultNetwork(mobile);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+
+ // Wifi disconnecting should not have any affect since it's not the current upstream.
+ wifi.fakeDisconnect();
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor, never()).setCurrentUpstream(any());
+
+ // Lose and regain upstream.
+ assertTrue(mUpstreamNetworkMonitor.getCurrentPreferredUpstream().linkProperties
+ .hasIPv4Address());
+ mobile.fakeDisconnect();
+ mCm.makeDefaultNetwork(null);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+
+ mobile = new TestNetworkAgent(mCm, buildMobile464xlatUpstreamState());
+ mobile.fakeConnect();
+ mCm.makeDefaultNetwork(mobile);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(mobile.networkId);
+
+ // Check the IP addresses to ensure that the upstream is indeed not the same as the previous
+ // mobile upstream, even though the netId is (unrealistically) the same.
+ assertFalse(mUpstreamNetworkMonitor.getCurrentPreferredUpstream().linkProperties
+ .hasIPv4Address());
+ mobile.fakeDisconnect();
+ mCm.makeDefaultNetwork(null);
+ mLooper.dispatchAll();
+ inOrder.verify(mUpstreamNetworkMonitor).setCurrentUpstream(null);
+ }
+
private void runNcmTethering() {
prepareNcmTethering();
sendUsbBroadcast(true, true, true, TETHERING_NCM);