/**
*
*/
package com.emc.vipr.transform.compression;
import static org.junit.Assert.*;
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;
/**
* @author cwikj
*
*/
public class LZMAOutputStreamTest {
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 method for
* {@link com.emc.vipr.transform.compression.LZMAOutputStream#memoryRequired(int)}
* .
*/
@Test
public void testMemoryRequiredInt() {
assertEquals(192937984, CompressionTransformFactory.memoryRequiredForLzma(5));
assertEquals(771751936, CompressionTransformFactory.memoryRequiredForLzma(9));
}
/**
* Test method for
* {@link com.emc.vipr.transform.compression.LZMAOutputStream#memoryRequired(com.emc.vipr.transform.compression.LZMAOutputStream.LzmaProfile)}
* .
*/
@Test
public void testMemoryRequiredLzmaProfile() {
assertEquals(0,
CompressionTransformFactory.memoryRequiredForLzma(new LzmaProfile(0, 0, 0)));
assertEquals(6174015488L,
CompressionTransformFactory.memoryRequiredForLzma(new LzmaProfile(
512 * 1024 * 1024, 0, 0)));
}
@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 {
LZMAOutputStream 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();
LZMAOutputStream lout = new LZMAOutputStream(out, i);
lout.write(data);
long usedMemory = Runtime.getRuntime().totalMemory()
- Runtime.getRuntime().freeMemory() - startMemory;
System.out.println("Memory used: " + (usedMemory / (1024 * 1024))
+ "MB");
lout.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 LZMAOutputStream 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();
LZMAOutputStream lout = new LZMAOutputStream(out, profile);
lout.write(data);
long usedMemory = Runtime.getRuntime().totalMemory()
- Runtime.getRuntime().freeMemory() - startMemory;
System.out.println("Memory used: " + (usedMemory / (1024 * 1024))
+ "MB");
lout.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 lout;
}
}