package com.emc.vipr.transform.compression;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.emc.vipr.transform.TransformConstants;
import com.emc.vipr.transform.TransformConstants.CompressionMode;
import com.emc.vipr.transform.TransformException;
public class CompressionTransformFactoryTest {
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
}
@Test
public void testGetTransformClass() {
CompressionTransformFactory factory = new CompressionTransformFactory();
assertEquals(TransformConstants.COMPRESSION_CLASS, factory.getTransformClass());
}
@Test
public void testGetCompressMode() {
CompressionTransformFactory factory = new CompressionTransformFactory();
//default
assertEquals("default mode incorrect", CompressionMode.Deflate, factory.getCompressMode());
}
@Test
public void testSetCompressMode() {
CompressionTransformFactory factory = new CompressionTransformFactory();
factory.setCompressMode(CompressionMode.LZMA);
assertEquals("mode incorrect", CompressionMode.LZMA, factory.getCompressMode());
}
@Test
public void testGetCompressionLevel() {
CompressionTransformFactory factory = new CompressionTransformFactory();
// default
assertEquals("Default compression level incorrect", 5, factory.getCompressionLevel());
}
@Test
public void testSetCompressionLevel() {
CompressionTransformFactory factory = new CompressionTransformFactory();
for(int i=0; i<10; i++) {
factory.setCompressionLevel(i);
assertEquals("Compression level did not set correctly", i, factory.getCompressionLevel());
}
// Bounds
checkInvalidCompression(factory, CompressionMode.Deflate, -1);
checkInvalidCompression(factory, CompressionMode.LZMA, -1);
checkInvalidCompression(factory, CompressionMode.Deflate, 10);
checkInvalidCompression(factory, CompressionMode.LZMA, 10);
}
private void checkInvalidCompression(CompressionTransformFactory factory, CompressionMode mode, int level) {
factory.setCompressMode(mode);
factory.setCompressionLevel(level);
try {
factory.getOutputTransform(new ByteArrayOutputStream(), new HashMap<String,String>());
fail("invalid compression accepted, mode:" + mode + ", level: " + level);
} catch(Exception e) {
// ignore.
}
}
@Test
public void testGetOutputTransform() throws IOException {
CompressionTransformFactory factory = new CompressionTransformFactory();
CompressionOutputTransform t = factory.getOutputTransform(new ByteArrayOutputStream(), new HashMap<String, String>());
assertNotNull("output transform null", t);
}
@Test
public void testGetInputTransform() throws IOException {
CompressionTransformFactory factory = new CompressionTransformFactory();
byte[] lzmaConfig = new byte[] { 0, 0, 0, 0, 0 };
CompressionInputTransform t = factory.getInputTransform("COMP:LZMA/9", new ByteArrayInputStream(lzmaConfig), new HashMap<String, String>());
assertNotNull("input transform null", t);
}
@Test
public void testCanDecode() {
CompressionTransformFactory factory = new CompressionTransformFactory();
checkDecode(factory, "COMP", "LZMA/9", true);
checkDecode(factory, "COMP", "Deflate/5", true);
// Technically the level parameter is not needed for decode.
checkDecode(factory, "COMP", "Deflate", true);
// Unsupported:
checkDecode(factory, "COMP", "", false);
checkDecode(factory, "COMP", null, false);
checkDecode(factory, "COMP", "BZip2/2", false);
checkDecode(factory, "COMP", "GZ/9", false);
checkDecode(factory, "ENC", "Deflate", false);
checkDecode(factory, "SomethingCrazy", "", false);
checkDecode(factory, "", "", false);
checkDecode(factory, null, null, false);
}
private void checkDecode(CompressionTransformFactory factory, String transformClass, String config, boolean shouldWork) {
if(shouldWork) {
assertTrue("Configuration " + transformClass + "|" + config + " should work", factory.canDecode(transformClass, config, new HashMap<String, String>()));
} else {
assertFalse("Configuration " + transformClass + "|" + config + " should not work", factory.canDecode(transformClass, config, new HashMap<String, String>()));
}
}
// Test getting pull stream in push mode.
@Test(expected=IllegalStateException.class)
public void testWrongMode() throws IOException {
// Test the factory front-to-back.
CompressionTransformFactory factory = new CompressionTransformFactory();
factory.setCompressionLevel(4);
factory.setCompressMode(CompressionMode.LZMA);
ByteArrayOutputStream compressedOutput = new ByteArrayOutputStream();
CompressionOutputTransform outTransform = factory.getOutputTransform(compressedOutput, null);
outTransform.getEncodedInputStream();
}
// Test getting push stream in pull mode.
@Test(expected=IllegalStateException.class)
public void testWrongMode2() throws IOException, TransformException {
// Test the factory front-to-back.
CompressionTransformFactory factory = new CompressionTransformFactory();
factory.setCompressionLevel(4);
factory.setCompressMode(CompressionMode.LZMA);
ByteArrayInputStream compressedInput = new ByteArrayInputStream(new byte[32]);
CompressionOutputTransform outTransform = factory.getOutputTransform(compressedInput, null);
outTransform.getEncodedOutputStream();
}
@Test
public void testEncodeDecodeLzma() throws Exception {
// Test the factory front-to-back.
CompressionTransformFactory factory = new CompressionTransformFactory();
factory.setCompressionLevel(2);
factory.setCompressMode(CompressionMode.LZMA);
// Some generic metadata
Map<String, String> metadata = new HashMap<String, String>();
metadata.put("name1", "value1");
metadata.put("name2", "value2");
// 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);
}
byte[] uncompressedData = classByteStream.toByteArray();
classin.close();
// Compress
ByteArrayOutputStream compressedOutput = new ByteArrayOutputStream();
CompressionOutputTransform outTransform = factory.getOutputTransform(compressedOutput, metadata);
OutputStream outStream = outTransform.getEncodedOutputStream();
assertNotNull(outStream);
outStream.write(uncompressedData);
outStream.close();
Map<String, String> objectData = outTransform.getEncodedMetadata();
assertEquals("Uncompressed digest incorrect", "027e997e6b1dfc97b93eb28dc9a6804096d85873",
objectData.get(TransformConstants.META_COMPRESSION_UNCOMP_SHA1));
assertEquals("Uncompressed size incorrect", 2516125, Long.parseLong(objectData
.get(TransformConstants.META_COMPRESSION_UNCOMP_SIZE)));
assertEquals("Compression ratio incorrect", "95.1%",
objectData.get(TransformConstants.META_COMPRESSION_COMP_RATIO));
assertEquals("Compressed size incorrect", 124271, Long.parseLong(objectData
.get(TransformConstants.META_COMPRESSION_COMP_SIZE)));
assertEquals("name1 incorrect", "value1", objectData.get("name1"));
assertEquals("name2 incorrect", "value2", objectData.get("name2"));
String transformConfig = outTransform.getTransformConfig();
assertEquals("Transform config string incorrect", "COMP:LZMA/2", transformConfig);
// Decompress
ByteArrayInputStream compressedInput = new ByteArrayInputStream(compressedOutput.toByteArray());
CompressionInputTransform inTransform = factory.getInputTransform(transformConfig, compressedInput, objectData);
assertNotNull(inTransform);
InputStream decompressedStream = inTransform.getDecodedInputStream();
assertNotNull(decompressedStream);
byte[] uncompressedData2 = new byte[uncompressedData.length];
c = 0;
while(c < uncompressedData2.length) {
int x = decompressedStream.read(uncompressedData2, c, uncompressedData2.length - c);
if(x == -1) {
break;
}
c += x;
}
assertEquals("stream length incorrect after decompression", uncompressedData.length, c);
assertArrayEquals("data incorrect after decompression", uncompressedData, uncompressedData2);
Map<String, String> decodedMetadata = inTransform.getDecodedMetadata();
// Should be same as above.
assertEquals("Uncompressed digest incorrect", "027e997e6b1dfc97b93eb28dc9a6804096d85873",
decodedMetadata.get(TransformConstants.META_COMPRESSION_UNCOMP_SHA1));
assertEquals("Compression ratio incorrect", "95.1%",
decodedMetadata.get(TransformConstants.META_COMPRESSION_COMP_RATIO));
assertEquals("Uncompressed size incorrect", 2516125, Long.parseLong(decodedMetadata
.get(TransformConstants.META_COMPRESSION_UNCOMP_SIZE)));
assertEquals("Compressed size incorrect", 124271, Long.parseLong(decodedMetadata
.get(TransformConstants.META_COMPRESSION_COMP_SIZE)));
assertEquals("name1 incorrect", "value1", decodedMetadata.get("name1"));
assertEquals("name2 incorrect", "value2", decodedMetadata.get("name2"));
}
@Test
public void testEncodeDecodeDeflate() throws Exception {
// Test the factory front-to-back.
CompressionTransformFactory factory = new CompressionTransformFactory();
factory.setCompressionLevel(8);
factory.setCompressMode(CompressionMode.Deflate);
// Some generic metadata
Map<String, String> metadata = new HashMap<String, String>();
metadata.put("name1", "value1");
metadata.put("name2", "value2");
// 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);
}
byte[] uncompressedData = classByteStream.toByteArray();
classin.close();
// Compress
ByteArrayOutputStream compressedOutput = new ByteArrayOutputStream();
CompressionOutputTransform outTransform = factory.getOutputTransform(compressedOutput, metadata);
OutputStream outStream = outTransform.getEncodedOutputStream();
assertNotNull(outStream);
outStream.write(uncompressedData);
outStream.close();
Map<String, String> objectData = outTransform.getEncodedMetadata();
assertEquals("Uncompressed digest incorrect", "027e997e6b1dfc97b93eb28dc9a6804096d85873",
objectData.get(TransformConstants.META_COMPRESSION_UNCOMP_SHA1));
assertEquals("Compression ratio incorrect", "92.0%",
objectData.get(TransformConstants.META_COMPRESSION_COMP_RATIO));
assertEquals("Uncompressed size incorrect", 2516125, Long.parseLong(objectData
.get(TransformConstants.META_COMPRESSION_UNCOMP_SIZE)));
assertEquals("Compressed size incorrect", 201969, Long.parseLong(objectData
.get(TransformConstants.META_COMPRESSION_COMP_SIZE)));
assertEquals("name1 incorrect", "value1", objectData.get("name1"));
assertEquals("name2 incorrect", "value2", objectData.get("name2"));
String transformConfig = outTransform.getTransformConfig();
assertEquals("Transform config string incorrect", "COMP:Deflate/8", transformConfig);
// Decompress
ByteArrayInputStream compressedInput = new ByteArrayInputStream(compressedOutput.toByteArray());
CompressionInputTransform inTransform = factory.getInputTransform(transformConfig, compressedInput, objectData);
assertNotNull(inTransform);
InputStream decompressedStream = inTransform.getDecodedInputStream();
assertNotNull(decompressedStream);
byte[] uncompressedData2 = new byte[uncompressedData.length];
c = 0;
while(c < uncompressedData2.length) {
int x = decompressedStream.read(uncompressedData2, c, uncompressedData2.length - c);
if(x == -1) {
break;
}
c += x;
}
assertEquals("stream length incorrect after decompression", uncompressedData.length, c);
assertArrayEquals("data incorrect after decompression", uncompressedData, uncompressedData2);
Map<String, String> decodedMetadata = inTransform.getDecodedMetadata();
// Should be same as above.
assertEquals("Uncompressed digest incorrect", "027e997e6b1dfc97b93eb28dc9a6804096d85873",
decodedMetadata.get(TransformConstants.META_COMPRESSION_UNCOMP_SHA1));
assertEquals("Compression ratio incorrect", "92.0%",
decodedMetadata.get(TransformConstants.META_COMPRESSION_COMP_RATIO));
assertEquals("Uncompressed size incorrect", 2516125, Long.parseLong(decodedMetadata
.get(TransformConstants.META_COMPRESSION_UNCOMP_SIZE)));
assertEquals("Compressed size incorrect", 201969, Long.parseLong(decodedMetadata
.get(TransformConstants.META_COMPRESSION_COMP_SIZE)));
assertEquals("name1 incorrect", "value1", decodedMetadata.get("name1"));
assertEquals("name2 incorrect", "value2", decodedMetadata.get("name2"));
}
@Test
public void testGetPriority() {
CompressionTransformFactory factory = new CompressionTransformFactory();
assertEquals("default priority incorrect", 1000, factory.getPriority());
}
@Test
public void testSetPriority() {
CompressionTransformFactory factory = new CompressionTransformFactory();
factory.setPriority(500);
assertEquals("priority incorrect", 500, factory.getPriority());
}
}