diff --git a/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java b/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java index c6d8d65bb4..6e9f0cd250 100644 --- a/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java +++ b/tests/cts/net/src/android/net/cts/Ikev2VpnTest.java @@ -39,13 +39,11 @@ import android.content.Intent; import android.net.ConnectivityManager; import android.net.Ikev2VpnProfile; import android.net.IpSecAlgorithm; -import android.net.LinkAddress; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.ProxyInfo; import android.net.TestNetworkInterface; -import android.net.TestNetworkManager; import android.net.VpnManager; import android.net.cts.util.CtsNetUtils; import android.os.Build; @@ -439,41 +437,37 @@ public class Ikev2VpnTest { assertEquals(vpnNetwork, cb.lastLostNetwork); } - private void doTestStartStopVpnProfile(boolean testIpv6) throws Exception { - // Non-final; these variables ensure we clean up properly after our test if we have - // allocated test network resources - final TestNetworkManager tnm = sContext.getSystemService(TestNetworkManager.class); - TestNetworkInterface testIface = null; - TestNetworkCallback tunNetworkCallback = null; + private class VerifyStartStopVpnProfileTest implements TestNetworkRunnable.Test { + private final boolean mTestIpv6Only; - try { - // Build underlying test network - testIface = tnm.createTunInterface( - new LinkAddress[] { - new LinkAddress(LOCAL_OUTER_4, IP4_PREFIX_LEN), - new LinkAddress(LOCAL_OUTER_6, IP6_PREFIX_LEN)}); + /** + * Constructs the test + * + * @param testIpv6Only if true, builds a IPv6-only test; otherwise builds a IPv4-only test + */ + VerifyStartStopVpnProfileTest(boolean testIpv6Only) { + mTestIpv6Only = testIpv6Only; + } - // Hold on to this callback to ensure network does not get reaped. - tunNetworkCallback = mCtsNetUtils.setupAndGetTestNetwork( - testIface.getInterfaceName()); + @Override + public void runTest(TestNetworkInterface testIface, TestNetworkCallback tunNetworkCallback) + throws Exception { final IkeTunUtils tunUtils = new IkeTunUtils(testIface.getFileDescriptor()); - checkStartStopVpnProfileBuildsNetworks(tunUtils, testIpv6); - } finally { - // Make sure to stop the VPN profile. This is safe to call multiple times. + checkStartStopVpnProfileBuildsNetworks(tunUtils, mTestIpv6Only); + } + + @Override + public void cleanupTest() { sVpnMgr.stopProvisionedVpnProfile(); + } - if (testIface != null) { - testIface.getFileDescriptor().close(); - } - - if (tunNetworkCallback != null) { - sCM.unregisterNetworkCallback(tunNetworkCallback); - } - - final Network testNetwork = tunNetworkCallback.currentNetwork; - if (testNetwork != null) { - tnm.teardownTestNetwork(testNetwork); + @Override + public InetAddress[] getTestNetworkAddresses() { + if (mTestIpv6Only) { + return new InetAddress[] {LOCAL_OUTER_6}; + } else { + return new InetAddress[] {LOCAL_OUTER_4}; } } } @@ -483,9 +477,8 @@ public class Ikev2VpnTest { assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); // Requires shell permission to update appops. - runWithShellPermissionIdentity(() -> { - doTestStartStopVpnProfile(false); - }); + runWithShellPermissionIdentity( + new TestNetworkRunnable(new VerifyStartStopVpnProfileTest(false))); } @Test @@ -493,9 +486,8 @@ public class Ikev2VpnTest { assumeTrue(mCtsNetUtils.hasIpsecTunnelsFeature()); // Requires shell permission to update appops. - runWithShellPermissionIdentity(() -> { - doTestStartStopVpnProfile(true); - }); + runWithShellPermissionIdentity( + new TestNetworkRunnable(new VerifyStartStopVpnProfileTest(true))); } private static class CertificateAndKey { diff --git a/tests/cts/net/src/android/net/cts/TestNetworkRunnable.java b/tests/cts/net/src/android/net/cts/TestNetworkRunnable.java new file mode 100644 index 0000000000..0eb564494d --- /dev/null +++ b/tests/cts/net/src/android/net/cts/TestNetworkRunnable.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2020 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 android.net.cts; + +import static android.Manifest.permission.MANAGE_TEST_NETWORKS; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static android.net.cts.util.CtsNetUtils.TestNetworkCallback; + +import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.LinkAddress; +import android.net.Network; +import android.net.TestNetworkInterface; +import android.net.TestNetworkManager; +import android.net.cts.util.CtsNetUtils; + +import androidx.test.InstrumentationRegistry; + +import com.android.compatibility.common.util.ThrowingRunnable; + +import java.net.Inet4Address; +import java.net.InetAddress; + +/** This class supports running a test with a test network. */ +public class TestNetworkRunnable implements ThrowingRunnable { + private static final int IP4_PREFIX_LEN = 32; + private static final int IP6_PREFIX_LEN = 128; + + private static final InetAddress DEFAULT_ADDRESS_4 = + InetAddress.parseNumericAddress("192.2.0.2"); + private static final InetAddress DEFAULT_ADDRESS_6 = + InetAddress.parseNumericAddress("2001:db8:1::2"); + + private static final Context sContext = InstrumentationRegistry.getContext(); + private static final ConnectivityManager sCm = + sContext.getSystemService(ConnectivityManager.class); + + private final Test mTest; + + public TestNetworkRunnable(Test test) { + mTest = test; + } + + private void runTest() throws Exception { + final TestNetworkManager tnm = sContext.getSystemService(TestNetworkManager.class); + + // Non-final; these variables ensure we clean up properly after our test if we + // have allocated test network resources + TestNetworkInterface testIface = null; + TestNetworkCallback tunNetworkCallback = null; + + final CtsNetUtils ctsNetUtils = new CtsNetUtils(sContext); + final InetAddress[] addresses = mTest.getTestNetworkAddresses(); + final LinkAddress[] linkAddresses = new LinkAddress[addresses.length]; + for (int i = 0; i < addresses.length; i++) { + InetAddress address = addresses[i]; + if (address instanceof Inet4Address) { + linkAddresses[i] = new LinkAddress(address, IP4_PREFIX_LEN); + } else { + linkAddresses[i] = new LinkAddress(address, IP6_PREFIX_LEN); + } + } + + try { + // Build underlying test network + testIface = tnm.createTunInterface(linkAddresses); + + // Hold on to this callback to ensure network does not get reaped. + tunNetworkCallback = ctsNetUtils.setupAndGetTestNetwork(testIface.getInterfaceName()); + + mTest.runTest(testIface, tunNetworkCallback); + } finally { + try { + mTest.cleanupTest(); + } catch (Exception e) { + // No action + } + + if (testIface != null) { + testIface.getFileDescriptor().close(); + } + + if (tunNetworkCallback != null) { + sCm.unregisterNetworkCallback(tunNetworkCallback); + } + + final Network testNetwork = tunNetworkCallback.currentNetwork; + if (testNetwork != null) { + tnm.teardownTestNetwork(testNetwork); + } + } + } + + @Override + public void run() throws Exception { + if (sContext.checkSelfPermission(MANAGE_TEST_NETWORKS) == PERMISSION_GRANTED) { + runTest(); + } else { + runWithShellPermissionIdentity(this::runTest, MANAGE_TEST_NETWORKS); + } + } + + /** Interface for test caller to configure the test that will be run with a test network */ + public interface Test { + /** Runs the test with a test network */ + void runTest(TestNetworkInterface testIface, TestNetworkCallback tunNetworkCallback) + throws Exception; + + /** Cleans up when the test is finished or interrupted */ + void cleanupTest(); + + /** Returns the IP addresses that will be used by the test network */ + default InetAddress[] getTestNetworkAddresses() { + return new InetAddress[] {DEFAULT_ADDRESS_4, DEFAULT_ADDRESS_6}; + } + } +}