/*
 * Copyright (C) 2008 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 org.bouncycastle.crypto.digests;

import junit.framework.TestCase;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.ExtendedDigest;

/**
 * Implements unit tests for our JNI wrapper around OpenSSL. We use the
 * existing Bouncy Castle implementation as our test oracle.
 */
public class DigestTest extends TestCase {

    /**
     * Processes the two given message digests for the same data and checks
     * the results. Requirement is that the results must be equal, the digest
     * implementations must have the same properties, and the new implementation
     * must be faster than the old one.
     *
     * @param oldDigest The old digest implementation, provided by Bouncy Castle
     * @param newDigest The new digest implementation, provided by OpenSSL
     */
    public void doTestMessageDigest(Digest oldDigest, Digest newDigest) {
        final int ITERATIONS = 10;

        byte[] data = new byte[1024];

        byte[] oldHash = new byte[oldDigest.getDigestSize()];
        byte[] newHash = new byte[newDigest.getDigestSize()];

        assertEquals("Hash names must be equal",
                     oldDigest.getAlgorithmName(), newDigest.getAlgorithmName());
        assertEquals("Hash sizes must be equal",
                     oldHash.length, newHash.length);
        assertEquals("Hash block sizes must be equal",
                     ((ExtendedDigest)oldDigest).getByteLength(),
                     ((ExtendedDigest)newDigest).getByteLength());
        for (int i = 0; i < data.length; i++) {
            data[i] = (byte)i;
        }

        long oldTime = 0;
        long newTime = 0;

        for (int j = 0; j < ITERATIONS; j++) {
            long t0 = System.currentTimeMillis();
            for (int i = 0; i < 4; i++) {
                oldDigest.update(data, 0, data.length);
            }
            int oldLength = oldDigest.doFinal(oldHash, 0);
            long t1 = System.currentTimeMillis();

            oldTime = oldTime + (t1 - t0);

            long t2 = System.currentTimeMillis();
            for (int i = 0; i < 4; i++) {
                newDigest.update(data, 0, data.length);
            }
            int newLength = newDigest.doFinal(newHash, 0);
            long t3 = System.currentTimeMillis();

            newTime = newTime + (t3 - t2);

            assertEquals("Hash sizes must be equal", oldLength, newLength);

            for (int i = 0; i < oldLength; i++) {
                assertEquals("Hashes[" + i + "] must be equal", oldHash[i], newHash[i]);
            }
        }

        System.out.println("Time for " + ITERATIONS + " x old hash processing: " + oldTime + " ms");
        System.out.println("Time for " + ITERATIONS + " x new hash processing: " + newTime + " ms");

        assertTrue("New hash should be faster", newTime < oldTime);
    }

    /**
     * Tests the MD5 implementation.
     */
    public void testMD5() {
        Digest oldDigest = new MD5Digest();
        Digest newDigest = new OpenSSLDigest.MD5();
        doTestMessageDigest(oldDigest, newDigest);
    }

    /**
     * Tests the SHA-1 implementation.
     */
    public void testSHA1() {
        Digest oldDigest = new SHA1Digest();
        Digest newDigest = new OpenSSLDigest.SHA1();
        doTestMessageDigest(oldDigest, newDigest);
    }

    /**
     * Tests the SHA-256 implementation.
     */
    public void testSHA256() {
        Digest oldDigest = new SHA256Digest();
        Digest newDigest = new OpenSSLDigest.SHA256();
        doTestMessageDigest(oldDigest, newDigest);
    }

    /**
     * Tests the SHA-384 implementation.
     */
    public void testSHA384() {
        Digest oldDigest = new SHA384Digest();
        Digest newDigest = new OpenSSLDigest.SHA384();
        doTestMessageDigest(oldDigest, newDigest);
    }

    /**
     * Tests the SHA-512 implementation.
     */
    public void testSHA512() {
        Digest oldDigest = new SHA512Digest();
        Digest newDigest = new OpenSSLDigest.SHA512();
        doTestMessageDigest(oldDigest, newDigest);
    }
}
