package com.emc.vipr.transform.compression; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Map; import org.junit.Assume; import org.junit.Before; import org.junit.Test; import SevenZip.Compression.LZMA.Encoder; import com.emc.vipr.transform.TransformConstants; import com.emc.vipr.transform.compression.CompressionTransformFactory.LzmaProfile; public class LZMACompressionFilterTest { byte[] data; /** * @throws java.lang.Exception */ @Before public void setUp() throws Exception { // get some data to compress. InputStream classin = this.getClass().getClassLoader() .getResourceAsStream("uncompressed.txt"); ByteArrayOutputStream classByteStream = new ByteArrayOutputStream(); byte[] buffer = new byte[4096]; int c = 0; while ((c = classin.read(buffer)) != -1) { classByteStream.write(buffer, 0, c); } data = classByteStream.toByteArray(); classin.close(); } @Test public void testCompressMode0() throws Exception { runCompressMode(0); } @Test public void testCompressMode1() throws Exception { runCompressMode(1); } @Test public void testCompressMode2() throws Exception { runCompressMode(2); } @Test public void testCompressMode3() throws Exception { runCompressMode(3); } @Test public void testCompressMode4() throws Exception { runCompressMode(4); } @Test public void testCompressMode5() throws Exception { runCompressMode(5); } @Test public void testCompressMode6() throws Exception { runCompressMode(6); } @Test public void testCompressMode7() throws Exception { runCompressMode(7); } @Test public void testCompressMode8() throws Exception { runCompressMode(8); } @Test public void testCompressMode9() throws Exception { runCompressMode(9); } @Test public void testCustomCompressMode() throws Exception { // Small memory footprint but work harder (max fastBits and 64-bit // matcher) runCompressMode(new LzmaProfile(8 * 1024, 273, Encoder.EMatchFinderTypeBT4)); } @Test public void testCompressionMetadata() throws Exception { LZMACompressionFilter lzma = runCompressMode(new LzmaProfile(16 * 1024, 128, Encoder.EMatchFinderTypeBT2)); Map<String, String> m = lzma.getStreamMetadata(); assertEquals("Uncompressed digest incorrect", "027e997e6b1dfc97b93eb28dc9a6804096d85873", m.get(TransformConstants.META_COMPRESSION_UNCOMP_SHA1)); assertEquals("Compression ratio incorrect", "93.9%", m.get(TransformConstants.META_COMPRESSION_COMP_RATIO)); assertEquals("Uncompressed size incorrect", 2516125, Long.parseLong(m .get(TransformConstants.META_COMPRESSION_UNCOMP_SIZE))); assertEquals("Compressed size incorrect", 154656, Long.parseLong(m .get(TransformConstants.META_COMPRESSION_COMP_SIZE))); } private void runCompressMode(int i) throws IOException { System.out.println("Testing compression level " + i); long requiredMemory = CompressionTransformFactory.memoryRequiredForLzma(i); System.out.println("Estimated memory usage: " + (requiredMemory / (1024 * 1024)) + "MB"); // Make sure there's enough RAM otherwise skip. Runtime.getRuntime().gc(); long startMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); long availableMemory = Runtime.getRuntime().maxMemory() - startMemory; Assume.assumeTrue( "Skipping test because there is not enough available heap", availableMemory > requiredMemory); long now = System.currentTimeMillis(); ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in = new ByteArrayInputStream(data); LZMACompressionFilter filter = new LZMACompressionFilter(in, i); byte[] buffer = new byte[4096]; int c = 0; while((c = filter.read(buffer)) != -1) { out.write(buffer, 0, c); } out.close(); long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() - startMemory; System.out.println("Memory used: " + (usedMemory / (1024 * 1024)) + "MB"); filter.close(); byte[] compressed = out.toByteArray(); System.out.println(String.format( "Original size: %d Compressed size: %d", data.length, compressed.length)); System.out.println("Compression Ratio: " + (100 - (compressed.length * 100 / data.length)) + "%"); System.out .println("Time: " + (System.currentTimeMillis() - now) + "ms"); assertTrue("compressed data not smaller than original for level " + i, compressed.length < data.length); } private LZMACompressionFilter runCompressMode(LzmaProfile profile) throws IOException { System.out.println("Testing custom profile"); long requiredMemory = CompressionTransformFactory.memoryRequiredForLzma(profile); System.out.println("Estimated memory usage: " + (requiredMemory / (1024 * 1024)) + "MB"); // Make sure there's enough RAM otherwise skip. Runtime.getRuntime().gc(); long startMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); long availableMemory = Runtime.getRuntime().maxMemory() - startMemory; Assume.assumeTrue( "Skipping test because there is not enough available heap", availableMemory > requiredMemory); long now = System.currentTimeMillis(); ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayInputStream in = new ByteArrayInputStream(data); LZMACompressionFilter filter = new LZMACompressionFilter(in, profile); byte[] buffer = new byte[4096]; int c = 0; while((c = filter.read(buffer)) != -1) { out.write(buffer, 0, c); } out.close(); long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() - startMemory; System.out.println("Memory used: " + (usedMemory / (1024 * 1024)) + "MB"); filter.close(); byte[] compressed = out.toByteArray(); System.out.println(String.format( "Original size: %d Compressed size: %d", data.length, compressed.length)); System.out.println("Compression Ratio: " + (100 - (compressed.length * 100 / data.length)) + "%"); System.out .println("Time: " + (System.currentTimeMillis() - now) + "ms"); assertTrue("compressed data not smaller than original", compressed.length < data.length); return filter; } }