From d4e7b00b2b78bdbca4e3859c186f47f651908186 Mon Sep 17 00:00:00 2001 From: lucaslin Date: Fri, 15 Oct 2021 13:23:46 +0800 Subject: [PATCH] Add tests for testing if [start|finish]Op is called or not Add a test for testing if [start|finish]Op will be called when [start|stop]VpnProfile is called. Also add a test to ensure that the startOp will not be called again when seamless handover is happened. Bug: 197135981 Test: atest FrameworksNetTests:VpnTest Change-Id: I778ea4edf7c4a2d20b3b8e1877e7942feac5372a --- .../android/server/connectivity/VpnTest.java | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/tests/unit/java/com/android/server/connectivity/VpnTest.java b/tests/unit/java/com/android/server/connectivity/VpnTest.java index b706090635..fd9aefa395 100644 --- a/tests/unit/java/com/android/server/connectivity/VpnTest.java +++ b/tests/unit/java/com/android/server/connectivity/VpnTest.java @@ -16,6 +16,7 @@ package com.android.server.connectivity; +import static android.Manifest.permission.BIND_VPN_SERVICE; import static android.content.pm.UserInfo.FLAG_ADMIN; import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; import static android.content.pm.UserInfo.FLAG_PRIMARY; @@ -31,12 +32,14 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.after; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doCallRealMethod; @@ -70,6 +73,7 @@ import android.net.InterfaceConfigurationParcel; import android.net.IpPrefix; import android.net.IpSecManager; import android.net.IpSecTunnelInterfaceResponse; +import android.net.LinkAddress; import android.net.LinkProperties; import android.net.LocalSocket; import android.net.Network; @@ -86,6 +90,7 @@ import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.ConditionVariable; import android.os.INetworkManagementService; +import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.UserHandle; import android.os.UserManager; @@ -102,6 +107,7 @@ import com.android.internal.R; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; import com.android.internal.net.VpnProfile; +import com.android.modules.utils.build.SdkLevel; import com.android.server.IpSecService; import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRunner; @@ -118,6 +124,7 @@ import org.mockito.MockitoAnnotations; import java.io.BufferedWriter; import java.io.File; +import java.io.FileDescriptor; import java.io.FileWriter; import java.io.IOException; import java.net.Inet4Address; @@ -850,6 +857,81 @@ public class VpnTest { } } + @Test + public void testStartOpAndFinishOpWillBeCalledWhenPlatformVpnIsOnAndOff() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN); + when(mVpnProfileStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG))) + .thenReturn(mVpnProfile.encode()); + vpn.startVpnProfile(TEST_VPN_PKG); + verify(mAppOps).noteOpNoThrow( + eq(AppOpsManager.OPSTR_ACTIVATE_PLATFORM_VPN), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(null) /* attributionTag */, + eq(null) /* message */); + verify(mAppOps).startOp( + eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(null) /* attributionTag */, + eq(null) /* message */); + // Add a small delay to make sure that startOp is only called once. + verify(mAppOps, after(100).times(1)).startOp( + eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(null) /* attributionTag */, + eq(null) /* message */); + // Check that the startOp is not called with OPSTR_ESTABLISH_VPN_SERVICE. + verify(mAppOps, never()).startOp( + eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(null) /* attributionTag */, + eq(null) /* message */); + vpn.stopVpnProfile(TEST_VPN_PKG); + // Add a small delay to double confirm that startOp is only called once. + verify(mAppOps, after(100)).finishOp( + eq(AppOpsManager.OPSTR_ESTABLISH_VPN_MANAGER), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(null) /* attributionTag */); + } + + @Test + public void testStartOpWithSeamlessHandover() throws Exception { + assumeTrue(SdkLevel.isAtLeastT()); + final Vpn vpn = createVpnAndSetupUidChecks(AppOpsManager.OPSTR_ACTIVATE_VPN); + assertTrue(vpn.prepare(TEST_VPN_PKG, null, VpnManager.TYPE_VPN_SERVICE)); + final VpnConfig config = new VpnConfig(); + config.user = "VpnTest"; + config.addresses.add(new LinkAddress("192.0.2.2/32")); + config.mtu = 1450; + final ResolveInfo resolveInfo = new ResolveInfo(); + final ServiceInfo serviceInfo = new ServiceInfo(); + serviceInfo.permission = BIND_VPN_SERVICE; + resolveInfo.serviceInfo = serviceInfo; + when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo); + when(mContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true); + vpn.establish(config); + verify(mAppOps, times(1)).startOp( + eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(null) /* attributionTag */, + eq(null) /* message */); + // Call establish() twice with the same config, it should match seamless handover case and + // startOp() shouldn't be called again. + vpn.establish(config); + verify(mAppOps, times(1)).startOp( + eq(AppOpsManager.OPSTR_ESTABLISH_VPN_SERVICE), + eq(Process.myUid()), + eq(TEST_VPN_PKG), + eq(null) /* attributionTag */, + eq(null) /* message */); + } + @Test public void testSetPackageAuthorizationVpnService() throws Exception { final Vpn vpn = createVpnAndSetupUidChecks(); @@ -1197,6 +1279,32 @@ public class VpnTest { public boolean isInterfacePresent(final Vpn vpn, final String iface) { return true; } + + @Override + public ParcelFileDescriptor adoptFd(Vpn vpn, int mtu) { + return new ParcelFileDescriptor(new FileDescriptor()); + } + + @Override + public int jniCreate(Vpn vpn, int mtu) { + // Pick a random positive number as fd to return. + return 345; + } + + @Override + public String jniGetName(Vpn vpn, int fd) { + return TEST_IFACE_NAME; + } + + @Override + public int jniSetAddresses(Vpn vpn, String interfaze, String addresses) { + if (addresses == null) return 0; + // Return the number of addresses. + return addresses.split(" ").length; + } + + @Override + public void setBlocking(FileDescriptor fd, boolean blocking) {} } /**