/*
* JBoss, Home of Professional Open Source.
* Copyright 2014 Red Hat, Inc., and individual contributors
* as indicated by the @author tags.
*
* 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.
*/
package io.undertow.websockets.extensions;
import io.undertow.testutils.category.UnitTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import java.util.zip.Deflater;
import java.util.zip.Inflater;
/**
* An auxiliar test class for compression/decompression operations implemented on extensions context.
*
* @author Lucas Ponce
*/
@Category(UnitTest.class)
public class CompressionUtilsTest {
private static Inflater decompress;
private static Deflater compress;
private static byte[] buf = new byte[1024];
@Before
public void setup() throws Exception {
compress = new Deflater(Deflater.BEST_SPEED, true);
decompress = new Inflater(true);
}
@After
public void finish() throws Exception {
compress.end();
decompress.end();
}
@Test
public void testBasicCompressDecompress() throws Exception {
String raw = "Hello";
compress.setInput(raw.getBytes());
compress.finish();
int read = compress.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH);
decompress.setInput(buf, 0, read);
read = decompress.inflate(buf);
Assert.assertEquals("Hello", new String(buf, 0, read, "UTF-8"));
compress.reset();
decompress.reset();
raw = "Hello, World!";
compress.setInput(raw.getBytes());
compress.finish();
read = compress.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH);
decompress.setInput(buf, 0, read);
read = decompress.inflate(buf);
Assert.assertEquals("Hello, World!", new String(buf, 0, read, "UTF-8"));
}
@Test
public void testCompressDecompressByFrames() throws Exception {
String raw = "Hello, World! This is a long input example data with a lot of content for testing";
/*
This test shares same buffer, 0-511 for compress, 512-1023 for decompress
*/
int position1 = 0;
int position2 = 512;
int chunkLength = 10;
// Frame 1
compress.setInput(raw.getBytes(), position1, chunkLength);
int compressed = compress.deflate(buf, 0, 512, Deflater.SYNC_FLUSH);
decompress.setInput(buf, 0, compressed);
int decompressed = decompress.inflate(buf, position2, buf.length - position2);
// Frame 2
position1 += chunkLength;
position2 += decompressed;
compress.setInput(raw.getBytes(), position1, chunkLength);
compressed = compress.deflate(buf, 0, 512, Deflater.NO_FLUSH);
decompress.setInput(buf, 0, compressed);
decompress.finished();
decompressed = decompress.inflate(buf, position2, buf.length - position2);
// Frame 3
position1 += chunkLength;
position2 += decompressed;
compress.setInput(raw.getBytes(), position1, raw.getBytes().length - position1);
compress.finish();
compressed = compress.deflate(buf, 0, 512, Deflater.NO_FLUSH);
decompress.setInput(buf, 0, compressed);
decompressed = decompress.inflate(buf, position2, buf.length - position2);
Assert.assertEquals(raw, new String(buf, 512, position2 + decompressed - 512, "UTF-8"));
}
@Test
public void testCompressByFramesDecompressWhole() throws Exception {
String raw = "Hello, World! This is a long input example data with a lot of content for testing";
byte[] compressed = new byte[raw.length() + 64];
byte[] decompressed = new byte[raw.length()];
int n = 0, total = 0;
// Compress Frame1
compress.setInput(raw.getBytes(), 0, 10);
n = compress.deflate(compressed, 0, compressed.length, Deflater.SYNC_FLUSH);
total += n;
// Compress Frame2
compress.setInput(raw.getBytes(), 10, 10);
n = compress.deflate(compressed, total, compressed.length - total, Deflater.SYNC_FLUSH);
total += n;
// Compress Frame3
compress.setInput(raw.getBytes(), 20, raw.getBytes().length - 20);
n = compress.deflate(compressed, total, compressed.length - total, Deflater.SYNC_FLUSH);
total += n;
// Uncompress
decompress.setInput(compressed, 0, total);
n = decompress.inflate(decompressed, 0, decompressed.length);
Assert.assertEquals(raw, new String(decompressed, 0, n, "UTF-8"));
}
@Test
public void testLongMessage() throws Exception {
int LONG_MSG = 16384;
StringBuilder longMsg = new StringBuilder(LONG_MSG);
byte[] longbuf = new byte[LONG_MSG + 64];
byte[] output = new byte[LONG_MSG];
for (int i = 0; i < LONG_MSG; i++) {
longMsg.append(new Integer(i).toString().charAt(0));
}
String msg = longMsg.toString();
byte[] input = msg.getBytes();
byte[] compressBuf = new byte[LONG_MSG + 64];
byte[] decompressBuf = new byte[LONG_MSG];
compress.setInput(input);
compress.finish();
int read = compress.deflate(compressBuf, 0, compressBuf.length, Deflater.SYNC_FLUSH);
decompress.setInput(compressBuf, 0, read);
read = decompress.inflate(decompressBuf);
Assert.assertEquals(msg, new String(decompressBuf, 0, read, "UTF-8"));
}
@Test
public void testCompressByFramesDecompressWholeLongMessage() throws Exception {
int LONG_MSG = 75 * 1024;
StringBuilder longMsg = new StringBuilder(LONG_MSG);
byte[] longbuf = new byte[LONG_MSG + 64];
byte[] output = new byte[LONG_MSG];
for (int i = 0; i < LONG_MSG; i++) {
longMsg.append(new Integer(i).toString().charAt(0));
}
String msg = longMsg.toString();
byte[] input = msg.getBytes();
/*
Compress in chunks of 1024 bytes
*/
boolean finished = false;
int start = 0;
int end;
int compressed;
int total = 0;
while (!finished) {
end = (start + 1024) < input.length ? 1024 : input.length - start;
compress.setInput(input, start, end);
start += 1024;
finished = start >= input.length;
if (finished) {
compress.finish();
}
compressed = compress.deflate(longbuf, total, longbuf.length - total, Deflater.SYNC_FLUSH);
total += compressed;
}
/*
Decompress whole message
*/
int decompressed = 0;
decompress.setInput(longbuf, 0, total);
decompress.finished();
decompressed = decompress.inflate(output, 0, output.length);
Assert.assertEquals(longMsg.toString(), new String(output, 0, decompressed, "UTF-8"));
}
@Test
public void testEmptyFrames() throws Exception {
decompress.reset();
byte[] compressedFrame1 = { (byte)0xf2, (byte)0x48, (byte)0xcd };
byte[] compressedFrame2 = { (byte)0xc9, (byte)0xc9, (byte)0x07, (byte)0x00 };
byte[] compressedFrame3 = { (byte)0x00, (byte)0x00, (byte)0xff, (byte)0xff };
byte[] output = new byte[1024];
int decompressed = 0;
decompress.setInput(compressedFrame1);
decompressed = decompress.inflate(output, 0, output.length);
Assert.assertEquals(2, decompressed);
Assert.assertEquals("He", new String(output, 0, decompressed, "UTF-8"));
decompress.setInput(compressedFrame2);
decompressed = decompress.inflate(output, 0, output.length);
Assert.assertEquals(3, decompressed);
Assert.assertEquals("llo", new String(output, 0, decompressed, "UTF-8"));
decompress.setInput(compressedFrame3);
decompressed = decompress.inflate(output, 0, output.length);
Assert.assertEquals(0, decompressed);
decompress.setInput(compressedFrame1);
decompressed = decompress.inflate(output, 0, output.length);
Assert.assertEquals(2, decompressed);
Assert.assertEquals("He", new String(output, 0, decompressed, "UTF-8"));
decompress.setInput(compressedFrame2);
decompressed = decompress.inflate(output, 0, output.length);
Assert.assertEquals(3, decompressed);
Assert.assertEquals("llo", new String(output, 0, decompressed, "UTF-8"));
}
@Test
public void testPadding() throws Exception {
String original = "This is a long message - This is a long message - This is a long message";
byte[] compressed = new byte[1024];
int nCompressed;
compress.setInput(original.getBytes());
nCompressed = compress.deflate(compressed, 0, compressed.length, Deflater.SYNC_FLUSH);
/*
Padding
*/
byte[] padding = {0, 0, 0, (byte)0xff, (byte)0xff, 0, 0, 0, (byte)0xff, (byte)0xff, 0, 0, 0, (byte)0xff, (byte)0xff};
int nPadding = padding.length;
for (int i = 0; i < padding.length; i++) {
compressed[nCompressed + i] = padding[i];
}
byte[] uncompressed = new byte[1024];
int nUncompressed;
decompress.setInput(compressed, 0, nCompressed + nPadding);
nUncompressed = decompress.inflate(uncompressed);
Assert.assertEquals(original, new String(uncompressed, 0, nUncompressed, "UTF-8"));
}
}