# HG changeset patch
# User andrew
# Date 1333630656 -3600
# Node ID a1fe26be9fab64d58f7b1b09a1a4cde30d376383
# Parent  3377516da58310f3d151dba6c5ee599932aa1ff4
Generalise ucrypto cryptography tests.

diff --git a/test/com/oracle/security/ucrypto/TestAES.java b/test/com/oracle/security/ucrypto/TestAES.java
--- openjdk/jdk/test/com/oracle/security/ucrypto/TestAES.java
+++ openjdk/jdk/test/com/oracle/security/ucrypto/TestAES.java
@@ -55,21 +55,24 @@
         main(new TestAES(), null);
     }
 
-    public void doTest(Provider prov) throws Exception {
+    public boolean doTest(Provider prov) 
+    throws NoSuchAlgorithmException {
         // Provider for testing Interoperability
         Provider sunJCEProv = Security.getProvider("SunJCE");
 
-        testCipherInterop(CIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv);
-        testCipherInterop(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv);
+        boolean result1 = testCipherInterop(CIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv);
+        boolean result2 = testCipherInterop(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv);
 
-        testCipherOffset(CIPHER_ALGOS, CIPHER_KEY, prov);
-        testCipherOffset(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov);
+        boolean result3 = testCipherOffset(CIPHER_ALGOS, CIPHER_KEY, prov);
+        boolean result4 = testCipherOffset(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov);
 
-        testCipherKeyWrapping(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv);
-        testCipherGCM(CIPHER_KEY, prov);
+        boolean result5 = testCipherKeyWrapping(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv);
+        boolean result6 = testCipherGCM(CIPHER_KEY, prov);
+
+	return result1 && result2 && result3 && result4 && result5 && result6;
     }
 
-    private static void testCipherInterop(String[] algos, SecretKey key,
+    private static boolean testCipherInterop(String[] algos, SecretKey key,
                                           Provider p,
                                           Provider interopP) {
         boolean testPassed = true;
@@ -83,7 +86,7 @@
                 try {
                     c = Cipher.getInstance(algo, p);
                 } catch (NoSuchAlgorithmException nsae) {
-                    System.out.println("Skipping Unsupported CIP algo: " + algo);
+                    System.err.println("Skipping Unsupported CIP algo: " + algo);
                     continue;
                 }
                 c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null);
@@ -95,10 +98,10 @@
                 byte[] eout2 = c2.doFinal(in, 0, in.length);
 
                 if (!Arrays.equals(eout, eout2)) {
-                    System.out.println(algo + ": DIFF FAILED");
+                    System.err.println(algo + ": DIFF FAILED");
                     testPassed = false;
                 } else {
-                    System.out.println(algo + ": ENC Passed");
+                    System.err.println(algo + ": ENC Passed");
                 }
 
                 // check DEC
@@ -108,34 +111,36 @@
                 byte[] dout2 = c2.doFinal(eout2);
 
                 if (!Arrays.equals(dout, dout2)) {
-                    System.out.println(algo + ": DIFF FAILED");
+                    System.err.println(algo + ": DIFF FAILED");
                     testPassed = false;
                 } else {
-                    System.out.println(algo + ": DEC Passed");
+                    System.err.println(algo + ": DEC Passed");
                 }
             } catch(Exception ex) {
-                System.out.println("Unexpected Exception: " + algo);
+                System.err.println("Unexpected Exception: " + algo);
                 ex.printStackTrace();
                 testPassed = false;
             }
         }
 
-        if (!testPassed) {
-            throw new RuntimeException("One or more CIPHER test failed!");
+        if (testPassed) {
+            System.err.println("CIPHER Interop Tests Passed");
         } else {
-            System.out.println("CIPHER Interop Tests Passed");
+            System.err.println("One or more CIPHER Interop tests failed!");
         }
+	
+	return testPassed;
     }
 
