/******************************************************************************* t * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.fastlz; import static org.junit.Assert.fail; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; import junit.framework.Assert; import org.junit.BeforeClass; import org.junit.Test; /** * @author Tuukka Lehtonen */ @SuppressWarnings("deprecation") public class FastLZBasicTests { static File testData1; static File testData2; static File testDataPrime; @BeforeClass public static void initialize() throws IOException { FastLZ.initialize(null); testData1 = new File("uncompressed.data"); writeTestData(testData1, 10000000); testData2 = new File("uncompressed-small.data"); writeTestData(testData2, 100000); testDataPrime = new File("uncompressed-prime.data"); writeTestData(testDataPrime, 1000); System.out.println("test data directory: " + testData1.getAbsolutePath()); // File javaFlz = new File("compressed-prime.data.native.flz"); // for (int i = 0; i < 100; ++i) { // compressFlzJava(testDataPrime, javaFlz); // } } @Test public void validateCompress() throws IOException { validateCompress(testData1); } private void validateCompress(File testData) throws IOException { System.out.println("==== validateCompress(" + testData.getName() + ") ===="); File nativeFlz = new File("compressed.data.native.flz"); long nativeCompressedSize = compressFlzNative(testData, nativeFlz); System.out.println("native compressed size: " + nativeCompressedSize); // Need to prime JVM JIT by performing multiple passes File javaFlz = new File("compressed.data.java.flz"); long javaCompressedSize = compressFlzJava(testData, javaFlz); System.out.println("java compressed size: " + javaCompressedSize); Assert.assertEquals(nativeCompressedSize, javaCompressedSize); System.out.println("Comparing compressed outputs..."); compareFiles(nativeFlz, javaFlz); System.out.println("Compressed outputs match."); File decompressedNativeFlz = new File("decompressed.data.native.flz"); File decompressedJavaFlz = new File("decompressed.data.java.flz"); decompressFlzNative(nativeFlz, decompressedNativeFlz); decompressFlzNative(javaFlz, decompressedJavaFlz); compareFiles(decompressedJavaFlz, decompressedNativeFlz); compareFiles(decompressedNativeFlz, testData); } // @Test // public void validateCompressSmall() throws IOException { // File nativeFlz = new File("compressed-small.data.native.flz"); // long nativeCompressedSize = compressFlzNative(testData2, nativeFlz); // System.out.println("native compressed size: " + nativeCompressedSize); // // // Need to prime JVM JIT by performing multiple passes // File javaFlz = new File("compressed-small.data.java.flz"); // long javaCompressedSize = compressFlzJava(testData2, javaFlz); // System.out.println("java compressed size: " + javaCompressedSize); // // Assert.assertEquals(nativeCompressedSize, javaCompressedSize); // // System.out.println("Comparing compressed outputs..."); // compareFiles(nativeFlz, javaFlz); // System.out.println("Compressed outputs match."); // } // @Test // public void testNativeCompressPerformance() throws IOException { // File javaFlz = new File("compressed.data.native.flz"); // for (int i = 0; i < 5; ++i) { // compressFlzNative(testData1, javaFlz); // } // } // // @Test // public void testJavaCompressPerformance() throws IOException { // // Need to prime JVM JIT by performing multiple passes // File javaFlz = new File("compressed.data.java.flz"); // for (int i = 0; i < 5; ++i) { // compressFlzJava(testData1, javaFlz); // } // } // @Test // public void testCompressNative() throws IOException { // File flz = new File("compressed.data.native.flz"); // for (int i = 0; i < 5; ++i) { // long compressedSize = compressFlzNative(testData1, flz); // System.out.println("native compressed size: " + compressedSize); // } // } // // @Test // public void testCompressionJava() throws IOException { // // Need to prime JVM JIT by performing multiple passes // File flz = new File("compressed.data.java.flz"); // for (int i = 0; i < 5; ++i) { // long compressedSize = compressFlzJava(testData1, flz); // System.out.println("java compressed size: " + compressedSize); // } // } @SuppressWarnings("unused") @Test public void testDecompress() throws IOException { File nativeFlz = new File("compressed.data.native.flz"); long nativeCompressedSize = compressFlzNative(testData1, nativeFlz); System.out.println("native compressed size: " + nativeCompressedSize); // Need to prime JVM JIT by performing multiple passes File javaFlz = new File("compressed.data.java.flz"); long javaCompressedSize = compressFlzJava(testData1, javaFlz); System.out.println("java compressed size: " + javaCompressedSize); Assert.assertEquals(nativeCompressedSize, javaCompressedSize); System.out.println("Comparing compressed outputs..."); compareFiles(nativeFlz, javaFlz); System.out.println("Compressed outputs match."); File java1 = new File("java-compressed.data.decompressed-with-native"); long nativeDecompressedSize = decompressFlzNative(javaFlz, java1); System.out.println("Comparing native-decompressed output..."); compareFiles(testData1, java1); System.out.println("Native-decompressed output matches original."); File java2 = new File("java-compressed.data.decompressed-with-java"); long javaDecompressedSize = decompressFlzJava(javaFlz, java2); System.out.println("Comparing java-decompressed output..."); compareFiles(testData1, java2); System.out.println("Java-decompressed output matches original."); for (int i = 0; i < 5; ++i) decompressFlz(javaFlz, FastLZ.read(javaFlz), java1, NullOutputStream.INSTANCE); for (int i = 0; i < 5; ++i) decompressFlz(javaFlz, FastLZJava.read(javaFlz), java2, NullOutputStream.INSTANCE); } @Test public void testDecompressCluster() { fail("Not yet implemented"); } static void compareFiles(File file1, File file2) throws IOException { InputStream in1 = new BufferedInputStream(new FileInputStream(file1)); InputStream in2 = new BufferedInputStream(new FileInputStream(file2)); try { int offset = 0; while (true) { int b1 = in1.read(); int b2 = in2.read(); if (b1 == -1 && b2 == -1) return; if (b1 == -1) fail("EOF reached in file1 " + file1.getName() + " but not in file2 " + file2.getName()); if (b2 == -1) fail("EOF reached in file1 " + file1.getName() + " but not in file2 " + file2.getName()); if (b1 != b2) fail("bytes at offset " + offset + " do not match: " + b1 + " vs. " + b2); ++offset; } } finally { in1.close(); in2.close(); } } public static void writeTestData(File file, int rows) throws IOException { if (file.exists()) return; System.out.println("writing test data..."); OutputStream stream = new FileOutputStream(file); for (int i = 0; i < rows; ++i) stream.write((Integer.toString(i) + "\n").getBytes()); stream.close(); System.out.println("wrote " + file.length() + " bytes of test data."); } /** * @param source * @param flz * @return compressed size in bytes * @throws IOException */ static long compressFlzJava(File source, File flz) throws IOException { return compressFlz(source, flz, FastLZJava.write(flz)); } /** * @param source * @param flz * @return compressed size in bytes * @throws IOException */ static long compressFlzNative(File source, File flz) throws IOException { return compressFlz(source, flz, FastLZ.write(flz)); } /** * @param source * @param flz * @return compressed size in bytes * @throws IOException */ static long compressFlz(File source, File flz, OutputStream flzOutput) throws IOException { System.out.println("compressFlz(" + source + ", " + flz + ")"); InputStream input = new BufferedInputStream(new FileInputStream(source)); copy(input, flzOutput); input.close(); flzOutput.close(); long compressed = flz.length(); System.out.println("Wrote " + compressed + " compressed bytes"); return compressed; } /** * @param source * @param flz * @return compressed size in bytes * @throws IOException */ static long decompressFlzJava(File flz, File dest) throws IOException { return decompressFlz(flz, FastLZJava.read(flz), dest); } /** * @param source * @param flz * @return compressed size in bytes * @throws IOException */ static long decompressFlzNative(File flz, File dest) throws IOException { return decompressFlz(flz, FastLZ.read(flz), dest); } /** * @param source * @param flz * @return compressed size in bytes * @throws IOException */ static long decompressFlz(File source, InputStream flzInput, File dest) throws IOException { System.out.println("decompressFlz(" + source + ", " + dest + ")"); OutputStream output = new BufferedOutputStream(new FileOutputStream(dest)); copy(flzInput, output); flzInput.close(); output.close(); long decompressed = dest.length(); System.out.println("Wrote " + decompressed + " decompressed bytes"); return decompressed; } /** * @param source * @param flz * @return compressed size in bytes * @throws IOException */ static long decompressFlz(File source, InputStream flzInput, File dest, OutputStream destStream) throws IOException { System.out.println("decompressFlz(" + source + ", " + dest + ")"); copy(flzInput, destStream); flzInput.close(); destStream.close(); long decompressed = dest.length(); System.out.println("Wrote " + decompressed + " decompressed bytes"); return decompressed; } /** * Copy the content of the input stream into the output stream, using a temporary * byte array buffer whose size is defined by {@link #IO_BUFFER_SIZE}. * * @param in The input stream to copy from. * @param out The output stream to copy to. * * @throws IOException If any error occurs during the copy. */ private static final int IO_BUFFER_SIZE = 128 * 1024; public static long copy(InputStream in, OutputStream out) throws IOException { byte[] b = new byte[IO_BUFFER_SIZE]; int read; long total = 0; long start = System.nanoTime(); while (true) { read = in.read(b); if (read < 0) break; total += read; //System.out.println("read " + read + " bytes, " + total + " bytes in total"); out.write(b, 0, read); } long end = System.nanoTime(); double totalmb = total/(1024.0*1024.0); double time = (end-start)*1e-9; double rate = totalmb / time; System.out.format("Transferred %d bytes (%.3f Mbytes) in %f seconds (%.3f MB/s)\n", total, totalmb, time, rate); return total; } @SuppressWarnings("unused") private boolean checksumsEqual(File f1, File f2) throws IOException { byte[] s1 = ChecksumUtil.computeSum(f1); byte[] s2 = ChecksumUtil.computeSum(f2); return Arrays.equals(s1, s2); } }