Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7087a4ac authored by Benedict Wong's avatar Benedict Wong
Browse files

Create proxy NetworkAgent for testing

This change adds a proxy NetworkAgent to facilitate testing, adding the
ability to test final methods such as sendNetworkCapabilities() and
sendLinkProperties(), which would otherwise call a real implementation,
and throw a null pointer while trying to access internal fields.

Bug: 184579891
Bug: 184697651
Test: atest FrameworksVcnTests
Change-Id: I8f13159bd266bf488f095a13d6ffe444bec65f38
parent a4f28eda
Loading
Loading
Loading
Loading
+83 −23
Original line number Diff line number Diff line
@@ -575,7 +575,7 @@ public class VcnGatewayConnection extends StateMachine {
     * <p>Set in Connected state, always @NonNull in Connected, Migrating states, @Nullable
     * otherwise.
     */
    private NetworkAgent mNetworkAgent;
    private VcnNetworkAgent mNetworkAgent;

    @Nullable private WakeupMessage mTeardownTimeoutAlarm;
    @Nullable private WakeupMessage mDisconnectRequestAlarm;
@@ -1441,7 +1441,7 @@ public class VcnGatewayConnection extends StateMachine {
    private abstract class ConnectedStateBase extends ActiveBaseState {
        protected void updateNetworkAgent(
                @NonNull IpSecTunnelInterface tunnelIface,
                @NonNull NetworkAgent agent,
                @NonNull VcnNetworkAgent agent,
                @NonNull VcnChildSessionConfiguration childConfig) {
            final NetworkCapabilities caps =
                    buildNetworkCapabilities(mConnectionConfig, mUnderlying);
@@ -1452,7 +1452,7 @@ public class VcnGatewayConnection extends StateMachine {
            agent.sendLinkProperties(lp);
        }

        protected NetworkAgent buildNetworkAgent(
        protected VcnNetworkAgent buildNetworkAgent(
                @NonNull IpSecTunnelInterface tunnelIface,
                @NonNull VcnChildSessionConfiguration childConfig) {
            final NetworkCapabilities caps =
@@ -1464,7 +1464,7 @@ public class VcnGatewayConnection extends StateMachine {
                            .setLegacyType(ConnectivityManager.TYPE_MOBILE)
                            .build();

            final NetworkAgent agent =
            final VcnNetworkAgent agent =
                    mDeps.newNetworkAgent(
                            mVcnContext,
                            TAG,
@@ -1993,12 +1993,12 @@ public class VcnGatewayConnection extends StateMachine {
    }

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    NetworkAgent getNetworkAgent() {
    VcnNetworkAgent getNetworkAgent() {
        return mNetworkAgent;
    }

    @VisibleForTesting(visibility = Visibility.PRIVATE)
    void setNetworkAgent(@Nullable NetworkAgent networkAgent) {
    void setNetworkAgent(@Nullable VcnNetworkAgent networkAgent) {
        mNetworkAgent = networkAgent;
    }

@@ -2086,8 +2086,8 @@ public class VcnGatewayConnection extends StateMachine {
            return new WakeupMessage(vcnContext.getContext(), handler, tag, runnable);
        }

        /** Builds a new NetworkAgent. */
        public NetworkAgent newNetworkAgent(
        /** Builds a new VcnNetworkAgent. */
        public VcnNetworkAgent newNetworkAgent(
                @NonNull VcnContext vcnContext,
                @NonNull String tag,
                @NonNull NetworkCapabilities caps,
@@ -2095,27 +2095,18 @@ public class VcnGatewayConnection extends StateMachine {
                @NonNull int score,
                @NonNull NetworkAgentConfig nac,
                @NonNull NetworkProvider provider,
                @NonNull Consumer<NetworkAgent> networkUnwantedCallback,
                @NonNull Consumer<VcnNetworkAgent> networkUnwantedCallback,
                @NonNull Consumer<Integer> validationStatusCallback) {
            return new NetworkAgent(
                    vcnContext.getContext(),
                    vcnContext.getLooper(),
            return new VcnNetworkAgent(
                    vcnContext,
                    tag,
                    caps,
                    lp,
                    score,
                    nac,
                    provider) {
                @Override
                public void onNetworkUnwanted() {
                    networkUnwantedCallback.accept(this);
                }

                @Override
                public void onValidationStatus(int status, @Nullable Uri redirectUri) {
                    validationStatusCallback.accept(status);
                }
            };
                    provider,
                    networkUnwantedCallback,
                    validationStatusCallback);
        }

        /** Gets the elapsed real time since boot, in millis. */
@@ -2231,4 +2222,73 @@ public class VcnGatewayConnection extends StateMachine {
            mImpl.release();
        }
    }

    /** Proxy Implementation of NetworkAgent, used for testing. */
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    public static class VcnNetworkAgent {
        private final NetworkAgent mImpl;

        public VcnNetworkAgent(
                @NonNull VcnContext vcnContext,
                @NonNull String tag,
                @NonNull NetworkCapabilities caps,
                @NonNull LinkProperties lp,
                @NonNull int score,
                @NonNull NetworkAgentConfig nac,
                @NonNull NetworkProvider provider,
                @NonNull Consumer<VcnNetworkAgent> networkUnwantedCallback,
                @NonNull Consumer<Integer> validationStatusCallback) {
            mImpl =
                    new NetworkAgent(
                            vcnContext.getContext(),
                            vcnContext.getLooper(),
                            tag,
                            caps,
                            lp,
                            score,
                            nac,
                            provider) {
                        @Override
                        public void onNetworkUnwanted() {
                            networkUnwantedCallback.accept(VcnNetworkAgent.this);
                        }

                        @Override
                        public void onValidationStatus(int status, @Nullable Uri redirectUri) {
                            validationStatusCallback.accept(status);
                        }
                    };
        }

        /** Registers the underlying NetworkAgent */
        public void register() {
            mImpl.register();
        }

        /** Marks the underlying NetworkAgent as connected */
        public void markConnected() {
            mImpl.markConnected();
        }

        /** Unregisters the underlying NetworkAgent */
        public void unregister() {
            mImpl.unregister();
        }

        /** Sends new NetworkCapabilities for the underlying NetworkAgent */
        public void sendNetworkCapabilities(@NonNull NetworkCapabilities caps) {
            mImpl.sendNetworkCapabilities(caps);
        }

        /** Sends new LinkProperties for the underlying NetworkAgent */
        public void sendLinkProperties(@NonNull LinkProperties lp) {
            mImpl.sendLinkProperties(lp);
        }

        /** Retrieves the Network for the underlying NetworkAgent */
        @Nullable
        public Network getNetwork() {
            return mImpl.getNetwork();
        }
    }
}
+12 −10
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;

import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -73,13 +74,13 @@ import java.util.function.Consumer;
@SmallTest
public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnectionTestBase {
    private VcnIkeSession mIkeSession;
    private NetworkAgent mNetworkAgent;
    private VcnNetworkAgent mNetworkAgent;

    @Before
    public void setUp() throws Exception {
        super.setUp();

        mNetworkAgent = mock(NetworkAgent.class);
        mNetworkAgent = mock(VcnNetworkAgent.class);
        doReturn(mNetworkAgent)
                .when(mDeps)
                .newNetworkAgent(any(), any(), any(), any(), anyInt(), any(), any(), any(), any());
@@ -299,8 +300,9 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
                .removeAddressFromTunnelInterface(
                        eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(TEST_INTERNAL_ADDR), any());

        // TODO(b/184579891): Also verify link properties updated and sent when sendLinkProperties
        // is mockable
        verify(mNetworkAgent).sendLinkProperties(argThat(
                lp -> newInternalAddrs.equals(lp.getLinkAddresses())
                        && Collections.singletonList(TEST_DNS_ADDR_2).equals(lp.getDnsServers())));

        // Verify that IpSecTunnelInterface only created once
        verify(mIpSecSvc).createTunnelInterface(any(), any(), any(), any(), any());
@@ -323,11 +325,11 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
        assertFalse(mGatewayConnection.isInSafeMode());
    }

    private Consumer<NetworkAgent> setupNetworkAndGetUnwantedCallback() {
    private Consumer<VcnNetworkAgent> setupNetworkAndGetUnwantedCallback() {
        triggerChildOpened();
        mTestLooper.dispatchAll();

        final ArgumentCaptor<Consumer<NetworkAgent>> unwantedCallbackCaptor =
        final ArgumentCaptor<Consumer<VcnNetworkAgent>> unwantedCallbackCaptor =
                ArgumentCaptor.forClass(Consumer.class);
        verify(mDeps)
                .newNetworkAgent(
@@ -346,7 +348,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection

    @Test
    public void testUnwantedNetworkAgentTriggersTeardown() throws Exception {
        final Consumer<NetworkAgent> unwantedCallback = setupNetworkAndGetUnwantedCallback();
        final Consumer<VcnNetworkAgent> unwantedCallback = setupNetworkAndGetUnwantedCallback();

        unwantedCallback.accept(mNetworkAgent);
        mTestLooper.dispatchAll();
@@ -357,7 +359,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection

    @Test
    public void testUnwantedNetworkAgentWithDisconnectedNetworkAgent() throws Exception {
        final Consumer<NetworkAgent> unwantedCallback = setupNetworkAndGetUnwantedCallback();
        final Consumer<VcnNetworkAgent> unwantedCallback = setupNetworkAndGetUnwantedCallback();

        mGatewayConnection.setNetworkAgent(null);
        unwantedCallback.accept(mNetworkAgent);
@@ -371,8 +373,8 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection

    @Test
    public void testUnwantedNetworkAgentWithNewNetworkAgent() throws Exception {
        final Consumer<NetworkAgent> unwantedCallback = setupNetworkAndGetUnwantedCallback();
        final NetworkAgent testAgent = mock(NetworkAgent.class);
        final Consumer<VcnNetworkAgent> unwantedCallback = setupNetworkAndGetUnwantedCallback();
        final VcnNetworkAgent testAgent = mock(VcnNetworkAgent.class);

        mGatewayConnection.setNetworkAgent(testAgent);
        unwantedCallback.accept(mNetworkAgent);
+3 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.vcn;

import static com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;

import static org.junit.Assert.assertEquals;
@@ -44,7 +45,6 @@ import android.net.IpSecTunnelInterfaceResponse;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.ipsec.ike.ChildSessionCallback;
import android.net.ipsec.ike.IkeSessionCallback;
@@ -278,8 +278,8 @@ public class VcnGatewayConnectionTestBase {

    protected void verifySafeModeTimeoutNotifiesCallbackAndUnregistersNetworkAgent(
            @NonNull State expectedState) {
        // Set a NetworkAgent, and expect it to be unregistered and cleared
        final NetworkAgent mockNetworkAgent = mock(NetworkAgent.class);
        // Set a VcnNetworkAgent, and expect it to be unregistered and cleared
        final VcnNetworkAgent mockNetworkAgent = mock(VcnNetworkAgent.class);
        mGatewayConnection.setNetworkAgent(mockNetworkAgent);

        // SafeMode timer starts when VcnGatewayConnection exits DisconnectedState (the initial