-    private static void testCipherOffset(String[] algos, SecretKey key,
-                                         Provider p) {
+    private static boolean testCipherOffset(String[] algos, SecretKey key,
+					    Provider p) {
         boolean testPassed = true;
         byte[] in = new byte[16];
         (new SecureRandom()).nextBytes(in);
         int blockSize = 16;
 
         for (int j = 1; j < (in.length - 1); j++) {
-            System.out.println("Input offset size: " + j);
+            System.err.println("Input offset size: " + j);
             for (int i = 0; i < algos.length; i++) {
                 try {
                     // check ENC
@@ -143,13 +148,13 @@
                     try {
                         c = Cipher.getInstance(algos[i], p);
                     } catch (NoSuchAlgorithmException nsae) {
-                        System.out.println("Skip Unsupported CIP algo: " + algos[i]);
+                        System.err.println("Skip Unsupported CIP algo: " + algos[i]);
                         continue;
                     }
                     c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null);
                     byte[] eout = new byte[c.getOutputSize(in.length)];
                     int firstPartLen = in.length - j - 1;
-                    //System.out.print("1st UPDATE: " + firstPartLen);
+                    //System.err.print("1st UPDATE: " + firstPartLen);
                     int k = c.update(in, 0, firstPartLen, eout, 0);
                     k += c.update(in, firstPartLen, 1, eout, k);
                     k += c.doFinal(in, firstPartLen+1, j, eout, k);
@@ -173,21 +178,23 @@
                     k += c.doFinal(eout, firstPartLen+1, eout.length - firstPartLen - 1, dout, k);
                     if (!checkArrays(in, in.length, dout, k)) testPassed = false;
                 } catch(Exception ex) {
-                    System.out.println("Unexpected Exception: " + algos[i]);
+                    System.err.println("Unexpected Exception: " + algos[i]);
                     ex.printStackTrace();
                     testPassed = false;
                 }
             }
         }
-        if (!testPassed) {
-            throw new RuntimeException("One or more CIPHER test failed!");
+        if (testPassed) {
+            System.err.println("CIPHER Offset Tests Passed");
         } else {
-            System.out.println("CIPHER Offset Tests Passed");
+            System.err.println("One or more CIPHER offset tests failed!");
         }
+	
+	return testPassed;
     }
 
-    private static void testCipherKeyWrapping(String[] algos, SecretKey key,
-                                              Provider p, Provider interopP)
+    private static boolean testCipherKeyWrapping(String[] algos, SecretKey key,
+						 Provider p, Provider interopP)
         throws NoSuchAlgorithmException {
         boolean testPassed = true;
 
@@ -203,13 +210,13 @@
 
         for (int i = 0; i < algos.length; i++) {
             try {
-                System.out.println(algos[i] + " - Native WRAP/Java UNWRAP");
+                System.err.println(algos[i] + " - Native WRAP/Java UNWRAP");
 
                 Cipher c1;
                 try {
                     c1 = Cipher.getInstance(algos[i], p);
                 } catch (NoSuchAlgorithmException nsae) {
-                    System.out.println("Skipping Unsupported CIP algo: " + algos[i]);
+                    System.err.println("Skipping Unsupported CIP algo: " + algos[i]);
                     continue;
                 }
                 c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null);
@@ -224,7 +231,7 @@
                     if (!checkKeys(tbwKeys[j], recovered)) testPassed = false;
                 }
 
-                System.out.println(algos[i] + " - Java WRAP/Native UNWRAP");
+                System.err.println(algos[i] + " - Java WRAP/Native UNWRAP");
                 c1 = Cipher.getInstance(algos[i], interopP);
                 c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null);
                 params = c1.getParameters();
@@ -239,21 +246,23 @@
                 }
 
             } catch(Exception ex) {
-                System.out.println("Unexpected Exception: " + algos[i]);
+                System.err.println("Unexpected Exception: " + algos[i]);
                 ex.printStackTrace();
                 testPassed = false;
             }
         }
-        if (!testPassed) {
-            throw new RuntimeException("One or more CIPHER test failed!");
+        if (testPassed) {
+            System.err.println("CIPHER KeyWrapping Tests Passed");
         } else {
-            System.out.println("CIPHER KeyWrapping Tests Passed");
+            System.err.println("One or more CIPHER keywrapping tests failed!");
         }
+
+	return testPassed;
     }
 
 
