Add TestRule to enable access to deprecated BC algorithms

Android restricts access to a number of deprecated BouncyCastle
algorithms to APKs that target SDK version <= 27. However, those
algorithms still need testing. Rather than set the target SDK version
to be <= 27 (which could have other side effects) tests use
Providers.setMaximumAllowableApiLevelForBcDeprecation(int) to raise
the level to make them accessible at the current target SDK version
and resets it the default value afterwards.

This change adds a JUnit test rule to implement that behavior and
uses it to replace duplicate setUp() and tearDown() code across a
number of tests. It also insulates the tests from having to access
the internal sun.security.jca.Providers and dalvik.system.VMRuntime
classes.

This is intended to be used by external/conscrypt so that the
conscrypt-tests module can stop depending on core-all-systems-module.

Bug: 141539296
Test: atest CtsLibcoreTestCases
Change-Id: If41b5c221c392e9b6d14d500537115d3380c4999
diff --git a/JavaLibrary.bp b/JavaLibrary.bp
index d98541f..37b74d9 100644
--- a/JavaLibrary.bp
+++ b/JavaLibrary.bp
@@ -536,6 +536,7 @@
 java_library_static {
     name: "core-test-rules",
     visibility: [
+        "//external/conscrypt",
         "//frameworks/base/location/tests/locationtests",
     ],
     hostdex: true,
diff --git a/luni/src/test/java/libcore/java/security/ProviderTest.java b/luni/src/test/java/libcore/java/security/ProviderTest.java
index a9a5318..946f602 100644
--- a/luni/src/test/java/libcore/java/security/ProviderTest.java
+++ b/luni/src/test/java/libcore/java/security/ProviderTest.java
@@ -55,29 +55,19 @@
 import javax.crypto.Cipher;
 import javax.crypto.EncryptedPrivateKeyInfo;
 import javax.crypto.NoSuchPaddingException;
-import junit.framework.TestCase;
 import libcore.javax.crypto.MockKey;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
-
-public class ProviderTest extends TestCase {
+public class ProviderTest extends TestCaseWithRules {
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     private static final boolean LOG_DEBUG = false;
 
diff --git a/luni/src/test/java/libcore/java/security/SignatureTest.java b/luni/src/test/java/libcore/java/security/SignatureTest.java
index 3750742..9c014d2 100644
--- a/luni/src/test/java/libcore/java/security/SignatureTest.java
+++ b/luni/src/test/java/libcore/java/security/SignatureTest.java
@@ -37,29 +37,19 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import junit.framework.TestCase;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
 import libcore.util.HexEncoding;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
-
-public class SignatureTest extends TestCase {
+public class SignatureTest extends TestCaseWithRules {
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     private static abstract class MockProvider extends Provider {
         public MockProvider(String name) {
diff --git a/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java b/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java
index 0f84e91..fc09ae8 100644
--- a/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/CertPathValidatorTest.java
@@ -32,8 +32,9 @@
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
-import junit.framework.TestCase;
 import libcore.java.security.TestKeyStore;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
 import org.bouncycastle.asn1.x509.CRLReason;
 import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
 import org.bouncycastle.cert.X509CertificateHolder;
@@ -48,27 +49,16 @@
 import org.bouncycastle.operator.DigestCalculatorProvider;
 import org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
-
-public class CertPathValidatorTest extends TestCase {
+public class CertPathValidatorTest extends TestCaseWithRules {
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     private OCSPResp generateOCSPResponse(X509Certificate serverCertJca, X509Certificate caCertJca,
             PrivateKey caKey, CertificateStatus status) throws Exception {
diff --git a/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java b/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java
index a26c631..1836aac 100644
--- a/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/PKIXParametersTest.java
@@ -16,32 +16,22 @@
 
 package libcore.java.security.cert;
 
-import junit.framework.TestCase;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.KeyStore;
 import java.security.cert.PKIXParameters;
 import libcore.java.security.TestKeyStore;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
-
-public class PKIXParametersTest extends TestCase {
+public class PKIXParametersTest extends TestCaseWithRules {
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     public void testKeyStoreConstructor() throws Exception {
         TestKeyStore server = TestKeyStore.getServer();
diff --git a/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java b/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java
index e2066ae..0e420cb 100644
--- a/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java
@@ -14,13 +14,20 @@
 import java.util.Collections;
 import java.util.Map;
 
-import junit.framework.TestCase;
 import libcore.java.security.TestKeyStore;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
+public class PKIXRevocationCheckerTest extends TestCaseWithRules {
 
-public class PKIXRevocationCheckerTest extends TestCase {
+    // Allow access to deprecated BC algorithms in this test, so we can ensure they
+    // continue to work
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
+
     PKIXRevocationChecker checker;
 
     PrivateKeyEntry entity;
@@ -31,11 +38,6 @@
     protected void setUp() throws Exception {
         super.setUp();
 
-        // Allow access to deprecated BC algorithms in this test, so we can ensure they
-        // continue to work
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-
         CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
         CertPathChecker rc = cpb.getRevocationChecker();
         assertNotNull(rc);
@@ -49,13 +51,6 @@
         issuer = intermediate.getPrivateKey("RSA", "RSA");
     }
 
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
-
     public void test_Initializes() throws Exception {
         assertEquals(0, checker.getOcspResponses().size());
         assertEquals(0, checker.getOcspExtensions().size());
diff --git a/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java b/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java
index b11b40e..ca612be 100644
--- a/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/X509CRLTest.java
@@ -18,8 +18,10 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 import sun.security.provider.X509Factory;
 import sun.security.x509.X509CRLImpl;
 import tests.support.resource.Support_Resources;
@@ -49,27 +51,20 @@
 import java.util.Map;
 import java.util.Set;
 
-import junit.framework.TestCase;
 import libcore.java.security.StandardNames;
 
-public class X509CRLTest extends TestCase {
+public class X509CRLTest extends TestCaseWithRules {
+
+    // Allow access to deprecated BC algorithms in this test, so we can ensure they
+    // continue to work
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
         mX509Providers = Security.getProviders("CertificateFactory.X509");
-
-        // Allow access to deprecated BC algorithms in this test, so we can ensure they
-        // continue to work
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
     }
 
     private Provider[] mX509Providers;
diff --git a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
index 95a95c0..d694214 100644
--- a/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
+++ b/luni/src/test/java/libcore/java/security/cert/X509CertificateTest.java
@@ -57,32 +57,26 @@
 import java.util.Locale;
 import java.util.Set;
 import javax.security.auth.x500.X500Principal;
-import junit.framework.TestCase;
 import libcore.java.security.StandardNames;
-
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 import tests.support.resource.Support_Resources;
 
-public class X509CertificateTest extends TestCase {
+public class X509CertificateTest extends TestCaseWithRules {
+
+    // Allow access to deprecated BC algorithms in this test, so we can ensure they
+    // continue to work
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
 
         mX509Providers = Security.getProviders("CertificateFactory.X509");
-
-        // Allow access to deprecated BC algorithms in this test, so we can ensure they
-        // continue to work
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
     }
 
     private Provider[] mX509Providers;
diff --git a/luni/src/test/java/libcore/javax/crypto/MacTest.java b/luni/src/test/java/libcore/javax/crypto/MacTest.java
index 3e49cd6..bd2ad39 100644
--- a/luni/src/test/java/libcore/javax/crypto/MacTest.java
+++ b/luni/src/test/java/libcore/javax/crypto/MacTest.java
@@ -26,28 +26,18 @@
 import javax.crypto.SecretKey;
 import javax.crypto.SecretKeyFactory;
 import javax.crypto.spec.PBEKeySpec;
-import junit.framework.TestCase;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
-
-public class MacTest extends TestCase {
+public class MacTest extends TestCaseWithRules {
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     private static abstract class MockProvider extends Provider {
         public MockProvider(String name) {
diff --git a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
index 1aa3550..226952f 100644
--- a/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
+++ b/luni/src/test/java/libcore/javax/security/auth/x500/X500PrincipalTest.java
@@ -21,30 +21,20 @@
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import javax.security.auth.x500.X500Principal;
-import junit.framework.TestCase;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
 import libcore.libcore.util.SerializationTester;
-
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
 
-public class X500PrincipalTest extends TestCase {
+public class X500PrincipalTest extends TestCaseWithRules {
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     public void testSerialization() {
         String expected = "aced0005737200266a617661782e73656375726974792e617574682e7"
diff --git a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
index 7d8aff0..751a99e 100644
--- a/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
+++ b/luni/src/test/java/org/apache/harmony/crypto/tests/javax/crypto/MacTest.java
@@ -39,39 +39,29 @@
 import javax.crypto.ShortBufferException;
 import javax.crypto.spec.DHGenParameterSpec;
 import javax.crypto.spec.SecretKeySpec;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
 import org.apache.harmony.crypto.tests.support.MyMacSpi;
 import org.apache.harmony.security.tests.support.SpiEngUtils;
-import junit.framework.TestCase;
 import junit.framework.Test;
 import junit.framework.TestSuite;
 import libcore.java.security.StandardNames;
 import libcore.javax.crypto.MockKey;
 import libcore.javax.crypto.MockKey2;
-
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
 /**
  * Tests for Mac class constructors and methods
  *
  */
-public class MacTest extends TestCase {
+public class MacTest extends TestCaseWithRules {
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     public static final String srvMac = "Mac";
 
diff --git a/luni/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java b/luni/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
index 689efa5..5367dcd 100644
--- a/luni/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
+++ b/luni/src/test/java/org/apache/harmony/security/tests/java/security/MessageDigest2Test.java
@@ -33,9 +33,19 @@
 import java.util.Map.Entry;
 
 import dalvik.system.VMRuntime;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 import sun.security.jca.Providers;
 
-public class MessageDigest2Test extends junit.framework.TestCase {
+public class MessageDigest2Test extends TestCaseWithRules {
+
+    // Allow access to deprecated BC algorithms in this test, so we can ensure they
+    // continue to work
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     private static final String MESSAGEDIGEST_ID = "MessageDigest.";
 
@@ -434,18 +444,6 @@
         for (Provider provider : providers) {
             digestAlgs.put(provider, getDigestAlgorithms(provider));
         }
-
-        // Allow access to deprecated BC algorithms in this test, so we can ensure they
-        // continue to work
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
     }
 
     /*
diff --git a/luni/src/test/java/tests/security/cert/CertificateFactory4Test.java b/luni/src/test/java/tests/security/cert/CertificateFactory4Test.java
index 18fe0c4..1b3f00c 100644
--- a/luni/src/test/java/tests/security/cert/CertificateFactory4Test.java
+++ b/luni/src/test/java/tests/security/cert/CertificateFactory4Test.java
@@ -17,10 +17,10 @@
 
 package tests.security.cert;
 
-import junit.framework.TestCase;
-
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 import tests.support.resource.Support_Resources;
 
 import tests.support.Support_GetResource;
@@ -40,23 +40,13 @@
 import java.util.Collection;
 import java.util.List;
 
-public class CertificateFactory4Test extends TestCase {
+public class CertificateFactory4Test extends TestCaseWithRules {
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     private static final String BASE_URL = Support_GetResource
             .getResourceURL("/../internalres/");
diff --git a/luni/src/test/java/tests/targets/security/cert/CertificateTest.java b/luni/src/test/java/tests/targets/security/cert/CertificateTest.java
index 80b34c0..4a8e5ef 100644
--- a/luni/src/test/java/tests/targets/security/cert/CertificateTest.java
+++ b/luni/src/test/java/tests/targets/security/cert/CertificateTest.java
@@ -32,29 +32,19 @@
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.List;
-import junit.framework.TestCase;
 import libcore.java.security.StandardNames;
+import libcore.junit.junit3.TestCaseWithRules;
+import libcore.junit.util.EnableDeprecatedBouncyCastleAlgorithmsRule;
+import org.junit.Rule;
+import org.junit.rules.TestRule;
 
-import dalvik.system.VMRuntime;
-import sun.security.jca.Providers;
-
-public class CertificateTest extends TestCase {
+public class CertificateTest extends TestCaseWithRules {
 
     // Allow access to deprecated BC algorithms in this test, so we can ensure they
     // continue to work
-    @Override
-    public void setUp() throws Exception {
-        super.setUp();
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                VMRuntime.getRuntime().getTargetSdkVersion());
-    }
-
-    @Override
-    public void tearDown() throws Exception {
-        Providers.setMaximumAllowableApiLevelForBcDeprecation(
-                Providers.DEFAULT_MAXIMUM_ALLOWABLE_TARGET_API_LEVEL_FOR_BC_DEPRECATION);
-        super.tearDown();
-    }
+    @Rule
+    public TestRule enableDeprecatedBCAlgorithmsRule =
+            EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
 
     /*
      * Following certificate chain was taken from https://www.verisign.com and
diff --git a/test-rules/src/main/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRule.java b/test-rules/src/main/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRule.java
new file mode 100644
index 0000000..bfd45ef
--- /dev/null
+++ b/test-rules/src/main/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRule.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2019 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 libcore.junit.util;
+
+import dalvik.system.VMRuntime;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.function.Supplier;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import sun.security.jca.Providers;
+
+/**
+ * Allows tests to temporarily enable deprecated BouncyCastle algorithms to verify that their
+ * behavior has not changed.
+ *
+ * <p>To use add the following to the test class.
+ *
+ * <pre>
+ * &#64;Rule
+ * public TestRule enableDeprecatedBCAlgorithmsRule =
+ *     EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance();
+ * </pre>
+ *
+ * <p>It will give all test methods access to the deprecated algorithms.
+ */
+public class EnableDeprecatedBouncyCastleAlgorithmsRule implements TestRule {
+
+    private static final TestRule INSTANCE = new EnableDeprecatedBouncyCastleAlgorithmsRule();
+
+    public static TestRule getInstance() {
+        return INSTANCE;
+    }
+
+    private EnableDeprecatedBouncyCastleAlgorithmsRule() {
+    }
+
+    @Override
+    public Statement apply(final Statement statement, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                int currentMaximum =
+                        Providers.getMaximumAllowableApiLevelForBcDeprecation();
+                try {
+                    int newMaximum = VMRuntime.getRuntime().getTargetSdkVersion();
+                    Providers.setMaximumAllowableApiLevelForBcDeprecation(newMaximum);
+                    statement.evaluate();
+                } finally {
+                    Providers.setMaximumAllowableApiLevelForBcDeprecation(currentMaximum);
+                }
+            }
+        };
+    }
+}
diff --git a/test-rules/src/test/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRuleTest.java b/test-rules/src/test/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRuleTest.java
new file mode 100644
index 0000000..a08ed84
--- /dev/null
+++ b/test-rules/src/test/java/libcore/junit/util/EnableDeprecatedBouncyCastleAlgorithmsRuleTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 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 libcore.junit.util;
+
+import dalvik.system.VMRuntime;
+import libcore.junit.util.SwitchTargetSdkVersionRule.TargetSdkVersion;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import sun.security.jca.Providers;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests for {@link EnableDeprecatedBouncyCastleAlgorithmsRule}.
+ */
+@RunWith(JUnit4.class)
+public class EnableDeprecatedBouncyCastleAlgorithmsRuleTest {
+
+    /**
+     * Chain the rules together so that changes to the target sdk version will be visible in the
+     * bouncy castle rules.
+     */
+    @Rule
+    public TestRule chain = RuleChain
+            .outerRule(SwitchTargetSdkVersionRule.getInstance())
+            .around(EnableDeprecatedBouncyCastleAlgorithmsRule.getInstance());
+
+    @Test
+    @TargetSdkVersion(23)
+    public void testRunningAsIfTargetedAtSDKVersion23() {
+        assertEquals(23, Providers.getMaximumAllowableApiLevelForBcDeprecation());
+    }
+
+    @Test
+    public void testRunningAsIfTargetedAtCurrentSDKVersion() {
+        assertEquals(VMRuntime.getRuntime().getTargetSdkVersion(),
+                Providers.getMaximumAllowableApiLevelForBcDeprecation());
+    }
+}