AI 147896: Some more fixes for tests that failed in
  the CTS, but worked fine in run-core-tests:
  - One cert test needs isolation, because
  it destroys the security provider.
  - The Thread.sleep() tests were too flaky.
  - Tests that tried to open a temporary DEX
  file failed in the CTS because we do not
  have access to the system DEX cache. We
  are now simply creating our own.
  The Java plan in the CTS should now pass
  fully. Yippie!
  BUG=1285921

Automated import of CL 147896
diff --git a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java
index 3089af5..6ef6d33 100644
--- a/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java
+++ b/libcore/luni/src/test/java/org/apache/harmony/luni/tests/java/lang/ThreadTest.java
@@ -147,6 +147,8 @@
     Thread st, ct, spinner;
 
     static boolean calledMySecurityManager = false;
+    
+    boolean wasInterrupted = false;
 
     /**
      * @tests java.lang.Thread#Thread()
@@ -1427,56 +1429,50 @@
         args = {long.class}
     )
     public void test_sleepJ() {
-        // Test for method void java.lang.Thread.sleep(long)
-
-        // TODO : Test needs enhancing.
-        long stime = 0, ftime = 0;
+        // Note: Not too much we can test here that can be reliably measured.
+        
+        // Check that basic behavior is about right (with some tolerance)
+        long stime = System.currentTimeMillis();
+        
         try {
-            stime = System.currentTimeMillis();
             Thread.sleep(1000);
-            ftime = System.currentTimeMillis();
         } catch (InterruptedException e) {
-            fail("Unexpected interrupt received");
+            fail("Unexpected InterruptedException was thrown");
         }
-        assertTrue("Failed to sleep long enough", (ftime - stime) >= 800);
-        
-        counter = 0;
-        st = new Thread() {
-           
-            public void run() {
-                while(true) {
-                    try {
-                        sleep(1000);
-                        counter++;
-                    } catch(InterruptedException e) {
-                        
-                    }
-                }
-            }
-        };
-       
-        st.start();
 
-        try {
-            Thread.sleep(5000);
-        } catch(InterruptedException e) {
-            fail("InterruptedException was thrown.");
-        }
-        assertEquals(4, counter);
+        long ftime = System.currentTimeMillis();
         
+        assertTrue("Failed to sleep long enough", (ftime - stime) >= 500);
+        assertTrue("Failed to wake up early enough", (ftime - stime) <= 1500);
+        
+        // Check that interrupt works
         st = new Thread() {
             public void run() {
                 try {
                     sleep(10000);
-                    fail("InterruptedException is thrown.");
                 } catch(InterruptedException ie) {
-                    //exception
+                    wasInterrupted = true;
                 }
             }
         };
 
         st.start();
+        
+        try {
+            Thread.sleep(5000);
+        } catch(InterruptedException e) {
+            fail("Unexpected InterruptedException was thrown");
+        }
+        
         st.interrupt();
+        
+        try {
+            Thread.sleep(5000);
+        } catch(InterruptedException e) {
+            fail("Unexpected InterruptedException was thrown");
+        }
+        
+        assertTrue(wasInterrupted);
     }
 
     /**
@@ -1489,57 +1485,50 @@
         args = {long.class, int.class}
     )
     public void test_sleepJI() {
-        // Test for method void java.lang.Thread.sleep(long, int)
-
-        // TODO : Test needs revisiting.
-        long stime = 0, ftime = 0;
+        // Note: Not too much we can test here that can be reliably measured.
+        
+        // Check that basic behavior is about right (with some tolerance)
+        long stime = System.currentTimeMillis();
+        
         try {
-            stime = System.currentTimeMillis();
-            Thread.sleep(1000, 999999);
-            ftime = System.currentTimeMillis();
+            Thread.sleep(1000, 99999);
         } catch (InterruptedException e) {
-            fail("Unexpected interrupt received");
+            fail("Unexpected InterruptedException was thrown");
         }
-        long result = ftime - stime;
-        assertTrue("Failed to sleep long enough: " + result, result >= 900
-                && result <= 1100);
-        
-        counter = 0;
-        st = new Thread() {
-           
-            public void run() {
-                while(true) {
-                    try {
-                        sleep(0, 999999);
-                        counter++;
-                    } catch(InterruptedException e) {
-                        
-                    }
-                }
-            }
-        };
-       
-        st.start();
 
-        try {
-            Thread.sleep(2, 999999);
-        } catch(InterruptedException e) {
-            fail("InterruptedException was thrown.");
-        }
-        assertEquals(2, counter);
+        long ftime = System.currentTimeMillis();
         
+        assertTrue("Failed to sleep long enough", (ftime - stime) >= 500);
+        assertTrue("Failed to wake up early enough", (ftime - stime) <= 1500);
+        
+        // Check that interrupt works
         st = new Thread() {
             public void run() {
                 try {
-                    sleep(10000, 999999);
-                    fail("InterruptedException is thrown.");
+                    sleep(10000, 99999);
                 } catch(InterruptedException ie) {
-                    //exception
+                    wasInterrupted = true;
                 }
             }
         };
+
         st.start();
+        
+        try {
+            Thread.sleep(5000, 99999);
+        } catch(InterruptedException e) {
+            fail("Unexpected InterruptedException was thrown");
+        }
+        
         st.interrupt();
+        
+        try {
+            Thread.sleep(5000);
+        } catch(InterruptedException e) {
+            fail("Unexpected InterruptedException was thrown");
+        }
+        
+        assertTrue(wasInterrupted);
     }
 
     /**
diff --git a/libcore/security/src/test/java/tests/api/javax/security/cert/X509CertificateTest.java b/libcore/security/src/test/java/tests/api/javax/security/cert/X509CertificateTest.java
index e12842a..4af8dc8 100644
--- a/libcore/security/src/test/java/tests/api/javax/security/cert/X509CertificateTest.java
+++ b/libcore/security/src/test/java/tests/api/javax/security/cert/X509CertificateTest.java
@@ -177,18 +177,6 @@
         }
     }
 
-    @Override
-    protected void tearDown() throws Exception {
-        if (myProvider != null) {
-//            Security.removeProvider(myProvider.getName());
-        }
-        if (mySSProvider != null) {
-//            Security.removeProvider(mySSProvider.getName());
-        }
-        
-        super.tearDown();
-    }
-    
     /**
      * X509Certificate() constructor testing.
      * @tests {@link X509Certificate#X509Certificate() }
@@ -875,6 +863,7 @@
       method = "verify",
       args = {java.security.PublicKey.class, java.lang.String.class}
     )
+    @SideEffect("Destroys MD5 provider, hurts succeeding tests")
     public void testVerifyPublicKeyString() throws InvalidKeyException,
             java.security.cert.CertificateException, NoSuchAlgorithmException,
             NoSuchProviderException, SignatureException, IOException,
diff --git a/libcore/security/src/test/java/tests/security/permissions/JavaLangClassLoaderTest.java b/libcore/security/src/test/java/tests/security/permissions/JavaLangClassLoaderTest.java
index b21bece..66302ed 100644
--- a/libcore/security/src/test/java/tests/security/permissions/JavaLangClassLoaderTest.java
+++ b/libcore/security/src/test/java/tests/security/permissions/JavaLangClassLoaderTest.java
@@ -23,15 +23,16 @@
 import dalvik.annotation.TestTargetNew;
 import dalvik.annotation.TestTargetClass;
 import dalvik.system.DexFile;
-import dalvik.system.PathClassLoader;
 
 import junit.framework.TestCase;
 
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.URL;
 import java.security.Permission;
 
+import tests.support.Support_ClassLoader;
 import tests.support.resource.Support_Resources;
 
 /*
@@ -118,7 +119,7 @@
             args = {}
         )
     })
-    @AndroidOnly("uses PathClassLoader and DexFile")
+    @AndroidOnly("uses DexFile")
     @BrokenTest("Endless loop in ClassLoader. Actually a known failure.")
     public void test_getSystemClassLoader () throws IOException,
             IllegalAccessException, InstantiationException {
@@ -129,7 +130,8 @@
             }
             @Override
             public void checkPermission(Permission permission){
-                if(permission instanceof RuntimePermission && "getClassLoader".equals(permission.getName())){
+                if(permission instanceof RuntimePermission &&
+                        "getClassLoader".equals(permission.getName())){
                     called = true;
                 }
             }
@@ -166,7 +168,7 @@
         InputStream is = Support_Resources.getResourceStream("testdex.jar");
         Support_Resources.copyLocalFileto(tempFile, is);
         DexFile dexfile = new DexFile(tempFile);
-        PathClassLoader pcl = new PathClassLoader("",
+        ClassLoader pcl = Support_ClassLoader.getInstance(new URL(""),
                 ClassLoader.getSystemClassLoader());
         
         Class<?> testClass = dexfile.loadClass(
diff --git a/libcore/support/src/test/java/tests/support/Support_ClassLoader.java b/libcore/support/src/test/java/tests/support/Support_ClassLoader.java
index b442e60..81de979 100644
--- a/libcore/support/src/test/java/tests/support/Support_ClassLoader.java
+++ b/libcore/support/src/test/java/tests/support/Support_ClassLoader.java
@@ -15,10 +15,11 @@
  */
 package tests.support;
 
