package com.limegroup.gnutella.connection;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.*;
import java.util.zip.*;
import java.net.*;
import junit.framework.Test;
import com.limegroup.gnutella.util.*;
/**
* Tests that DeflaterWriter deflates data written to it correctly,
* passing it on to the source channel.
*/
public final class DeflaterWriterTest extends BaseTestCase {
private Deflater DEFLATER = new Deflater();
private WriteBufferChannel SINK = new WriteBufferChannel(1024 * 1024);
private DeflaterWriter WRITER = new DeflaterWriter(DEFLATER, SINK);
private static Random RND = new Random();
private WriteBufferChannel SOURCE = new WriteBufferChannel(WRITER);
private Inflater INFLATER = new Inflater();
public DeflaterWriterTest(String name) {
super(name);
}
public static Test suite() {
return buildTestSuite(DeflaterWriterTest.class);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(suite());
}
public void tearDown() {
DEFLATER.end();
INFLATER.end();
}
public void testSimpleDeflation() throws Exception {
byte[] data = data(10 * 1024);
SOURCE.setBuffer(buffer(data));
assertFalse(WRITER.handleWrite()); // should have been able to write everything.
ByteBuffer deflated = SINK.getBuffer();
assertGreaterThan(0, deflated.limit());
byte[] inflated = inflate(deflated);
assertEquals(data, inflated);
}
public void testSourceEmptiesAndFillsRepeatedly() throws Exception {
byte[] data = data(3 * 1024);
SOURCE.setBuffer(buffer(data));
assertFalse(WRITER.handleWrite()); // should have been able to write everything.
ByteBuffer deflated = SINK.getBuffer();
assertGreaterThan(0, deflated.limit());
byte[] inflated = inflate(deflated);
assertEquals(data, inflated);
SINK.clear();
data = data(8 * 1024 + 127);
SOURCE.setBuffer(buffer(data));
assertFalse(WRITER.handleWrite());
deflated = SINK.getBuffer();
assertGreaterThan(0, deflated.limit());
inflated = inflate(deflated);
assertEquals(data, inflated);
SINK.clear();
data = data(123615);
SOURCE.setBuffer(buffer(data));
assertFalse(WRITER.handleWrite());
deflated = SINK.getBuffer();
assertGreaterThan(0, deflated.limit());
inflated = inflate(deflated);
assertTrue(Arrays.equals(data, inflated));
assertEquals(data, inflated);
}
public void testSinkFillsAndEmptiesRepeatedly() throws Exception {
byte[] data = data(52 * 1024);
ByteBuffer compare = ByteBuffer.wrap(data);
ByteBuffer out = ByteBuffer.allocate(data.length);
SOURCE.setBuffer(buffer(data));
SINK.resize(100);
assertTrue(WRITER.handleWrite()); // still data to write.
ByteBuffer deflated = SINK.getBuffer();
assertGreaterThan(0, deflated.limit());
byte[] inflated = inflate(deflated);
assertGreaterThan(0, inflated.length);
int position = 0;
int limit = inflated.length + position;
assertEquals(compare.limit(limit).position(position), buffer(inflated));
out.put(inflated);
assertEquals(out.position(), compare.limit());
SINK.resize(5000);
assertTrue(WRITER.handleWrite()); // still data to write.
deflated = SINK.getBuffer();
assertGreaterThan(0, deflated.limit());
inflated = inflate(deflated);
assertGreaterThan(0, inflated.length);
position = compare.limit();
limit = inflated.length + position;
assertEquals(compare.limit(limit).position(position), buffer(inflated));
out.put(inflated);
assertEquals(out.position(), compare.limit());
SINK.resize(13535);
assertTrue(WRITER.handleWrite()); // still data to write.
deflated = SINK.getBuffer();
assertGreaterThan(0, deflated.limit());
inflated = inflate(deflated);
assertGreaterThan(0, inflated.length);
position = compare.limit();
limit = inflated.length + position;
assertEquals(compare.limit(limit).position(position), buffer(inflated));
out.put(inflated);
assertEquals(out.position(), compare.limit());
SINK.resize(data.length * 2); // top it off.
assertFalse(WRITER.handleWrite()); // nothing left to write.
deflated = SINK.getBuffer();
assertGreaterThan(0, deflated.limit());
inflated = inflate(deflated);
assertGreaterThan(0, inflated.length);
position = compare.limit();
limit = inflated.length + position;
assertEquals(compare.limit(limit).position(position), buffer(inflated));
out.put(inflated);
assertEquals(out.position(), compare.limit());
assertEquals(buffer(data), out.flip());
}
private byte[] data(int size) {
byte[] data = new byte[size];
// for(int i = 0; i < size; i++)
// data[i] = (byte)(i % 10);
RND.nextBytes(data);
return data;
}
private ByteBuffer buffer(byte[] data) {
return ByteBuffer.wrap(data);
}
private byte[] inflate(ByteBuffer data) throws Exception {
INFLATER.setInput(data.array(), 0, data.limit());
byte[] buf = new byte[512];
ByteArrayOutputStream out = new BufferByteArrayOutputStream();
int inflated = 0;
while( (inflated = INFLATER.inflate(buf)) > 0)
out.write(buf, 0, inflated);
return out.toByteArray();
}
}