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

Commit 9500317c authored by Lorenzo Colitti's avatar Lorenzo Colitti
Browse files

Fix the legacy VPN tests that start racoon.

These tests do not actually work, or at least not as designed.
What happens when they are run is that creating/connecting the
VPN throws an exception. The call to legacyRunnerReady.block()
times out after 10 seconds because the condition variable is
never opened, but the doesn't notice the timeout becasue it
doesn't check the return value of block().

There are two reasons for the VPN not coming up.
1. VpnConfig.getIntentForStatusPanel calls into PendingIntent and
   ActivityManager statics, which bypass all the mocks and fail
   with an appops denial. Fix this by making it a dependency.
2. The tests are broken due to the UserManager API changes
   tracked in b/175883995. Fixing by adding a bit of ad-hoc code
   into startLegacyVpn, with a TODO to delete it once the rest of
   the UserManager setup code is fixed.

Fix these and check the return value of block(). This ensures
that if any other breakage is added the test will actually fail.
Also check that the throw route survives all the way to the
LinkProperties sent to the agent.

Bug: 173331190
Test: atest com.android.server.connectivity.VpnTest
Change-Id: Ieb7f33bce283ac5ee562a912df8edb9c930ed2b0
parent 61514b2a
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -277,6 +277,10 @@ public class Vpn {
            return LocalServices.getService(DeviceIdleInternal.class);
        }

        public PendingIntent getIntentForStatusPanel(Context context) {
            return VpnConfig.getIntentForStatusPanel(context);
        }

        public void sendArgumentsToDaemon(
                final String daemon, final LocalSocket socket, final String[] arguments,
                final RetryScheduler retryScheduler) throws IOException, InterruptedException {
@@ -1768,7 +1772,7 @@ public class Vpn {
    private void prepareStatusIntent() {
        final long token = Binder.clearCallingIdentity();
        try {
            mStatusIntent = VpnConfig.getIntentForStatusPanel(mContext);
            mStatusIntent = mDeps.getIntentForStatusPanel(mContext);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
+32 −12
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -119,6 +120,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@@ -213,6 +215,8 @@ public class VpnTest {

        when(mContext.getPackageName()).thenReturn(TEST_VPN_PKG);
        when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG);
        when(mContext.getSystemServiceName(UserManager.class))
                .thenReturn(Context.USER_SERVICE);
        when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
        when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
        when(mContext.getSystemServiceName(NotificationManager.class))
@@ -954,7 +958,14 @@ public class VpnTest {
    }

    private Vpn startLegacyVpn(final Vpn vpn, final VpnProfile vpnProfile) throws Exception {
        setMockedUsers(primaryUser);
        // TODO(b/175883995): once these tests have been updated for the changes to the UserManager
        // API, remove this ad-hoc setup code and use setMockedUsers(primaryUser) again.
        // setMockedUsers(primaryUser);
        final ArrayList<UserInfo> users = new ArrayList<>();
        users.add(primaryUser);
        when(mUserManager.getAliveUsers()).thenReturn(users);
        when(mUserManager.getUserInfo(primaryUser.id)).thenReturn(primaryUser);
        when(mUserManager.canHaveRestrictedProfile()).thenReturn(false);

        // Dummy egress interface
        final LinkProperties lp = new LinkProperties();
@@ -997,14 +1008,12 @@ public class VpnTest {
        profile.ipsecIdentifier = "id";
        profile.ipsecSecret = "secret";
        profile.l2tpSecret = "l2tpsecret";

        when(mConnectivityManager.getAllNetworks())
            .thenReturn(new Network[] { new Network(101) });

        when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(),
                anyInt(), any(), anyInt())).thenAnswer(invocation -> {
                    // The runner has registered an agent and is now ready.
                    legacyRunnerReady.open();
                    return new Network(102);
                });
                anyInt(), any(), anyInt())).thenReturn(new Network(102));
        final Vpn vpn = startLegacyVpn(createVpn(primaryUser.id), profile);
        final TestDeps deps = (TestDeps) vpn.mDeps;
        try {
@@ -1020,14 +1029,20 @@ public class VpnTest {
                            "linkname", "vpn", "refuse-eap", "nodefaultroute", "usepeerdns",
                            "idle", "1800", "mtu", "1270", "mru", "1270" },
                    deps.mtpdArgs.get(10, TimeUnit.SECONDS));

            // Now wait for the runner to be ready before testing for the route.
            legacyRunnerReady.block(10_000);
            // In this test the expected address is always v4 so /32
            ArgumentCaptor<LinkProperties> lpCaptor = ArgumentCaptor.forClass(LinkProperties.class);
            verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
                    lpCaptor.capture(), any(), anyInt(), any(), anyInt());

            // In this test the expected address is always v4 so /32.
            // Note that the interface needs to be specified because RouteInfo objects stored in
            // LinkProperties objects always acquire the LinkProperties' interface.
            final RouteInfo expectedRoute = new RouteInfo(new IpPrefix(expectedAddr + "/32"),
                    RouteInfo.RTN_THROW);
            assertTrue("Routes lack the expected throw route (" + expectedRoute + ") : "
                    + vpn.mConfig.routes,
                    vpn.mConfig.routes.contains(expectedRoute));
                    null, EGRESS_IFACE, RouteInfo.RTN_THROW);
            final List<RouteInfo> actualRoutes = lpCaptor.getValue().getRoutes();
            assertTrue("Expected throw route (" + expectedRoute + ") not found in " + actualRoutes,
                    actualRoutes.contains(expectedRoute));
        } finally {
            // Now interrupt the thread, unblock the runner and clean up.
            vpn.mVpnRunner.exitVpnRunner();
@@ -1082,6 +1097,11 @@ public class VpnTest {
            return mStateFile;
        }

        @Override
        public PendingIntent getIntentForStatusPanel(Context context) {
            return null;
        }

        @Override
        public void sendArgumentsToDaemon(
                final String daemon, final LocalSocket socket, final String[] arguments,