8050370: Need new regressions tests for messageDigest with DigestIOStream
authorweijun
Tue, 26 Aug 2014 15:10:29 +0800
changeset 26203 0030579ec361
parent 26202 6f45f1d6688a
child 26204 77df35747ce7
8050370: Need new regressions tests for messageDigest with DigestIOStream Reviewed-by: weijun Contributed-by: Zaiyao Liu <zaiyao.liu@oracle.com>
jdk/test/java/security/MessageDigest/TestDigestIOStream.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/MessageDigest/TestDigestIOStream.java	Tue Aug 26 15:10:29 2014 +0800
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.security.DigestInputStream;
+import java.security.DigestOutputStream;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.Random;
+import static java.lang.System.out;
+
+/**
+ * @test
+ * @bug 8050370
+ * @summary MessageDigest tests with DigestIOStream
+ * @author Kevin Liu
+ */
+
+enum ReadModel {
+    READ, BUFFER_READ, MIX_READ
+}
+
+public class TestDigestIOStream {
+
+    private static final int[] DATA_LEN_ARRAY = {
+        1, 50, 2500, 125000, 6250000
+    };
+    private static final String[] ALGORITHM_ARRAY = {
+        "MD2", "MD5", "SHA1", "SHA-224", "SHA-256", "SHA-384", "SHA-512"
+    };
+
+    private static byte[] data;
+
+    private static MessageDigest md = null;
+
+    public static void main(String argv[]) throws Exception {
+        TestDigestIOStream test = new TestDigestIOStream();
+        test.run();
+    }
+
+    public void run() throws Exception {
+        for (String algorithm: ALGORITHM_ARRAY) {
+
+            md = MessageDigest.getInstance(algorithm);
+
+            for (int length: DATA_LEN_ARRAY) {
+
+                Random rdm = new Random();
+                data = new byte[length];
+                rdm.nextBytes(data);
+
+                if (!testMDChange(algorithm, length)) {
+                    throw new RuntimeException("testMDChange failed at:"
+                            + algorithm + "/" + length);
+                }
+                if (!testMDShare(algorithm, length)) {
+                    throw new RuntimeException("testMDShare failed at:"
+                            + algorithm + "/" + length);
+                }
+                for (ReadModel readModel: ReadModel.values()) {
+                    // test Digest function when digest switch on
+                    if (!testDigestOnOff(algorithm, readModel, true, length)) {
+                        throw new RuntimeException("testDigestOn failed at:"
+                                + algorithm + "/" + length + "/" + readModel);
+                    }
+                    // test Digest function when digest switch off
+                    if (!testDigestOnOff(algorithm, readModel, false, length)) {
+                        throw new RuntimeException("testDigestOff failed at:"
+                                + algorithm + "/" + length + "/" + readModel);
+                    }
+                }
+            }
+        }
+        int testNumber = ALGORITHM_ARRAY.length * ReadModel.values().length
+                * DATA_LEN_ARRAY.length * 2 + ALGORITHM_ARRAY.length
+                * DATA_LEN_ARRAY.length * 2;
+        out.println("All " + testNumber + " Tests Passed");
+    }
+
+    /**
+     * Test DigestInputStream and DigestOutputStream digest function when digest
+     * set on and off
+     *
+     * @param algo
+     *            Message Digest algorithm
+     * @param readModel
+     *            which read method used(READ, BUFFER_READ, MIX_READ)
+     * @param on
+     *            digest switch(on and off)
+     * @param dataLength
+     *            plain test data length.
+     * @exception Exception
+     *                throw unexpected exception
+     */
+    public boolean testDigestOnOff(String algo, ReadModel readModel,
+            boolean on, int dataLength) throws Exception {
+
+        // Generate the DigestInputStream/DigestOutputStream object
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+                DigestInputStream dis = new DigestInputStream(bais,
+                        MessageDigest.getInstance(algo));
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                DigestOutputStream dos = new DigestOutputStream(baos,
+                        MessageDigest.getInstance(algo));
+                ByteArrayOutputStream baOut = new ByteArrayOutputStream();) {
+
+            // Perform the update using all available/possible update methods
+            int k = 0;
+            byte[] buffer = new byte[5];
+            boolean enDigest = true;
+            // Make sure the digest function is on (default)
+            dis.on(enDigest);
+            dos.on(enDigest);
+
+            switch (readModel) {
+            case READ: // use only read()
+                while ((k = dis.read()) != -1) {
+                    if (on) {
+                        dos.write(k);
+                    } else {
+                        dos.write(k);
+                        if (enDigest) {
+                            baOut.write(k);
+                        }
+                        enDigest = !enDigest;
+                        dos.on(enDigest);
+                        dis.on(enDigest);
+                    }
+                }
+                break;
+            case BUFFER_READ: // use only read(byte[], int, int)
+                while ((k = dis.read(buffer, 0, buffer.length)) != -1) {
+                    if (on) {
+                        dos.write(buffer, 0, k);
+                    } else {
+                        dos.write(buffer, 0, k);
+                        if (enDigest) {
+                            baOut.write(buffer, 0, k);
+                        }
+                        enDigest = !enDigest;
+                        dis.on(enDigest);
+                        dos.on(enDigest);
+                    }
+                }
+                break;
+            case MIX_READ: // use both read() and read(byte[], int, int)
+                while ((k = dis.read()) != -1) {
+                    if (on) {
+                        dos.write(k);
+                        if ((k = dis.read(buffer, 0, buffer.length)) != -1) {
+                            dos.write(buffer, 0, k);
+                        }
+                    } else {
+                        dos.write(k);
+                        if (enDigest) {
+                            baOut.write(k);
+                        }
+                        enDigest = !enDigest;
+                        dis.on(enDigest);
+                        dos.on(enDigest);
+                        if ((k = dis.read(buffer, 0, buffer.length)) != -1) {
+                            dos.write(buffer, 0, k);
+                            if (enDigest) {
+                                baOut.write(buffer, 0, k);
+                            }
+                            enDigest = !enDigest;
+                            dis.on(enDigest);
+                            dos.on(enDigest);
+                        }
+                    }
+                }
+                break;
+            default:
+                out.println("ERROR: Invalid read/write combination choice!");
+                return false;
+            }
+
+            // Get the output and the "correct" digest values
+            byte[] output1 = dis.getMessageDigest().digest();
+            byte[] output2 = dos.getMessageDigest().digest();
+            byte[] standard;
+            if (on) {
+                standard = md.digest(data);
+            } else {
+                byte[] dataDigested = baOut.toByteArray();
+                standard = md.digest(dataDigested);
+            }
+
+            // Compare the output byte array value to the input data
+            if (!MessageDigest.isEqual(data, baos.toByteArray())) {
+                out.println("ERROR of " + readModel
+                        + ": output and input data unexpectedly changed");
+                return false;
+            }
+            // Compare generated digest values
+            if (!MessageDigest.isEqual(output1, standard)
+                    || !MessageDigest.isEqual(output2, standard)) {
+                out.println("ERROR" + readModel
+                        + ": generated digest data unexpectedly changed");
+                return false;
+            }
+
+            return true;
+        } catch (Exception ex) {
+            out.println("testDigestOnOff failed at:" + algo + "/" + readModel
+                    + "/" + dataLength + " with unexpected exception");
+            throw ex;
+        }
+    }
+
+    /**
+     * Test DigestInputStream and DigestOutputStream digest function when Swap
+     * the message digest engines between DigestIn/OutputStream
+     *
+     * @param algo
+     *            Message Digest algorithm
+     * @param dataLength
+     *            plain test data length.
+     * @exception Exception
+     *                throw unexpected exception
+     */
+    public boolean testMDChange(String algo, int dataLength) throws Exception {
+        // Generate the DigestInputStream/DigestOutputStream object
+        MessageDigest mdIn = MessageDigest.getInstance(algo);
+        MessageDigest mdOut = MessageDigest.getInstance(algo);
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+                DigestInputStream dis = new DigestInputStream(bais, mdIn);
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                DigestOutputStream dos = new DigestOutputStream(baos, mdOut);) {
+
+            // Perform the update using all available/possible update methods
+            int k = 0;
+            byte[] buffer = new byte[10];
+
+            // use both read() and read(byte[], int, int)
+            while ((k = dis.read()) != -1) {
+                dos.write(k);
+                if ((k = dis.read(buffer, 0, buffer.length)) != -1) {
+                    dos.write(buffer, 0, k);
+                }
+
+                // Swap the message digest engines between
+                // DigestIn/OutputStream objects
+                dis.setMessageDigest(mdOut);
+                dos.setMessageDigest(mdIn);
+                mdIn = dis.getMessageDigest();
+                mdOut = dos.getMessageDigest();
+            }
+
+            // Get the output and the "correct" digest values
+            byte[] output1 = mdIn.digest();
+            byte[] output2 = mdOut.digest();
+            byte[] standard = md.digest(data);
+
+            // Compare generated digest values
+            return MessageDigest.isEqual(output1, standard)
+                    && MessageDigest.isEqual(output2, standard);
+        } catch (Exception ex) {
+            out.println("testMDChange failed at:" + algo + "/" + dataLength
+                    + " with unexpected exception");
+            throw ex;
+        }
+    }
+
+    /**
+     * Test DigestInputStream and DigestOutputStream digest function when use
+     * same message digest object.
+     *
+     * @param algo
+     *            Message Digest algorithm
+     * @param dataLength
+     *            plain test data length.
+     * @exception Exception
+     *                throw unexpected exception
+     */
+    public boolean testMDShare(String algo, int dataLength) throws Exception {
+        MessageDigest mdCommon = MessageDigest.getInstance(algo);
+        // Generate the DigestInputStream/DigestOutputStream object
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(data);
+                DigestInputStream dis = new DigestInputStream(bais, mdCommon);
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                DigestOutputStream dos = new DigestOutputStream(baos, mdCommon);) {
+
+            // Perform the update using all available/possible update methods
+            int k = 0;
+            byte[] buffer = new byte[10];
+
+            // use both read() and read(byte[], int, int)
+            while (k < data.length) {
+                int len = dis.read(buffer, 0, buffer.length);
+                if (len != -1) {
+                    k += len;
+                    if (k < data.length) {
+                        dos.write(data[k]);
+                        k++;
+                        dis.skip(1);
+                    }
+                }
+            }
+
+            // Get the output and the "correct" digest values
+            byte[] output = mdCommon.digest();
+            byte[] standard = md.digest(data);
+
+            // Compare generated digest values
+            return MessageDigest.isEqual(output, standard);
+        } catch (Exception ex) {
+            out.println("TestMDShare failed at:" + algo + "/" + dataLength
+                    + " with unexpected exception");
+            throw ex;
+        }
+    }
+}