-    private static void testCipherGCM(SecretKey key,
-                                      Provider p) {
+    private static boolean testCipherGCM(SecretKey key,
+					 Provider p) {
         boolean testPassed = true;
         byte[] in = new byte[16];
         (new SecureRandom()).nextBytes(in);
@@ -270,8 +279,8 @@
             try {
                 c = Cipher.getInstance(algo, p);
             } catch (NoSuchAlgorithmException nsae) {
-                System.out.println("Skipping Unsupported CIP algo: " + algo);
-                return;
+                System.err.println("Skipping Unsupported CIP algo: " + algo);
+                return true;
             }
             for (int i = 0; i < tagLen.length; i++) {
                 AlgorithmParameterSpec paramSpec = new GCMParameterSpec(tagLen[i], iv);
@@ -287,33 +296,35 @@
                 byte[] dout = c.doFinal(eout, 0, eout.length);
 
                 if (!Arrays.equals(dout, in)) {
-                    System.out.println(algo + ": PT and RT DIFF FAILED");
+                    System.err.println(algo + ": PT and RT DIFF FAILED");
                     testPassed = false;
                 } else {
-                    System.out.println(algo + ": tagLen " + tagLen[i] + " done");
+                    System.err.println(algo + ": tagLen " + tagLen[i] + " done");
                 }
             }
         } catch(Exception ex) {
-            System.out.println("Unexpected Exception: " + algo);
+            System.err.println("Unexpected Exception: " + algo);
             ex.printStackTrace();
             testPassed = false;
         }
-        if (!testPassed) {
-            throw new RuntimeException("One or more CIPHER test failed!");
+        if (testPassed) {
+            System.err.println("CIPHER GCM Tests Passed");
         } else {
-            System.out.println("CIPHER GCM Tests Passed");
+            System.err.println("One or more CIPHER GCM tests failed!");
         }
+
+	return testPassed;
     }
 
     private static boolean checkArrays(byte[] a1, int a1Len, byte[] a2, int a2Len) {
         boolean equal = true;
         if (a1Len != a2Len) {
-            System.out.println("DIFFERENT OUT LENGTH");
+            System.err.println("DIFFERENT OUT LENGTH");
             equal = false;
         } else {
             for (int p = 0; p < a1Len; p++) {
                 if (a1[p] != a2[p]) {
-                    System.out.println("DIFF FAILED");
+                    System.err.println("DIFF FAILED");
                     equal = false;
                     break;
                 }
@@ -325,13 +336,13 @@
     private static boolean checkKeys(Key k1, Key k2) {
         boolean equal = true;
         if (!k1.getAlgorithm().equalsIgnoreCase(k2.getAlgorithm())) {
-            System.out.println("DIFFERENT Key Algorithm");
+            System.err.println("DIFFERENT Key Algorithm");
             equal = false;
         } else if (!k1.getFormat().equalsIgnoreCase(k2.getFormat())) {
-            System.out.println("DIFFERENT Key Format");
+            System.err.println("DIFFERENT Key Format");
             equal = false;
         } else if (!Arrays.equals(k1.getEncoded(), k2.getEncoded())) {
-            System.out.println("DIFFERENT Key Encoding");
+            System.err.println("DIFFERENT Key Encoding");
             equal = false;
         }
         return equal;
diff --git a/test/com/oracle/security/ucrypto/TestDigest.java b/test/com/oracle/security/ucrypto/TestDigest.java
--- openjdk/jdk/test/com/oracle/security/ucrypto/TestDigest.java
+++ openjdk/jdk/test/com/oracle/security/ucrypto/TestDigest.java
@@ -47,7 +47,7 @@
         main(new TestDigest(), null);
     }
 
-    public void doTest(Provider p) {
+    public boolean doTest(Provider p) {
         boolean testPassed = true;
         byte[] msg = new byte[200];
         (new SecureRandom()).nextBytes(msg);
@@ -59,7 +59,7 @@
                 try {
                     md = MessageDigest.getInstance(a, p);
                 } catch (NoSuchAlgorithmException nsae) {
-                    System.out.println("Skipping Unsupported MD algo: " + a);
+                    System.err.println("Skipping Unsupported MD algo: " + a);
                     continue;
                 }
                 md2 = MessageDigest.getInstance(a, interopProvName);
@@ -70,7 +70,7 @@
                     md2.update(msg);
                     byte[] digest2 = md2.digest();
                     if (!Arrays.equals(digest, digest2)) {
-                        System.out.println("DIFF1 FAILED for: " + a + " at iter " + i);
+                        System.err.println("DIFF1 FAILED for: " + a + " at iter " + i);
                         testPassed = false;
                     }
                 }
@@ -83,7 +83,7 @@
                     byte[] digest = md.digest();
                     byte[] digest2 = md2.digest();
                     if (!Arrays.equals(digest, digest2)) {
-                        System.out.println("DIFF2 FAILED for: " + a + " at iter " + i);
+                        System.err.println("DIFF2 FAILED for: " + a + " at iter " + i);
                         testPassed = false;
                     }
                 }
@@ -94,7 +94,7 @@
                 byte[] digest = md.digest();
                 byte[] digest2 = md2.digest();
                 if (!Arrays.equals(digest, digest2)) {
-                    System.out.println("DIFF-3.1 FAILED for: " + a);
+                    System.err.println("DIFF-3.1 FAILED for: " + a);
                     testPassed = false;
                 }
                 md.update(msg);
@@ -102,26 +102,28 @@
                 digest = md.digest();
                 digest2 = md2.digest();
                 if (!Arrays.equals(digest, digest2)) {
-                    System.out.println("DIFF-3.2 FAILED for: " + a);
+                    System.err.println("DIFF-3.2 FAILED for: " + a);
                     testPassed = false;
                 }
                 md2 = (MessageDigest) md.clone(); // clone after digest
                 digest = md.digest();
                 digest2 = md2.digest();
                 if (!Arrays.equals(digest, digest2)) {
-                    System.out.println("DIFF-3.3 FAILED for: " + a);
+                    System.err.println("DIFF-3.3 FAILED for: " + a);
                     testPassed = false;
                 }
             } catch(Exception ex) {
-                System.out.println("Unexpected Exception: " + a);
+                System.err.println("Unexpected Exception: " + a);
                 ex.printStackTrace();
                 testPassed = false;
             }
         }
-        if (!testPassed) {
-            throw new RuntimeException("One or more MD test failed!");
+        if (testPassed) {
+            System.err.println("MD Tests Passed");
         } else {
-            System.out.println("MD Tests Passed");
+            System.err.println("One or more MD test failed!");
         }
+
+	return testPassed;
     }
 }
diff --git a/test/com/oracle/security/ucrypto/TestRSA.java b/test/com/oracle/security/ucrypto/TestRSA.java
--- openjdk/jdk/test/com/oracle/security/ucrypto/TestRSA.java
+++ openjdk/jdk/test/com/oracle/security/ucrypto/TestRSA.java
@@ -164,25 +164,35 @@
         (byte)0x04, (byte)0x85, (byte)0x73, (byte)0xd1
     };
 
