Add the ability to affect ordering in the tethering unit tests.
Currently, TestConnectivityManager immediately sends all callbacks and broadcasts to the Tethering code as soon as the test code makes any change. This makes it impossible to affect the order in which those events are delivered to the Tethering code, so it is not possible to test for races. Fix some of this as follows: 1. Make TestConnectivityManager post all its callbacks to the handlers that Tethering registered them with. 2. In TetheringTest, use the existing TestLooper object to advance time manually. Also use setUseRegisteredHandlers to ensure that the broadcasts are sent in order. This requires calling dispatchAll() after sending the broadcast to preserve the existing synchronous behaviour. Take advantage of that to remove lots of existing dispatchAll calls. 3. Add a TestLooper to UpstreamNetworkMonitorTest and use it. Keep the test passing by adding lots of mLooper.dispatchAll(), which is a bit ugly but probably acceptable given the additional coverage it provides. This exposes an existing bug in the code where if upstream selection is in automatic mode, and all CONNECTIVITY_ACTION broadcasts are received before all NetworkCallbacks, the code does not switch upstream. In order to make the tests pass, re-order the CONNECTIVITY_ACTION broadcasts with the NetworkCallbacks in TestConnectivityManager so as not to trigger the bug. A future CL will make the order configurable. While I'm at it, switch TestConnectivityManager from HashMap to ArrayMap, which is generally preferred for maps that do not contain too many elements. Bug: 173068192 Test: test-only change Change-Id: I964f365c691fbc396ab0a87f292bd32b123011fe
This commit is contained in:
@@ -30,12 +30,10 @@ import android.net.NetworkInfo;
|
||||
import android.net.NetworkRequest;
|
||||
import android.os.Handler;
|
||||
import android.os.UserHandle;
|
||||
import android.util.ArrayMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Simulates upstream switching and sending NetworkCallbacks and CONNECTIVITY_ACTION broadcasts.
|
||||
@@ -60,12 +58,12 @@ import java.util.Set;
|
||||
* that state changes), this may become less important or unnecessary.
|
||||
*/
|
||||
public class TestConnectivityManager extends ConnectivityManager {
|
||||
public Map<NetworkCallback, Handler> allCallbacks = new HashMap<>();
|
||||
public Set<NetworkCallback> trackingDefault = new HashSet<>();
|
||||
public Map<NetworkCallback, NetworkRequestInfo> allCallbacks = new ArrayMap<>();
|
||||
public Map<NetworkCallback, NetworkRequestInfo> trackingDefault = new ArrayMap<>();
|
||||
public TestNetworkAgent defaultNetwork = null;
|
||||
public Map<NetworkCallback, NetworkRequest> listening = new HashMap<>();
|
||||
public Map<NetworkCallback, NetworkRequest> requested = new HashMap<>();
|
||||
public Map<NetworkCallback, Integer> legacyTypeMap = new HashMap<>();
|
||||
public Map<NetworkCallback, NetworkRequestInfo> listening = new ArrayMap<>();
|
||||
public Map<NetworkCallback, NetworkRequestInfo> requested = new ArrayMap<>();
|
||||
public Map<NetworkCallback, Integer> legacyTypeMap = new ArrayMap<>();
|
||||
|
||||
private final NetworkRequest mDefaultRequest;
|
||||
private final Context mContext;
|
||||
@@ -86,6 +84,15 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
mDefaultRequest = defaultRequest;
|
||||
}
|
||||
|
||||
class NetworkRequestInfo {
|
||||
public final NetworkRequest request;
|
||||
public final Handler handler;
|
||||
NetworkRequestInfo(NetworkRequest r, Handler h) {
|
||||
request = r;
|
||||
handler = h;
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasNoCallbacks() {
|
||||
return allCallbacks.isEmpty()
|
||||
&& trackingDefault.isEmpty()
|
||||
@@ -106,8 +113,8 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
final NetworkCapabilities empty = new NetworkCapabilities();
|
||||
empty.clearAll();
|
||||
|
||||
for (NetworkRequest req : listening.values()) {
|
||||
if (req.networkCapabilities.equalRequestableCapabilities(empty)) {
|
||||
for (NetworkRequestInfo nri : listening.values()) {
|
||||
if (nri.request.networkCapabilities.equalRequestableCapabilities(empty)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -118,40 +125,52 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
return ++mNetworkId;
|
||||
}
|
||||
|
||||
void makeDefaultNetwork(TestNetworkAgent agent) {
|
||||
if (Objects.equals(defaultNetwork, agent)) return;
|
||||
|
||||
final TestNetworkAgent formerDefault = defaultNetwork;
|
||||
defaultNetwork = agent;
|
||||
|
||||
private void sendDefaultNetworkBroadcasts(TestNetworkAgent formerDefault,
|
||||
TestNetworkAgent defaultNetwork) {
|
||||
if (formerDefault != null) {
|
||||
sendConnectivityAction(formerDefault.legacyType, false /* connected */);
|
||||
}
|
||||
if (defaultNetwork != null) {
|
||||
sendConnectivityAction(defaultNetwork.legacyType, true /* connected */);
|
||||
}
|
||||
}
|
||||
|
||||
for (NetworkCallback cb : trackingDefault) {
|
||||
private void sendDefaultNetworkCallbacks(TestNetworkAgent formerDefault,
|
||||
TestNetworkAgent defaultNetwork) {
|
||||
for (NetworkCallback cb : trackingDefault.keySet()) {
|
||||
final NetworkRequestInfo nri = trackingDefault.get(cb);
|
||||
if (defaultNetwork != null) {
|
||||
cb.onAvailable(defaultNetwork.networkId);
|
||||
cb.onCapabilitiesChanged(
|
||||
defaultNetwork.networkId, defaultNetwork.networkCapabilities);
|
||||
cb.onLinkPropertiesChanged(
|
||||
defaultNetwork.networkId, defaultNetwork.linkProperties);
|
||||
nri.handler.post(() -> cb.onAvailable(defaultNetwork.networkId));
|
||||
nri.handler.post(() -> cb.onCapabilitiesChanged(
|
||||
defaultNetwork.networkId, defaultNetwork.networkCapabilities));
|
||||
nri.handler.post(() -> cb.onLinkPropertiesChanged(
|
||||
defaultNetwork.networkId, defaultNetwork.linkProperties));
|
||||
} else if (formerDefault != null) {
|
||||
nri.handler.post(() -> cb.onLost(formerDefault.networkId));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void makeDefaultNetwork(TestNetworkAgent agent) {
|
||||
if (Objects.equals(defaultNetwork, agent)) return;
|
||||
|
||||
final TestNetworkAgent formerDefault = defaultNetwork;
|
||||
defaultNetwork = agent;
|
||||
|
||||
sendDefaultNetworkCallbacks(formerDefault, defaultNetwork);
|
||||
sendDefaultNetworkBroadcasts(formerDefault, defaultNetwork);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestNetwork(NetworkRequest req, NetworkCallback cb, Handler h) {
|
||||
assertFalse(allCallbacks.containsKey(cb));
|
||||
allCallbacks.put(cb, h);
|
||||
allCallbacks.put(cb, new NetworkRequestInfo(req, h));
|
||||
if (mDefaultRequest.equals(req)) {
|
||||
assertFalse(trackingDefault.contains(cb));
|
||||
trackingDefault.add(cb);
|
||||
assertFalse(trackingDefault.containsKey(cb));
|
||||
trackingDefault.put(cb, new NetworkRequestInfo(req, h));
|
||||
} else {
|
||||
assertFalse(requested.containsKey(cb));
|
||||
requested.put(cb, req);
|
||||
requested.put(cb, new NetworkRequestInfo(req, h));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,9 +183,9 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
public void requestNetwork(NetworkRequest req,
|
||||
int timeoutMs, int legacyType, Handler h, NetworkCallback cb) {
|
||||
assertFalse(allCallbacks.containsKey(cb));
|
||||
allCallbacks.put(cb, h);
|
||||
allCallbacks.put(cb, new NetworkRequestInfo(req, h));
|
||||
assertFalse(requested.containsKey(cb));
|
||||
requested.put(cb, req);
|
||||
requested.put(cb, new NetworkRequestInfo(req, h));
|
||||
assertFalse(legacyTypeMap.containsKey(cb));
|
||||
if (legacyType != ConnectivityManager.TYPE_NONE) {
|
||||
legacyTypeMap.put(cb, legacyType);
|
||||
@@ -176,9 +195,9 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
@Override
|
||||
public void registerNetworkCallback(NetworkRequest req, NetworkCallback cb, Handler h) {
|
||||
assertFalse(allCallbacks.containsKey(cb));
|
||||
allCallbacks.put(cb, h);
|
||||
allCallbacks.put(cb, new NetworkRequestInfo(req, h));
|
||||
assertFalse(listening.containsKey(cb));
|
||||
listening.put(cb, req);
|
||||
listening.put(cb, new NetworkRequestInfo(req, h));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -198,7 +217,7 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
|
||||
@Override
|
||||
public void unregisterNetworkCallback(NetworkCallback cb) {
|
||||
if (trackingDefault.contains(cb)) {
|
||||
if (trackingDefault.containsKey(cb)) {
|
||||
trackingDefault.remove(cb);
|
||||
} else if (listening.containsKey(cb)) {
|
||||
listening.remove(cb);
|
||||
@@ -211,7 +230,7 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
allCallbacks.remove(cb);
|
||||
|
||||
assertFalse(allCallbacks.containsKey(cb));
|
||||
assertFalse(trackingDefault.contains(cb));
|
||||
assertFalse(trackingDefault.containsKey(cb));
|
||||
assertFalse(listening.containsKey(cb));
|
||||
assertFalse(requested.containsKey(cb));
|
||||
}
|
||||
@@ -275,23 +294,25 @@ public class TestConnectivityManager extends ConnectivityManager {
|
||||
}
|
||||
|
||||
public void fakeConnect() {
|
||||
for (NetworkRequest request : cm.requested.values()) {
|
||||
if (matchesLegacyType(request.legacyType)) {
|
||||
for (NetworkRequestInfo nri : cm.requested.values()) {
|
||||
if (matchesLegacyType(nri.request.legacyType)) {
|
||||
cm.sendConnectivityAction(legacyType, true /* connected */);
|
||||
// In practice, a given network can match only one legacy type.
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (NetworkCallback cb : cm.listening.keySet()) {
|
||||
cb.onAvailable(networkId);
|
||||
cb.onCapabilitiesChanged(networkId, copy(networkCapabilities));
|
||||
cb.onLinkPropertiesChanged(networkId, copy(linkProperties));
|
||||
final NetworkRequestInfo nri = cm.listening.get(cb);
|
||||
nri.handler.post(() -> cb.onAvailable(networkId));
|
||||
nri.handler.post(() -> cb.onCapabilitiesChanged(
|
||||
networkId, copy(networkCapabilities)));
|
||||
nri.handler.post(() -> cb.onLinkPropertiesChanged(networkId, copy(linkProperties)));
|
||||
}
|
||||
}
|
||||
|
||||
public void fakeDisconnect() {
|
||||
for (NetworkRequest request : cm.requested.values()) {
|
||||
if (matchesLegacyType(request.legacyType)) {
|
||||
for (NetworkRequestInfo nri : cm.requested.values()) {
|
||||
if (matchesLegacyType(nri.request.legacyType)) {
|
||||
cm.sendConnectivityAction(legacyType, false /* connected */);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -618,6 +618,7 @@ public class TetheringTest {
|
||||
when(mOffloadHardwareInterface.getForwardedStats(any())).thenReturn(mForwardedStats);
|
||||
|
||||
mServiceContext = new TestContext(mContext);
|
||||
mServiceContext.setUseRegisteredHandlers(true);
|
||||
mContentResolver = new MockContentResolver(mServiceContext);
|
||||
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
||||
setTetheringSupported(true /* supported */);
|
||||
@@ -716,6 +717,7 @@ public class TetheringTest {
|
||||
final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
|
||||
intent.putExtra(EXTRA_WIFI_AP_STATE, state);
|
||||
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
|
||||
@@ -724,6 +726,7 @@ public class TetheringTest {
|
||||
intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
|
||||
intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
|
||||
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
private static final String[] P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST = {
|
||||
@@ -750,6 +753,7 @@ public class TetheringTest {
|
||||
|
||||
mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL,
|
||||
P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
private void sendUsbBroadcast(boolean connected, boolean configured, boolean function,
|
||||
@@ -763,11 +767,13 @@ public class TetheringTest {
|
||||
intent.putExtra(USB_FUNCTION_NCM, function);
|
||||
}
|
||||
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
private void sendConfigurationChanged() {
|
||||
final Intent intent = new Intent(Intent.ACTION_CONFIGURATION_CHANGED);
|
||||
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
private void verifyDefaultNetworkRequestFiled() {
|
||||
@@ -809,7 +815,6 @@ public class TetheringTest {
|
||||
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
|
||||
}
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
// If, and only if, Tethering received an interface status changed then
|
||||
// it creates a IpServer and sends out a broadcast indicating that the
|
||||
@@ -857,7 +862,6 @@ public class TetheringTest {
|
||||
|
||||
// Pretend we then receive USB configured broadcast.
|
||||
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
||||
mLooper.dispatchAll();
|
||||
// Now we should see the start of tethering mechanics (in this case:
|
||||
// tetherMatchingInterfaces() which starts by fetching all interfaces).
|
||||
verify(mNetd, times(1)).interfaceGetList();
|
||||
@@ -886,7 +890,6 @@ public class TetheringTest {
|
||||
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
|
||||
}
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
|
||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||
@@ -948,7 +951,6 @@ public class TetheringTest {
|
||||
initTetheringUpstream(upstreamState);
|
||||
prepareUsbTethering();
|
||||
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
private void assertSetIfaceToDadProxy(final int numOfCalls, final String ifaceName) {
|
||||
@@ -1099,7 +1101,6 @@ public class TetheringTest {
|
||||
// Start USB tethering with no current upstream.
|
||||
prepareUsbTethering();
|
||||
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
||||
mLooper.dispatchAll();
|
||||
inOrder.verify(mUpstreamNetworkMonitor).startObserveAllNetworks();
|
||||
inOrder.verify(mUpstreamNetworkMonitor).setTryCell(true);
|
||||
|
||||
@@ -1157,7 +1158,6 @@ public class TetheringTest {
|
||||
private void runNcmTethering() {
|
||||
prepareNcmTethering();
|
||||
sendUsbBroadcast(true, true, true, TETHERING_NCM);
|
||||
mLooper.dispatchAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1205,7 +1205,6 @@ public class TetheringTest {
|
||||
// tethering mode is to be started.
|
||||
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
// There is 1 IpServer state change event: STATE_AVAILABLE
|
||||
verify(mNotificationUpdater, times(1)).onDownstreamChanged(DOWNSTREAM_NONE);
|
||||
@@ -1233,7 +1232,6 @@ public class TetheringTest {
|
||||
// tethering mode is to be started.
|
||||
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
|
||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||
@@ -1310,7 +1308,6 @@ public class TetheringTest {
|
||||
// tethering mode is to be started.
|
||||
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
// We verify get/set called three times here: twice for setup and once during
|
||||
// teardown because all events happen over the course of the single
|
||||
@@ -1634,7 +1631,6 @@ public class TetheringTest {
|
||||
|
||||
mTethering.startTethering(createTetheringRequestParcel(TETHERING_WIFI), null);
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
|
||||
mLooper.dispatchAll();
|
||||
tetherState = callback.pollTetherStatesChanged();
|
||||
assertArrayEquals(tetherState.tetheredList, new String[] {TEST_WLAN_IFNAME});
|
||||
callback.expectUpstreamChanged(upstreamState.network);
|
||||
@@ -1656,7 +1652,6 @@ public class TetheringTest {
|
||||
mLooper.dispatchAll();
|
||||
mTethering.stopTethering(TETHERING_WIFI);
|
||||
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_DISABLED);
|
||||
mLooper.dispatchAll();
|
||||
tetherState = callback2.pollTetherStatesChanged();
|
||||
assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
|
||||
mLooper.dispatchAll();
|
||||
@@ -1749,7 +1744,6 @@ public class TetheringTest {
|
||||
mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
|
||||
}
|
||||
sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
|
||||
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||
@@ -1767,7 +1761,6 @@ public class TetheringTest {
|
||||
// is being removed.
|
||||
sendWifiP2pConnectionChanged(false, true, TEST_P2P_IFNAME);
|
||||
mTethering.interfaceRemoved(TEST_P2P_IFNAME);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verify(mNetd, times(1)).tetherApplyDnsInterfaces();
|
||||
verify(mNetd, times(1)).tetherInterfaceRemove(TEST_P2P_IFNAME);
|
||||
@@ -1790,7 +1783,6 @@ public class TetheringTest {
|
||||
mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
|
||||
}
|
||||
sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
|
||||
verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
|
||||
@@ -1802,7 +1794,6 @@ public class TetheringTest {
|
||||
// is being removed.
|
||||
sendWifiP2pConnectionChanged(false, false, TEST_P2P_IFNAME);
|
||||
mTethering.interfaceRemoved(TEST_P2P_IFNAME);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verify(mNetd, never()).tetherApplyDnsInterfaces();
|
||||
verify(mNetd, never()).tetherInterfaceRemove(TEST_P2P_IFNAME);
|
||||
@@ -1838,7 +1829,6 @@ public class TetheringTest {
|
||||
mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
|
||||
}
|
||||
sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
|
||||
mLooper.dispatchAll();
|
||||
|
||||
verify(mNetd, never()).interfaceSetCfg(any(InterfaceConfigurationParcel.class));
|
||||
verify(mNetd, never()).tetherInterfaceAdd(TEST_P2P_IFNAME);
|
||||
@@ -1968,7 +1958,6 @@ public class TetheringTest {
|
||||
// Expect that when USB comes up, the DHCP server is configured with the requested address.
|
||||
mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
|
||||
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
||||
mLooper.dispatchAll();
|
||||
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).startWithCallbacks(
|
||||
any(), any());
|
||||
verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
|
||||
@@ -1988,7 +1977,6 @@ public class TetheringTest {
|
||||
verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
|
||||
mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
|
||||
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
||||
mLooper.dispatchAll();
|
||||
verify(mNetd).interfaceSetCfg(argThat(cfg -> serverAddr.equals(cfg.ipv4Addr)));
|
||||
verify(mIpServerDependencies, times(1)).makeDhcpServer(any(), dhcpParamsCaptor.capture(),
|
||||
any());
|
||||
@@ -2212,7 +2200,6 @@ public class TetheringTest {
|
||||
|
||||
mTethering.interfaceStatusChanged(TEST_USB_IFNAME, true);
|
||||
sendUsbBroadcast(true, true, true, TETHERING_USB);
|
||||
mLooper.dispatchAll();
|
||||
assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_USB_IFNAME);
|
||||
assertContains(Arrays.asList(mTethering.getTetherableIfaces()), TEST_ETH_IFNAME);
|
||||
assertEquals(TETHER_ERROR_IFACE_CFG_ERROR, mTethering.getLastTetherError(TEST_USB_IFNAME));
|
||||
@@ -2251,7 +2238,6 @@ public class TetheringTest {
|
||||
// Run local only tethering.
|
||||
mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
|
||||
sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
|
||||
mLooper.dispatchAll();
|
||||
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS)).startWithCallbacks(
|
||||
any(), dhcpEventCbsCaptor.capture());
|
||||
eventCallbacks = dhcpEventCbsCaptor.getValue();
|
||||
@@ -2268,7 +2254,6 @@ public class TetheringTest {
|
||||
// Run wifi tethering.
|
||||
mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
|
||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
|
||||
mLooper.dispatchAll();
|
||||
verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS)).startWithCallbacks(
|
||||
any(), dhcpEventCbsCaptor.capture());
|
||||
eventCallbacks = dhcpEventCbsCaptor.getValue();
|
||||
|
||||
@@ -50,13 +50,16 @@ import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkRequest;
|
||||
import android.net.util.SharedLog;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.test.TestLooper;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.util.State;
|
||||
import com.android.internal.util.StateMachine;
|
||||
import com.android.networkstack.tethering.TestConnectivityManager.NetworkRequestInfo;
|
||||
import com.android.networkstack.tethering.TestConnectivityManager.TestNetworkAgent;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -100,6 +103,8 @@ public class UpstreamNetworkMonitorTest {
|
||||
private TestConnectivityManager mCM;
|
||||
private UpstreamNetworkMonitor mUNM;
|
||||
|
||||
private final TestLooper mLooper = new TestLooper();
|
||||
|
||||
@Before public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
reset(mContext);
|
||||
@@ -109,7 +114,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
when(mEntitleMgr.isCellularUpstreamPermitted()).thenReturn(true);
|
||||
|
||||
mCM = spy(new TestConnectivityManager(mContext, mCS, sDefaultRequest));
|
||||
mSM = new TestStateMachine();
|
||||
mSM = new TestStateMachine(mLooper.getLooper());
|
||||
mUNM = new UpstreamNetworkMonitor(mCM, mSM, mLog, EVENT_UNM_UPDATE);
|
||||
}
|
||||
|
||||
@@ -295,14 +300,17 @@ public class UpstreamNetworkMonitorTest {
|
||||
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, WIFI_CAPABILITIES);
|
||||
wifiAgent.fakeConnect();
|
||||
mLooper.dispatchAll();
|
||||
// WiFi is up, we should prefer it.
|
||||
assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
wifiAgent.fakeDisconnect();
|
||||
mLooper.dispatchAll();
|
||||
// There are no networks, so there is nothing to select.
|
||||
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES);
|
||||
cellAgent.fakeConnect();
|
||||
mLooper.dispatchAll();
|
||||
assertSatisfiesLegacyType(TYPE_NONE, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
|
||||
preferredTypes.add(TYPE_MOBILE_DUN);
|
||||
@@ -319,7 +327,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
// Check to see we filed an explicit request.
|
||||
assertEquals(1, mCM.requested.size());
|
||||
NetworkRequest netReq = (NetworkRequest) mCM.requested.values().toArray()[0];
|
||||
NetworkRequest netReq = ((NetworkRequestInfo) mCM.requested.values().toArray()[0]).request;
|
||||
assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR));
|
||||
assertFalse(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN));
|
||||
// mobile is not permitted, we should not use HIPRI.
|
||||
@@ -332,6 +340,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
|
||||
wifiAgent.fakeConnect();
|
||||
mLooper.dispatchAll();
|
||||
// WiFi is up, and we should prefer it over cell.
|
||||
assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
assertEquals(0, mCM.requested.size());
|
||||
@@ -344,17 +353,19 @@ public class UpstreamNetworkMonitorTest {
|
||||
|
||||
final TestNetworkAgent dunAgent = new TestNetworkAgent(mCM, DUN_CAPABILITIES);
|
||||
dunAgent.fakeConnect();
|
||||
mLooper.dispatchAll();
|
||||
|
||||
// WiFi is still preferred.
|
||||
assertSatisfiesLegacyType(TYPE_WIFI, mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
|
||||
// WiFi goes down, cell and DUN are still up but only DUN is preferred.
|
||||
wifiAgent.fakeDisconnect();
|
||||
mLooper.dispatchAll();
|
||||
assertSatisfiesLegacyType(TYPE_MOBILE_DUN,
|
||||
mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
// Check to see we filed an explicit request.
|
||||
assertEquals(1, mCM.requested.size());
|
||||
netReq = (NetworkRequest) mCM.requested.values().toArray()[0];
|
||||
netReq = ((NetworkRequestInfo) mCM.requested.values().toArray()[0]).request;
|
||||
assertTrue(netReq.networkCapabilities.hasTransport(TRANSPORT_CELLULAR));
|
||||
assertTrue(netReq.networkCapabilities.hasCapability(NET_CAPABILITY_DUN));
|
||||
// mobile is not permitted, we should not use DUN.
|
||||
@@ -378,6 +389,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES);
|
||||
cellAgent.fakeConnect();
|
||||
mCM.makeDefaultNetwork(cellAgent);
|
||||
mLooper.dispatchAll();
|
||||
assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
|
||||
assertEquals(0, mCM.requested.size());
|
||||
|
||||
@@ -390,11 +402,13 @@ public class UpstreamNetworkMonitorTest {
|
||||
// [2] WiFi connects but not validated/promoted to default -> mobile selected.
|
||||
final TestNetworkAgent wifiAgent = new TestNetworkAgent(mCM, WIFI_CAPABILITIES);
|
||||
wifiAgent.fakeConnect();
|
||||
mLooper.dispatchAll();
|
||||
assertEquals(cellAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
|
||||
assertEquals(0, mCM.requested.size());
|
||||
|
||||
// [3] WiFi validates and is promoted to the default network -> WiFi selected.
|
||||
mCM.makeDefaultNetwork(wifiAgent);
|
||||
mLooper.dispatchAll();
|
||||
assertEquals(wifiAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
|
||||
assertEquals(0, mCM.requested.size());
|
||||
|
||||
@@ -406,6 +420,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
|
||||
// [5] WiFi no longer validated, mobile becomes default, DUN required -> null selected.
|
||||
mCM.makeDefaultNetwork(cellAgent);
|
||||
mLooper.dispatchAll();
|
||||
assertEquals(null, mUNM.getCurrentPreferredUpstream());
|
||||
assertEquals(1, mCM.requested.size());
|
||||
assertTrue(isDunRequested());
|
||||
@@ -415,6 +430,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
dunAgent.networkCapabilities.addCapability(NET_CAPABILITY_DUN);
|
||||
dunAgent.networkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
|
||||
dunAgent.fakeConnect();
|
||||
mLooper.dispatchAll();
|
||||
assertEquals(dunAgent.networkId, mUNM.getCurrentPreferredUpstream().network);
|
||||
assertEquals(1, mCM.requested.size());
|
||||
|
||||
@@ -461,6 +477,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
}
|
||||
wifiAgent.fakeConnect();
|
||||
wifiAgent.sendLinkProperties();
|
||||
mLooper.dispatchAll();
|
||||
|
||||
local = mUNM.getLocalPrefixes();
|
||||
assertPrefixSet(local, INCLUDES, alreadySeen);
|
||||
@@ -485,6 +502,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
}
|
||||
cellAgent.fakeConnect();
|
||||
cellAgent.sendLinkProperties();
|
||||
mLooper.dispatchAll();
|
||||
|
||||
local = mUNM.getLocalPrefixes();
|
||||
assertPrefixSet(local, INCLUDES, alreadySeen);
|
||||
@@ -506,6 +524,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
}
|
||||
dunAgent.fakeConnect();
|
||||
dunAgent.sendLinkProperties();
|
||||
mLooper.dispatchAll();
|
||||
|
||||
local = mUNM.getLocalPrefixes();
|
||||
assertPrefixSet(local, INCLUDES, alreadySeen);
|
||||
@@ -517,6 +536,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
// [4] Pretend Wi-Fi disconnected. It's addresses/prefixes should no
|
||||
// longer be included (should be properly removed).
|
||||
wifiAgent.fakeDisconnect();
|
||||
mLooper.dispatchAll();
|
||||
local = mUNM.getLocalPrefixes();
|
||||
assertPrefixSet(local, EXCLUDES, wifiLinkPrefixes);
|
||||
assertPrefixSet(local, INCLUDES, cellLinkPrefixes);
|
||||
@@ -524,6 +544,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
|
||||
// [5] Pretend mobile disconnected.
|
||||
cellAgent.fakeDisconnect();
|
||||
mLooper.dispatchAll();
|
||||
local = mUNM.getLocalPrefixes();
|
||||
assertPrefixSet(local, EXCLUDES, wifiLinkPrefixes);
|
||||
assertPrefixSet(local, EXCLUDES, cellLinkPrefixes);
|
||||
@@ -531,6 +552,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
|
||||
// [6] Pretend DUN disconnected.
|
||||
dunAgent.fakeDisconnect();
|
||||
mLooper.dispatchAll();
|
||||
local = mUNM.getLocalPrefixes();
|
||||
assertTrue(local.isEmpty());
|
||||
}
|
||||
@@ -550,6 +572,7 @@ public class UpstreamNetworkMonitorTest {
|
||||
// Setup mobile network.
|
||||
final TestNetworkAgent cellAgent = new TestNetworkAgent(mCM, CELL_CAPABILITIES);
|
||||
cellAgent.fakeConnect();
|
||||
mLooper.dispatchAll();
|
||||
|
||||
assertSatisfiesLegacyType(TYPE_MOBILE_HIPRI,
|
||||
mUNM.selectPreferredUpstreamType(preferredTypes));
|
||||
@@ -575,8 +598,8 @@ public class UpstreamNetworkMonitorTest {
|
||||
}
|
||||
|
||||
private boolean isDunRequested() {
|
||||
for (NetworkRequest req : mCM.requested.values()) {
|
||||
if (req.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
|
||||
for (NetworkRequestInfo nri : mCM.requested.values()) {
|
||||
if (nri.request.networkCapabilities.hasCapability(NET_CAPABILITY_DUN)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -602,8 +625,8 @@ public class UpstreamNetworkMonitorTest {
|
||||
}
|
||||
}
|
||||
|
||||
public TestStateMachine() {
|
||||
super("UpstreamNetworkMonitor.TestStateMachine");
|
||||
public TestStateMachine(Looper looper) {
|
||||
super("UpstreamNetworkMonitor.TestStateMachine", looper);
|
||||
addState(mLoggingState);
|
||||
setInitialState(mLoggingState);
|
||||
super.start();
|
||||
|
||||
Reference in New Issue
Block a user