+import java.io.File;
 import java.net.URL;
 import java.net.URLClassLoader;
 
-import dalvik.system.PathClassLoader;
+import dalvik.system.DexClassLoader;
 
 /**
  * Support class for creating a file-based ClassLoader. Delegates to either
@@ -46,14 +47,36 @@
             throw new RuntimeException("Unable to create ClassLoader", ex);
         }
     }
-    
+
+    /**
+     * Implementation for Dalvik. Uses the DexClassLoader, so we can write
+     * temporary DEX files to a special directory. We don't want to spoil the
+     * system's DEX cache with our files. Also, we might not have write access
+     * to the system's DEX cache at all (which is the case when we're running
+     * CTS).
+     */
     static class Dalvik extends Support_ClassLoader {
+
+        private static File tmp;
+
+        static {
+            tmp = new File(System.getProperty("java.io.tmpdir"), "dex-cache");
+            tmp.mkdirs();
+        }
+
+        @Override
         public ClassLoader getClassLoader(URL url, ClassLoader parent) {
-            return new PathClassLoader(url.getPath(), parent);
+            return new DexClassLoader(url.getPath(), tmp.getAbsolutePath(),
+                    null, parent);
         }
     }
     
+    /**
+     * Implementation for the reference implementation. Nothing interesting to
+     * see here. Please get along.
+     */
     static class RefImpl extends Support_ClassLoader {
+        @Override
         public ClassLoader getClassLoader(URL url, ClassLoader parent) {
             return new URLClassLoader(new URL[] { url }, parent);
         }