diff options
| author | 2021-01-20 20:32:02 -0800 | |
|---|---|---|
| committer | 2021-02-05 15:11:38 -0800 | |
| commit | 2ef953a9a1ee0c824f128928bd1ca90601237f02 (patch) | |
| tree | a80d51edb87ff3c5fad939381e8ac54ce6602403 | |
| parent | 3996801c602ab28acb8d85444d3582827d19b236 (diff) | |
Test Network startup in ConnectedState
Add additional tests based on proxy implementations of
ChildSessionCallback and ChildSessionConfiguration
Bug: 165827287
Test: atest FrameworksVcnTests
Change-Id: I165716a0212da7c06b9723656ffe35921cf81854
3 files changed, 129 insertions, 20 deletions
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java index 9ecdf1b48789..4d5cf4ff750a 100644 --- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java +++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java @@ -75,6 +75,7 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -297,9 +298,9 @@ public class VcnGatewayConnection extends StateMachine { private static final int EVENT_SETUP_COMPLETED = 6; private static class EventSetupCompletedInfo implements EventInfo { - @NonNull public final ChildSessionConfiguration childSessionConfig; + @NonNull public final VcnChildSessionConfiguration childSessionConfig; - EventSetupCompletedInfo(@NonNull ChildSessionConfiguration childSessionConfig) { + EventSetupCompletedInfo(@NonNull VcnChildSessionConfiguration childSessionConfig) { this.childSessionConfig = Objects.requireNonNull(childSessionConfig); } @@ -471,7 +472,7 @@ public class VcnGatewayConnection extends StateMachine { * <p>Set in Connected and Migrating states, always @NonNull in Connected, Migrating * states, @Nullable otherwise. */ - private ChildSessionConfiguration mChildConfig; + private VcnChildSessionConfiguration mChildConfig; /** * The active network agent. @@ -659,7 +660,7 @@ public class VcnGatewayConnection extends StateMachine { new EventTransformCreatedInfo(direction, transform)); } - private void childOpened(int token, @NonNull ChildSessionConfiguration childConfig) { + private void childOpened(int token, @NonNull VcnChildSessionConfiguration childConfig) { sendMessage(EVENT_SETUP_COMPLETED, token, new EventSetupCompletedInfo(childConfig)); } @@ -1008,7 +1009,7 @@ public class VcnGatewayConnection extends StateMachine { protected void updateNetworkAgent( @NonNull IpSecTunnelInterface tunnelIface, @NonNull NetworkAgent agent, - @NonNull ChildSessionConfiguration childConfig) { + @NonNull VcnChildSessionConfiguration childConfig) { final NetworkCapabilities caps = buildNetworkCapabilities(mConnectionConfig, mUnderlying); final LinkProperties lp = @@ -1020,7 +1021,7 @@ public class VcnGatewayConnection extends StateMachine { protected NetworkAgent buildNetworkAgent( @NonNull IpSecTunnelInterface tunnelIface, - @NonNull ChildSessionConfiguration childConfig) { + @NonNull VcnChildSessionConfiguration childConfig) { final NetworkCapabilities caps = buildNetworkCapabilities(mConnectionConfig, mUnderlying); final LinkProperties lp = @@ -1068,15 +1069,15 @@ public class VcnGatewayConnection extends StateMachine { protected void setupInterface( int token, @NonNull IpSecTunnelInterface tunnelIface, - @NonNull ChildSessionConfiguration childConfig) { + @NonNull VcnChildSessionConfiguration childConfig) { setupInterface(token, tunnelIface, childConfig, null); } protected void setupInterface( int token, @NonNull IpSecTunnelInterface tunnelIface, - @NonNull ChildSessionConfiguration childConfig, - @Nullable ChildSessionConfiguration oldChildConfig) { + @NonNull VcnChildSessionConfiguration childConfig, + @Nullable VcnChildSessionConfiguration oldChildConfig) { try { final Set<LinkAddress> newAddrs = new ArraySet<>(childConfig.getInternalAddresses()); @@ -1189,7 +1190,7 @@ public class VcnGatewayConnection extends StateMachine { protected void setupInterfaceAndNetworkAgent( int token, @NonNull IpSecTunnelInterface tunnelIface, - @NonNull ChildSessionConfiguration childConfig) { + @NonNull VcnChildSessionConfiguration childConfig) { setupInterface(token, tunnelIface, childConfig); if (mNetworkAgent == null) { @@ -1277,7 +1278,7 @@ public class VcnGatewayConnection extends StateMachine { private static LinkProperties buildConnectedLinkProperties( @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig, @NonNull IpSecTunnelInterface tunnelIface, - @NonNull ChildSessionConfiguration childConfig) { + @NonNull VcnChildSessionConfiguration childConfig) { final LinkProperties lp = new LinkProperties(); lp.setInterfaceName(tunnelIface.getInterfaceName()); @@ -1328,20 +1329,28 @@ public class VcnGatewayConnection extends StateMachine { } } - private class ChildSessionCallbackImpl implements ChildSessionCallback { + /** Implementation of ChildSessionCallback, exposed for testing. */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + public class VcnChildSessionCallback implements ChildSessionCallback { private final int mToken; - ChildSessionCallbackImpl(int token) { + VcnChildSessionCallback(int token) { mToken = token; } - @Override - public void onOpened(@NonNull ChildSessionConfiguration childConfig) { + /** Internal proxy method for injecting of mocked ChildSessionConfiguration */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + void onOpened(@NonNull VcnChildSessionConfiguration childConfig) { Slog.v(TAG, "ChildOpened for token " + mToken); childOpened(mToken, childConfig); } @Override + public void onOpened(@NonNull ChildSessionConfiguration childConfig) { + onOpened(new VcnChildSessionConfiguration(childConfig)); + } + + @Override public void onClosed() { Slog.v(TAG, "ChildClosed for token " + mToken); sessionLost(mToken, null); @@ -1421,7 +1430,7 @@ public class VcnGatewayConnection extends StateMachine { buildIkeParams(), buildChildParams(), new IkeSessionCallbackImpl(token), - new ChildSessionCallbackImpl(token)); + new VcnChildSessionCallback(token)); } /** External dependencies used by VcnGatewayConnection, for injection in tests */ @@ -1458,6 +1467,35 @@ public class VcnGatewayConnection extends StateMachine { } } + /** + * Proxy implementation of Child Session Configuration, used for testing. + * + * <p>This wrapper allows mocking of the final, parcelable ChildSessionConfiguration object for + * testing purposes. This is the unfortunate result of mockito-inline (for mocking final + * classes) not working properly with system services & associated classes. + * + * <p>This class MUST EXCLUSIVELY be a passthrough, proxying calls directly to the actual + * ChildSessionConfiguration. + */ + @VisibleForTesting(visibility = Visibility.PRIVATE) + public static class VcnChildSessionConfiguration { + private final ChildSessionConfiguration mChildConfig; + + public VcnChildSessionConfiguration(ChildSessionConfiguration childConfig) { + mChildConfig = childConfig; + } + + /** Retrieves the addresses to be used inside the tunnel. */ + public List<LinkAddress> getInternalAddresses() { + return mChildConfig.getInternalAddresses(); + } + + /** Retrieves the DNS servers to be used inside the tunnel. */ + public List<InetAddress> getInternalDnsServers() { + return mChildConfig.getInternalDnsServers(); + } + } + /** Proxy implementation of IKE session, used for testing. */ @VisibleForTesting(visibility = Visibility.PRIVATE) public static class VcnIkeSession { diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java index e20070ee4f07..278d93a1b17b 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java @@ -18,22 +18,35 @@ package com.android.server.vcn; import static android.net.IpSecManager.DIRECTION_IN; import static android.net.IpSecManager.DIRECTION_OUT; +import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR; +import static android.net.NetworkCapabilities.TRANSPORT_WIFI; +import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration; import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import android.net.LinkProperties; +import android.net.NetworkCapabilities; + import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; + +import java.util.Collections; /** Tests for VcnGatewayConnection.ConnectedState */ @RunWith(AndroidJUnit4.class) @@ -107,6 +120,51 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection } @Test + public void testChildOpenedRegistersNetwork() throws Exception { + final VcnChildSessionConfiguration mMockChildSessionConfig = + mock(VcnChildSessionConfiguration.class); + doReturn(Collections.singletonList(TEST_INTERNAL_ADDR)) + .when(mMockChildSessionConfig) + .getInternalAddresses(); + doReturn(Collections.singletonList(TEST_DNS_ADDR)) + .when(mMockChildSessionConfig) + .getInternalDnsServers(); + + getChildSessionCallback().onOpened(mMockChildSessionConfig); + mTestLooper.dispatchAll(); + + assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState()); + + final ArgumentCaptor<LinkProperties> lpCaptor = + ArgumentCaptor.forClass(LinkProperties.class); + final ArgumentCaptor<NetworkCapabilities> ncCaptor = + ArgumentCaptor.forClass(NetworkCapabilities.class); + verify(mConnMgr) + .registerNetworkAgent( + any(), + any(), + lpCaptor.capture(), + ncCaptor.capture(), + anyInt(), + any(), + anyInt()); + verify(mIpSecSvc) + .addAddressToTunnelInterface( + eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(TEST_INTERNAL_ADDR), any()); + + final LinkProperties lp = lpCaptor.getValue(); + assertEquals(Collections.singletonList(TEST_INTERNAL_ADDR), lp.getLinkAddresses()); + assertEquals(Collections.singletonList(TEST_DNS_ADDR), lp.getDnsServers()); + + final NetworkCapabilities nc = ncCaptor.getValue(); + assertTrue(nc.hasTransport(TRANSPORT_CELLULAR)); + assertFalse(nc.hasTransport(TRANSPORT_WIFI)); + for (int cap : mConfig.getAllExposedCapabilities()) { + assertTrue(nc.hasCapability(cap)); + } + } + + @Test public void testChildSessionClosedTriggersDisconnect() throws Exception { getChildSessionCallback().onClosed(); mTestLooper.dispatchAll(); @@ -122,6 +180,4 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection assertEquals(mGatewayConnection.mRetryTimeoutState, mGatewayConnection.getCurrentState()); verify(mIkeSession).close(); } - - // TODO: Add tests for childOpened() when ChildSessionConfiguration can be mocked or created } diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java index 333b5b990dde..d449eab494f6 100644 --- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java +++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java @@ -27,10 +27,13 @@ import static org.mockito.Mockito.verify; import android.annotation.NonNull; import android.content.Context; +import android.net.ConnectivityManager; +import android.net.InetAddresses; import android.net.IpSecConfig; import android.net.IpSecManager; import android.net.IpSecTransform; import android.net.IpSecTunnelInterfaceResponse; +import android.net.LinkAddress; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; @@ -44,15 +47,22 @@ import android.os.test.TestLooper; import com.android.server.IpSecService; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.Vcn.VcnGatewayStatusCallback; +import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback; import org.junit.Before; import org.mockito.ArgumentCaptor; +import java.net.InetAddress; import java.util.Collections; import java.util.UUID; public class VcnGatewayConnectionTestBase { protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID()); + protected static final InetAddress TEST_DNS_ADDR = + InetAddresses.parseNumericAddress("2001:DB8:0:1::"); + protected static final LinkAddress TEST_INTERNAL_ADDR = + new LinkAddress(InetAddresses.parseNumericAddress("2001:DB8:0:2::"), 64); + protected static final int TEST_IPSEC_SPI_VALUE = 0x1234; protected static final int TEST_IPSEC_SPI_RESOURCE_ID = 1; protected static final int TEST_IPSEC_TRANSFORM_RESOURCE_ID = 2; @@ -86,6 +96,7 @@ public class VcnGatewayConnectionTestBase { @NonNull protected final UnderlyingNetworkTracker mUnderlyingNetworkTracker; @NonNull protected final IpSecService mIpSecSvc; + @NonNull protected final ConnectivityManager mConnMgr; protected VcnIkeSession mMockIkeSession; protected VcnGatewayConnection mGatewayConnection; @@ -103,6 +114,10 @@ public class VcnGatewayConnectionTestBase { mIpSecSvc = mock(IpSecService.class); setupIpSecManager(mContext, mIpSecSvc); + mConnMgr = mock(ConnectivityManager.class); + VcnTestUtils.setupSystemService( + mContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class); + doReturn(mContext).when(mVcnContext).getContext(); doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper(); doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider(); @@ -145,10 +160,10 @@ public class VcnGatewayConnectionTestBase { return captor.getValue(); } - protected ChildSessionCallback getChildSessionCallback() { + protected VcnChildSessionCallback getChildSessionCallback() { ArgumentCaptor<ChildSessionCallback> captor = ArgumentCaptor.forClass(ChildSessionCallback.class); verify(mDeps).newIkeSession(any(), any(), any(), any(), captor.capture()); - return captor.getValue(); + return (VcnChildSessionCallback) captor.getValue(); } } |