-    private static KeyPair genRSAKey(int keyLength) throws Exception {
-        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
-        kpg.initialize(keyLength);
-        return kpg.generateKeyPair();
+    private static KeyPair genRSAKey(int keyLength) {
+	try {
+	    KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+	    kpg.initialize(keyLength);
+	    return kpg.generateKeyPair();
+	} catch (NoSuchAlgorithmException e) {
+	    System.err.println("Couldn't generate key: " + e);
+	    return null;
+	}
     }
 
-    private static KeyPair genPredefinedRSAKeyPair() throws Exception {
-        KeyFactory kf = KeyFactory.getInstance("RSA");
-        BigInteger mod = new BigInteger(MOD);
-        BigInteger pub = new BigInteger(PUB_EXP);
-
-        PrivateKey privKey = kf.generatePrivate
-            (new RSAPrivateCrtKeySpec
-             (mod, pub, new BigInteger(PRIV_EXP),
-              new BigInteger(PRIME_P), new BigInteger(PRIME_Q),
-              new BigInteger(EXP_P), new BigInteger(EXP_Q),
-              new BigInteger(CRT_COEFF)));
-        PublicKey pubKey = kf.generatePublic(new RSAPublicKeySpec(mod, pub));
-        return new KeyPair(pubKey, privKey);
+    private static KeyPair genPredefinedRSAKeyPair() {
+	try {
+	    KeyFactory kf = KeyFactory.getInstance("RSA");
+	    BigInteger mod = new BigInteger(MOD);
+	    BigInteger pub = new BigInteger(PUB_EXP);
+	    
+	    PrivateKey privKey = kf.generatePrivate
+		(new RSAPrivateCrtKeySpec
+		 (mod, pub, new BigInteger(PRIV_EXP),
+		  new BigInteger(PRIME_P), new BigInteger(PRIME_Q),
+		  new BigInteger(EXP_P), new BigInteger(EXP_Q),
+		  new BigInteger(CRT_COEFF)));
+	    PublicKey pubKey = kf.generatePublic(new RSAPublicKeySpec(mod, pub));
+	    return new KeyPair(pubKey, privKey);
+	} catch (NoSuchAlgorithmException|InvalidKeySpecException ex) {
+	    System.err.println("Couldn't generate predefined key pair: " + ex);
+	    return null;
+	}
     }
 
     private static final String CIP_ALGOS[] = {
@@ -207,106 +217,152 @@
         main(new TestRSA(), null);
     }
 
-    public void doTest(Provider prov) throws Exception {
+    public boolean doTest(Provider prov) {
         // first test w/ predefine KeyPair
         KeyPair pkp = genPredefinedRSAKeyPair();
-        System.out.println("Test against Predefined RSA Key Pair");
-        testCipher(pkp, 128, true, prov);
-        testSignature(pkp, true, prov);
+	if (pkp == null)
+	    return true;
+        System.err.println("Test against Predefined RSA Key Pair");
+        boolean result1 = testCipher(pkp, 128, true, prov);
+        boolean result2 = testSignature(pkp, true, prov);
 
+	boolean[] cResults = new boolean[10];
+	boolean[] sResults = new boolean[10];
         for (int i = 0; i < 10; i++) {
             // then test w/ various key lengths
             int keyLens[] = { 1024, 2048 };
             kp = new KeyPair[keyLens.length];
 
-            testCipher(keyLens, false, prov);
-            testSignature(keyLens, false, prov);
+            cResults[i] = testCipher(keyLens, false, prov);
+            sResults[i] = testSignature(keyLens, false, prov);
         }
+	boolean result3 = true;
+	boolean result4 = true;
+	for (int i = 0; i < 10; i++) {
+	    if (!cResults[i])
+		result3 = false;
+	    if (!sResults[i])
+		result4 = false;
+	}
+	return result1 && result2 && result3 && result4;
     }
 
 
-    private static void testCipher(KeyPair kp, int inputSizeInBytes,
-                                   boolean checkInterop, Provider prov)
-        throws Exception {
+    private static boolean testCipher(KeyPair kp, int inputSizeInBytes,
+				      boolean checkInterop, Provider prov) {
         Cipher c1, c2;
+	boolean[] results = new boolean[CIP_ALGOS.length];
         for (int i = 0; i < CIP_ALGOS.length; i++) {
             String algo = CIP_ALGOS[i];
             try {
                 c1 = Cipher.getInstance(algo, prov);
-            } catch (NoSuchAlgorithmException nsae) {
-                System.out.println("Skip unsupported Cipher algo: " + algo);
+            } catch (NoSuchAlgorithmException|NoSuchPaddingException nsae) {
+                System.err.println("Skip unsupported Cipher algo: " + algo);
+		results[i] = true;
                 continue;
             }
 
-            if (checkInterop) {
-                c2 = Cipher.getInstance(algo, "SunJCE");
-            } else {
-                c2 = Cipher.getInstance(algo, prov);
+	    try {
+		if (checkInterop) {
+		    c2 = Cipher.getInstance(algo, "SunJCE");
+		} else {
+		    c2 = Cipher.getInstance(algo, prov);
+		}
+            } catch (NoSuchAlgorithmException|NoSuchPaddingException|NoSuchProviderException nsae) {
+                System.err.println("Skip unsupported Cipher algo: " + algo);
+		results[i] = true;
+                continue;
             }
+
             byte[] data = Arrays.copyOf
                  (PLAINTEXT, inputSizeInBytes - INPUT_SIZE_REDUCTION[i]);
 
-            testEncryption(c1, c2, kp, data);
+            results[i] = testEncryption(c1, c2, kp, data);
         }
+	for (int i = 0; i < CIP_ALGOS.length; i++)
+	    if (!results[i])
+		return false;
+	return true;
     }
 
-    private static void testCipher(int keyLens[], boolean checkInterop,
-                                   Provider prov)
-        throws Exception {
+    private static boolean testCipher(int keyLens[], boolean checkInterop,
+				      Provider prov) {
         // RSA CipherText will always differ due to the random nonce in padding
         // so we check whether both
         // 1) Java Encrypt/C Decrypt
         // 2) C Encrypt/Java Decrypt
         // works
         Cipher c1, c2;
+	boolean[] results = new boolean[CIP_ALGOS.length];
         for (int i = 0; i < CIP_ALGOS.length; i++) {
             String algo = CIP_ALGOS[i];
+	    results[i] = true;
             try {
                 c1 = Cipher.getInstance(algo, prov);
-            } catch (NoSuchAlgorithmException nsae) {
-                System.out.println("Skip unsupported Cipher algo: " + algo);
+            } catch (NoSuchAlgorithmException|NoSuchPaddingException nsae) {
+                System.err.println("Skip unsupported Cipher algo: " + algo);
                 continue;
             }
 
-            if (checkInterop) {
-                c2 = Cipher.getInstance(algo, "SunJCE");
-            } else {
-                c2 = Cipher.getInstance(algo, prov);
+	    try {
+		if (checkInterop) {
+		    c2 = Cipher.getInstance(algo, "SunJCE");
+		} else {
+		    c2 = Cipher.getInstance(algo, prov);
+		}
+            } catch (NoSuchAlgorithmException|NoSuchPaddingException|NoSuchProviderException nsae) {
+                System.err.println("Skip unsupported Cipher algo: " + algo);
+                continue;
             }
 
+	    boolean[] encResults = new boolean[keyLens.length];
             for (int h = 0; h < keyLens.length; h++) {
                 // Defer key pair generation until now when it'll soon be used.
                 if (kp[h] == null) {
                     kp[h] = genRSAKey(keyLens[h]);
+		    if (kp[h] == null) {
+			encResults[h] = true;
+			continue;
+		    }
                 }
-                System.out.println("\tTesting Cipher " + algo + " w/ KeySize " + keyLens[h]);
+                System.err.println("Testing Cipher " + algo + " w/ KeySize " + keyLens[h]);
                 byte[] data = Arrays.copyOf
                     (PLAINTEXT, keyLens[h]/8 - INPUT_SIZE_REDUCTION[i]);
-                testEncryption(c1, c2, kp[h], data);
+                encResults[h] = testEncryption(c1, c2, kp[h], data);
             }
+	    for (int h = 0; h < keyLens.length; h++)
+		if (!encResults[h])
+		    results[i] = false;
         }
+	for (int i = 0; i < CIP_ALGOS.length; i++)
+	    if (!results[i])
+		return false;
+	return true;
     }
 
-    private static void testEncryption(Cipher c1, Cipher c2, KeyPair kp, byte[] data)
-        throws Exception {
+    private static boolean testEncryption(Cipher c1, Cipher c2, KeyPair kp, byte[] data) {
         // C1 Encrypt + C2 Decrypt
         byte[] out1 = null;
         byte[] recoveredText = null;
+	boolean result1 = true;
         try {
             c1.init(Cipher.ENCRYPT_MODE, kp.getPublic());
             out1 = c1.doFinal(data);
             c2.init(Cipher.DECRYPT_MODE, kp.getPrivate());
             recoveredText = c2.doFinal(out1);
         } catch (Exception ex) {
-            System.out.println("\tDEC ERROR: unexpected exception");
+            System.err.println("DEC ERROR: unexpected exception: " + ex);
             ex.printStackTrace();
-            throw ex;
+            result1 = false;
         }
+	boolean result2 = true;
         if(!Arrays.equals(recoveredText, data)) {
-            throw new RuntimeException("\tDEC ERROR: different PT bytes!");
+            System.err.println("DEC ERROR: different PT bytes");
+	    result2 = false;
         }
         // C2 Encrypt + C1 Decrypt
         byte[] cipherText = null;
+	boolean result3 = true;
         try {
             c2.init(Cipher.ENCRYPT_MODE, kp.getPublic());
             cipherText = c2.doFinal(data);
@@ -314,108 +370,158 @@
             try {
                 out1 = c1.doFinal(cipherText);
             } catch (Exception ex) {
-                System.out.println("\tENC ERROR: invalid encrypted output");
+                System.err.println("\tENC ERROR: invalid encrypted output: " + ex);
                 ex.printStackTrace();
-                throw ex;
+                result3 = false;
             }
         } catch (Exception ex) {
-            System.out.println("\tENC ERROR: unexpected exception");
+            System.err.println("ENC ERROR: unexpected exception: " + ex);
             ex.printStackTrace();
-            throw ex;
+            result3 = false;
         }
-        if (!Arrays.equals(out1, data)) {
-            throw new RuntimeException("\tENC ERROR: Decrypted result DIFF!");
+	boolean result4 = Arrays.equals(out1, data);
+        if (!result4) {
+            System.err.println("ENC ERROR: Decrypted result DIFF");
         }
-        System.out.println("\t=> PASS");
+	if (result1 && result2 && result3 && result4) {
+	    System.err.println("=> PASS");
+	    return true;
+	}
+	return false;
     }
 
-    private static void testSignature(KeyPair kp, boolean checkInterop,
-                                      Provider prov) throws Exception {
+    private static boolean testSignature(KeyPair kp, boolean checkInterop,
+					 Provider prov) {
         byte[] data = PLAINTEXT;
         Signature sig1, sig2;
+	boolean[] results = new boolean[SIG_ALGOS.length];
         for (int i = 0; i < SIG_ALGOS.length; i++) {
             String algo = SIG_ALGOS[i];
             try {
                 sig1 = Signature.getInstance(algo, prov);
             } catch (NoSuchAlgorithmException nsae) {
-                System.out.println("Skip unsupported Signature algo: " + algo);
+                System.err.println("Skip unsupported Signature algo: " + algo);
+		results[i] = true;
                 continue;
             }
 
-            if (checkInterop) {
-                sig2 = Signature.getInstance(algo, "SunRsaSign");
-            } else {
-                sig2 = Signature.getInstance(algo, prov);
+	    try {
+		if (checkInterop) {
+		    sig2 = Signature.getInstance(algo, "SunRsaSign");
+		} else {
+		    sig2 = Signature.getInstance(algo, prov);
+		}
+	    } catch (NoSuchAlgorithmException|NoSuchProviderException nsae) {
+		System.err.println("Skip unsupported interop Signature algo: " + algo);
+		results[i] = true;
+		continue;
             }
-            testSigning(sig1, sig2, kp, data);
+            results[i] = testSigning(sig1, sig2, kp, data);
         }
+	for (int i = 0; i < SIG_ALGOS.length; i++)
+	    if (!results[i])
+		return false;
+	return true;
     }
 
-    private static void testSignature(int keyLens[], boolean checkInterop,
-                                      Provider prov) throws Exception {
+    private static boolean testSignature(int keyLens[], boolean checkInterop,
+					 Provider prov) {
         byte[] data = PLAINTEXT;
         Signature sig1, sig2;
+	boolean[] results = new boolean[SIG_ALGOS.length];
         for (int i = 0; i < SIG_ALGOS.length; i++) {
             String algo = SIG_ALGOS[i];
+	    results[i] = true;
             try {
                 sig1 = Signature.getInstance(algo, prov);
             } catch (NoSuchAlgorithmException nsae) {
-                System.out.println("Skip unsupported Signature algo: " + algo);
+                System.err.println("Skip unsupported Signature algo: " + algo);
                 continue;
             }
 
-            if (checkInterop) {
-                sig2 = Signature.getInstance(algo, "SunRsaSign");
-            } else {
-                sig2 = Signature.getInstance(algo, prov);
+	    try {
+		if (checkInterop) {
+		    sig2 = Signature.getInstance(algo, "SunRsaSign");
+		} else {
+		    sig2 = Signature.getInstance(algo, prov);
+		}
+            } catch (NoSuchAlgorithmException|NoSuchProviderException nsae) {
+                System.err.println("Skip unsupported Signature algo: " + algo);
+                continue;
             }
 
+	    boolean[] subResults = new boolean[keyLens.length];
             for (int h = 0; h < keyLens.length; h++) {
                 // Defer key pair generation until now when it'll soon be used.
                 if (kp[h] == null) {
                     kp[h] = genRSAKey(keyLens[h]);
+		    if (kp[h] == null) {
+			subResults[h] = true;
+			continue;
+		    }
                 }
-                System.out.println("\tTesting Signature " + algo + " w/ KeySize " + keyLens[h]);
+                System.err.println("Testing Signature " + algo + " w/ KeySize " + keyLens[h]);
 
-                testSigning(sig1, sig2, kp[h], data);
+                subResults[h] = testSigning(sig1, sig2, kp[h], data);
             }
+	    for (int h = 0; h < keyLens.length; h++)
+		if (!subResults[h])
+		    results[i] = false;
         }
+	for (int i = 0; i < SIG_ALGOS.length; i++)
+	    if (!results[i])
+		return false;
+	return true;
     }
 
-    private static void testSigning(Signature sig1, Signature sig2, KeyPair kp, byte[] data)
-            throws Exception {
+    private static boolean testSigning(Signature sig1, Signature sig2, KeyPair kp, byte[] data) {
         boolean sameSig = false;
         byte[] out = null;
+	boolean testInit = true;
         try {
             sig1.initSign(kp.getPrivate());
             sig1.update(data);
             out = sig1.sign();
         } catch (Exception ex) {
-            System.out.println("\tSIGN ERROR: unexpected exception!");
+            System.err.println("SIGN ERROR: unexpected exception: " + ex);
             ex.printStackTrace();
+	    testInit = false;
         }
 
-        sig2.initSign(kp.getPrivate());
-        sig2.update(data);
-        byte[] out2 = sig2.sign();
-        if (!Arrays.equals(out2, out)) {
-            throw new RuntimeException("\tSIGN ERROR: Signature DIFF!");
+	boolean testInit2 = true;
+	byte[] out2 = null;
+	try {
+	    sig2.initSign(kp.getPrivate());
+	    sig2.update(data);
+	    out2 = sig2.sign();
+	} catch (InvalidKeyException|SignatureException ex) {
+	    System.err.println("SIGN ERROR: unexpected exception " + ex);
+	    ex.printStackTrace();
+	    testInit2 = false;
+	}
+	boolean sigTestPassed = true;
+        if (out2 == null || !Arrays.equals(out2, out)) {
+            System.err.println("SIGN ERROR: Signature DIFF!");
+	    sigTestPassed = false;
         }
 
         boolean verify = false;
         try {
-            System.out.println("\tVERIFY1 using native out");
+            System.err.println("VERIFY1 using native out");
             sig1.initVerify(kp.getPublic());
             sig1.update(data);
             verify = sig1.verify(out);
             if (!verify) {
-                throw new RuntimeException("VERIFY1 FAIL!");
+                System.err.println("VERIFY1 FAIL!");
             }
         } catch (Exception ex) {
-            System.out.println("\tVERIFY1 ERROR: unexpected exception!");
+            System.err.println("VERIFY1 ERROR: unexpected exception: " + ex);
             ex.printStackTrace();
-            throw ex;
         }
-        System.out.println("\t=> PASS");
+	if (verify && sigTestPassed && testInit && testInit2) {
+	    System.err.println("=> PASS");
+	    return true;
+	}
+	return false;
     }
 }
diff --git a/test/com/oracle/security/ucrypto/UcryptoTest.java b/test/com/oracle/security/ucrypto/UcryptoTest.java
--- openjdk/jdk/test/com/oracle/security/ucrypto/UcryptoTest.java
+++ openjdk/jdk/test/com/oracle/security/ucrypto/UcryptoTest.java
@@ -44,22 +44,26 @@
         return (Provider)obj;
     }
 
-    public abstract void doTest(Provider p) throws Exception;
+    public abstract boolean doTest(Provider p) throws Exception;
 
     public static void main(UcryptoTest test, String config) throws Exception {
         Provider prov = null;
-        if (hasUcrypto) {
-            if (config != null) {
-                prov = getCustomizedUcrypto(config);
-            } else {
-                prov = Security.getProvider("OracleUcrypto");
-            }
+        if (hasUcrypto && config != null) {
+	    prov = getCustomizedUcrypto(config);
         }
-        if (prov == null) {
-            // un-available, skip testing...
-            System.out.println("No OracleUcrypto provider found, skipping test");
-            return;
-        }
-        test.doTest(prov);
+	List<Provider> providers = Arrays.asList(Security.getProviders());
+	if (prov != null)
+	    providers.add(prov);
+	List<String> failures = new ArrayList<String>();
+	for (Provider p : providers) {
+	    System.err.println("Testing provider: " + p);
+	    if (!test.doTest(p))
+		failures.add(p.getName());
+	}
+	if (failures.size() != 0)
+	    throw new RuntimeException("The following providers failed: " +
+				       failures);
+	System.err.println("All providers passed.");
     }
+
 }
