Unit test TelephonySubscriptionSnapshot changes for VCNs.

This CL adds unit testing for TelephonySubscriptionSnapshot updates in
UnderlyingNetworkTracker, Vcn, and VcnManagementService.

Bug: 177364490
Test: atest FrameworksVcnTests
Change-Id: I244744194a1360c7c7dee062a302e04f9b5efc32
This commit is contained in:
Cody Kesting
2021-01-22 09:59:07 -08:00
parent 2b0754517c
commit 50e9bf04aa
6 changed files with 241 additions and 35 deletions

View File

@@ -27,11 +27,16 @@ import android.os.Message;
import android.os.ParcelUuid;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Represents an single instance of a VCN.
@@ -99,7 +104,8 @@ public class Vcn extends Handler {
this(vcnContext, subscriptionGroup, config, snapshot, new Dependencies());
}
private Vcn(
@VisibleForTesting(visibility = Visibility.PRIVATE)
public Vcn(
@NonNull VcnContext vcnContext,
@NonNull ParcelUuid subscriptionGroup,
@NonNull VcnConfig config,
@@ -137,6 +143,12 @@ public class Vcn extends Handler {
sendMessageAtFrontOfQueue(obtainMessage(MSG_CMD_TEARDOWN));
}
/** Get current Gateways for testing purposes */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public Set<VcnGatewayConnection> getVcnGatewayConnections() {
return Collections.unmodifiableSet(new HashSet<>(mVcnGatewayConnections.values()));
}
private class VcnNetworkRequestListener implements VcnNetworkProvider.NetworkRequestListener {
@Override
public void onNetworkRequested(@NonNull NetworkRequest request, int score, int providerId) {
@@ -217,7 +229,7 @@ public class Vcn extends Handler {
"Bringing up new VcnGatewayConnection for request " + request.requestId);
final VcnGatewayConnection vcnGatewayConnection =
new VcnGatewayConnection(
mDeps.newVcnGatewayConnection(
mVcnContext,
mSubscriptionGroup,
mLastSnapshot,
@@ -259,5 +271,17 @@ public class Vcn extends Handler {
return 52;
}
private static class Dependencies {}
/** External dependencies used by Vcn, for injection in tests */
@VisibleForTesting(visibility = Visibility.PRIVATE)
public static class Dependencies {
/** Builds a new VcnGatewayConnection */
public VcnGatewayConnection newVcnGatewayConnection(
VcnContext vcnContext,
ParcelUuid subscriptionGroup,
TelephonySubscriptionSnapshot snapshot,
VcnGatewayConnectionConfig connectionConfig) {
return new VcnGatewayConnection(
vcnContext, subscriptionGroup, snapshot, connectionConfig);
}
}
}

View File

@@ -25,6 +25,9 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
import java.util.Objects;
import java.util.Set;
@@ -52,8 +55,13 @@ public class VcnNetworkProvider extends NetworkProvider {
super(context, looper, VcnNetworkProvider.class.getSimpleName());
}
// Package-private
void registerListener(@NonNull NetworkRequestListener listener) {
/**
* Registers a NetworkRequestListener with this NetworkProvider.
*
* <p>Upon registering, the provided listener will receive all cached requests.
*/
@VisibleForTesting(visibility = Visibility.PACKAGE)
public void registerListener(@NonNull NetworkRequestListener listener) {
mListeners.add(listener);
// Send listener all cached requests
@@ -62,8 +70,9 @@ public class VcnNetworkProvider extends NetworkProvider {
}
}
// Package-private
void unregisterListener(@NonNull NetworkRequestListener listener) {
/** Unregisters the specified listener from receiving future NetworkRequests. */
@VisibleForTesting(visibility = Visibility.PACKAGE)
public void unregisterListener(@NonNull NetworkRequestListener listener) {
mListeners.remove(listener);
}

View File

@@ -598,4 +598,16 @@ public class VcnManagementServiceTest {
mVcnMgmtSvc.getUnderlyingNetworkPolicy(new NetworkCapabilities(), new LinkProperties());
}
@Test
public void testSubscriptionSnapshotUpdateNotifiesVcn() {
mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG, TEST_PACKAGE_NAME);
final Map<ParcelUuid, Vcn> vcnInstances = mVcnMgmtSvc.getAllVcns();
final Vcn vcnInstance = vcnInstances.get(TEST_UUID_2);
TelephonySubscriptionSnapshot snapshot =
triggerSubscriptionTrackerCbAndGetSnapshot(Collections.singleton(TEST_UUID_2));
verify(vcnInstance).updateSubscriptionSnapshot(eq(snapshot));
}
}

View File

@@ -66,6 +66,12 @@ public class UnderlyingNetworkTrackerTest {
private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
private static final int INITIAL_SUB_ID_1 = 1;
private static final int INITIAL_SUB_ID_2 = 2;
private static final int UPDATED_SUB_ID = 3;
private static final Set<Integer> INITIAL_SUB_IDS =
new ArraySet<>(Arrays.asList(INITIAL_SUB_ID_1, INITIAL_SUB_ID_2));
private static final Set<Integer> UPDATED_SUB_IDS =
new ArraySet<>(Arrays.asList(UPDATED_SUB_ID));
private static final NetworkCapabilities INITIAL_NETWORK_CAPABILITIES =
new NetworkCapabilities.Builder()
@@ -115,9 +121,7 @@ public class UnderlyingNetworkTrackerTest {
Context.CONNECTIVITY_SERVICE,
ConnectivityManager.class);
Set<Integer> initialSubIds =
new ArraySet<>(Arrays.asList(INITIAL_SUB_ID_1, INITIAL_SUB_ID_2));
when(mSubscriptionSnapshot.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(initialSubIds);
when(mSubscriptionSnapshot.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(INITIAL_SUB_IDS);
mUnderlyingNetworkTracker =
new UnderlyingNetworkTracker(
@@ -148,23 +152,45 @@ public class UnderlyingNetworkTrackerTest {
eq(getWifiRequest()),
any(),
any(NetworkBringupCallback.class));
verify(mConnectivityManager)
.requestBackgroundNetwork(
eq(getCellRequestForSubId(INITIAL_SUB_ID_1)),
any(),
any(NetworkBringupCallback.class));
verify(mConnectivityManager)
.requestBackgroundNetwork(
eq(getCellRequestForSubId(INITIAL_SUB_ID_2)),
any(),
any(NetworkBringupCallback.class));
verifyBackgroundCellRequests(mSubscriptionSnapshot, SUB_GROUP, INITIAL_SUB_IDS);
verify(mConnectivityManager)
.requestBackgroundNetwork(
eq(getRouteSelectionRequest()),
any(),
any(RouteSelectionCallback.class));
}
verify(mSubscriptionSnapshot).getAllSubIdsInGroup(eq(SUB_GROUP));
private void verifyBackgroundCellRequests(
TelephonySubscriptionSnapshot snapshot,
ParcelUuid subGroup,
Set<Integer> expectedSubIds) {
verify(snapshot).getAllSubIdsInGroup(eq(subGroup));
for (final int subId : expectedSubIds) {
verify(mConnectivityManager)
.requestBackgroundNetwork(
eq(getCellRequestForSubId(subId)),
any(),
any(NetworkBringupCallback.class));
}
}
@Test
public void testUpdateSubscriptionSnapshot() {
// Verify initial cell background requests filed
verifyBackgroundCellRequests(mSubscriptionSnapshot, SUB_GROUP, INITIAL_SUB_IDS);
TelephonySubscriptionSnapshot subscriptionUpdate =
mock(TelephonySubscriptionSnapshot.class);
when(subscriptionUpdate.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(UPDATED_SUB_IDS);
mUnderlyingNetworkTracker.updateSubscriptionSnapshot(subscriptionUpdate);
// verify that initially-filed bringup requests are unregistered
verify(mConnectivityManager, times(INITIAL_SUB_IDS.size()))
.unregisterNetworkCallback(any(NetworkBringupCallback.class));
verifyBackgroundCellRequests(subscriptionUpdate, SUB_GROUP, UPDATED_SUB_IDS);
}
private NetworkRequest getWifiRequest() {

View File

@@ -24,10 +24,10 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.annotation.NonNull;
import android.content.Context;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -37,14 +37,15 @@ import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
import android.os.ParcelUuid;
import android.os.Process;
import android.os.test.TestLooper;
import android.telephony.SubscriptionInfo;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -56,8 +57,9 @@ import java.util.UUID;
/** Tests for TelephonySubscriptionTracker */
@RunWith(AndroidJUnit4.class)
@SmallTest
public class VcnGatewayConnectionTest {
public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
private static final int TEST_UID = Process.myUid();
private static final ParcelUuid TEST_PARCEL_UUID = new ParcelUuid(UUID.randomUUID());
private static final int TEST_SIM_SLOT_INDEX = 1;
private static final int TEST_SUBSCRIPTION_ID_1 = 2;
@@ -73,17 +75,12 @@ public class VcnGatewayConnectionTest {
TEST_SUBID_TO_GROUP_MAP = Collections.unmodifiableMap(subIdToGroupMap);
}
@NonNull private final Context mContext;
@NonNull private final TestLooper mTestLooper;
@NonNull private final VcnNetworkProvider mVcnNetworkProvider;
@NonNull private final VcnGatewayConnection.Dependencies mDeps;
@NonNull private final WifiInfo mWifiInfo;
private WifiInfo mWifiInfo;
@Before
public void setUp() throws Exception {
super.setUp();
public VcnGatewayConnectionTest() {
mContext = mock(Context.class);
mTestLooper = new TestLooper();
mVcnNetworkProvider = mock(VcnNetworkProvider.class);
mDeps = mock(VcnGatewayConnection.Dependencies.class);
mWifiInfo = mock(WifiInfo.class);
}
@@ -132,4 +129,13 @@ public class VcnGatewayConnectionTest {
public void testBuildNetworkCapabilitiesUnderlyingCell() throws Exception {
verifyBuildNetworkCapabilitiesCommon(TRANSPORT_CELLULAR);
}
@Test
public void testSubscriptionSnapshotUpdateNotifiesUnderlyingNetworkTracker() {
final TelephonySubscriptionSnapshot updatedSnapshot =
mock(TelephonySubscriptionSnapshot.class);
mGatewayConnection.updateSubscriptionSnapshot(updatedSnapshot);
verify(mUnderlyingNetworkTracker).updateSubscriptionSnapshot(eq(updatedSnapshot));
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.vcn;
import static org.junit.Assert.assertFalse;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.net.NetworkRequest;
import android.net.vcn.VcnConfig;
import android.net.vcn.VcnGatewayConnectionConfigTest;
import android.os.ParcelUuid;
import android.os.test.TestLooper;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.util.Set;
import java.util.UUID;
public class VcnTest {
private static final String PKG_NAME = VcnTest.class.getPackage().getName();
private static final ParcelUuid TEST_SUB_GROUP = new ParcelUuid(new UUID(0, 0));
private static final int NETWORK_SCORE = 0;
private static final int PROVIDER_ID = 5;
private Context mContext;
private VcnContext mVcnContext;
private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
private VcnNetworkProvider mVcnNetworkProvider;
private Vcn.Dependencies mDeps;
private TestLooper mTestLooper;
private VcnConfig mConfig;
private Vcn mVcn;
@Before
public void setUp() {
mContext = mock(Context.class);
mVcnContext = mock(VcnContext.class);
mSubscriptionSnapshot = mock(TelephonySubscriptionSnapshot.class);
mVcnNetworkProvider = mock(VcnNetworkProvider.class);
mDeps = mock(Vcn.Dependencies.class);
mTestLooper = new TestLooper();
doReturn(PKG_NAME).when(mContext).getOpPackageName();
doReturn(mContext).when(mVcnContext).getContext();
doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper();
doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider();
// Setup VcnGatewayConnection instance generation
doAnswer((invocation) -> {
// Mock-within a doAnswer is safe, because it doesn't actually run nested.
return mock(VcnGatewayConnection.class);
}).when(mDeps).newVcnGatewayConnection(any(), any(), any(), any());
mConfig =
new VcnConfig.Builder(mContext)
.addGatewayConnectionConfig(
VcnGatewayConnectionConfigTest.buildTestConfig())
.build();
mVcn = new Vcn(mVcnContext, TEST_SUB_GROUP, mConfig, mSubscriptionSnapshot, mDeps);
}
private NetworkRequestListener verifyAndGetRequestListener() {
ArgumentCaptor<NetworkRequestListener> mNetworkRequestListenerCaptor =
ArgumentCaptor.forClass(NetworkRequestListener.class);
verify(mVcnNetworkProvider).registerListener(mNetworkRequestListenerCaptor.capture());
return mNetworkRequestListenerCaptor.getValue();
}
private NetworkRequest getNetworkRequestWithCapabilities(int[] networkCapabilities) {
final NetworkRequest.Builder builder = new NetworkRequest.Builder();
for (final int netCapability : networkCapabilities) {
builder.addCapability(netCapability);
}
return builder.build();
}
@Test
public void testSubscriptionSnapshotUpdatesVcnGatewayConnections() {
final NetworkRequestListener requestListener = verifyAndGetRequestListener();
requestListener.onNetworkRequested(
getNetworkRequestWithCapabilities(VcnGatewayConnectionConfigTest.EXPOSED_CAPS),
NETWORK_SCORE,
PROVIDER_ID);
mTestLooper.dispatchAll();
final Set<VcnGatewayConnection> gatewayConnections = mVcn.getVcnGatewayConnections();
assertFalse(gatewayConnections.isEmpty());
final TelephonySubscriptionSnapshot updatedSnapshot =
mock(TelephonySubscriptionSnapshot.class);
mVcn.updateSubscriptionSnapshot(updatedSnapshot);
mTestLooper.dispatchAll();
for (final VcnGatewayConnection gateway : gatewayConnections) {
verify(gateway).updateSubscriptionSnapshot(eq(updatedSnapshot));
}
}
}