/*
 * TLSH is provided for use under two licenses: Apache OR BSD.
 * Users may opt to use either license depending on the license
 * restictions of the systems with which they plan to integrate
 * the TLSH code.
 */

/* ==============
 * Apache License
 * ==============
 * Copyright 2017 Trend Micro Incorporated
 *
 * 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.
 */

/* ===========
 * BSD License
 * ===========
 * Copyright (c) 2017, Trend Micro Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.

 * 3. Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.trendmicro.tlsh;

import java.security.SecureRandom;

import org.junit.Test;

/**
 * Some methods to see the performance of the TLSH implementation.
 *
 */
public class TlshPerformanceTests {
	// TODO: This kind of micro-benchmarking is probably better done
	// in a framework like JMH

    /**
     * Attempt to test the performance of the getHash method
     */
    //@Test
    public void test_performance_getHash()  {
    		TlshCreator tlsh = new TlshCreator();
    		byte[] b = new byte[TlshCreator.MIN_DATA_LENGTH];
    		new SecureRandom().nextBytes(b);
    		
    		final int numIters = 250000;
    		long start = System.nanoTime();
    		for (int i = 0; i < numIters; ++i) {
    			tlsh.update(b);
    			tlsh.getHash(false);
    			tlsh.reset();
    		}
    		long end = System.nanoTime();
    		long diff = end-start;
    		long timePerIter = diff/numIters;
    		System.out.println("It took " + (diff)/1000000 + "ms to run " + numIters + " iterations, for " + timePerIter + "ns/call");
    		
    }

    //@Test
    public void test_performance_update_128_1()  {
    		test_performance_update(BucketOption.BUCKETS_128, ChecksumOption.CHECKSUM_1B);
    }

    //@Test
    public void test_performance_update_128_3()  {
    		test_performance_update(BucketOption.BUCKETS_128, ChecksumOption.CHECKSUM_3B);
    }

    //@Test
    public void test_performance_update_256_1()  {
    		test_performance_update(BucketOption.BUCKETS_256, ChecksumOption.CHECKSUM_1B);
    }

    @Test
    public void test_performance_update_256_3()  {
    		test_performance_update(BucketOption.BUCKETS_256, ChecksumOption.CHECKSUM_3B);
    }

	/**
     * Attempt to test the performance of the update method
     */
    private void test_performance_update(BucketOption bucketOption, ChecksumOption checksumOption)  {
    		TlshCreator tlsh = new TlshCreator(bucketOption, checksumOption);
    		byte[] b = new byte[16384];
    		new SecureRandom().nextBytes(b);
    		
    		final int numIters = 10000;
    		long start = System.nanoTime();
    		for (int i = 0; i < numIters; ++i) {
    			tlsh.update(b);
    		}
    		long end = System.nanoTime();
    		tlsh.getHash(false);
    		long diff = end-start;
    		long totalHashed = (long)numIters*b.length;
		System.out.format("With %d buckets and %d byte checksum it took %,dms to hash %,d bytes, for %,d bytes hashed/s\n",
				bucketOption.getBucketCount(), checksumOption.getChecksumLength(), (diff) / 1000000, totalHashed,
				(totalHashed * 1000000000L) / (diff));
    		
    }


}
