/*
* Copyright (C) 2015 SoftIndex LLC.
*
* 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.datakernel.stream.processor;
import io.datakernel.bytebuf.ByteBuf;
import io.datakernel.bytebuf.ByteBufPool;
import io.datakernel.bytebuf.ByteBufQueue;
import io.datakernel.eventloop.Eventloop;
import io.datakernel.stream.StreamConsumers;
import io.datakernel.stream.StreamProducer;
import io.datakernel.stream.StreamProducers;
import io.datakernel.stream.TestStreamConsumers;
import org.junit.Before;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import static io.datakernel.bytebuf.ByteBufPool.*;
import static io.datakernel.eventloop.FatalErrorHandlers.rethrowOnAnyError;
import static io.datakernel.stream.StreamStatus.END_OF_STREAM;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
public class StreamLZ4Test {
private static ByteBuf createRandomByteBuf(Random random) {
int offset = random.nextInt(10);
int tail = random.nextInt(10);
int len = random.nextInt(100);
ByteBuf result = ByteBuf.wrapForWriting(new byte[offset + len + tail]);
int lenUnique = 1 + random.nextInt(len + 1);
result.writePosition(offset);
result.readPosition(offset);
for (int i = 0; i < len; i++) {
result.put((byte) (i % lenUnique));
}
return result;
}
private static byte[] byteBufsToByteArray(List<ByteBuf> byteBufs) {
ByteBufQueue queue = ByteBufQueue.create();
for (ByteBuf buf : byteBufs) {
queue.add(buf.slice());
}
byte[] bytes = new byte[queue.remainingBytes()];
queue.drainTo(bytes, 0, bytes.length);
return bytes;
}
@Before
public void before() {
ByteBufPool.clear();
ByteBufPool.setSizes(0, Integer.MAX_VALUE);
}
@Test
public void test() {
Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
List<ByteBuf> buffers = new ArrayList<>();
Random random = new Random(123456);
int buffersCount = 1000;
for (int i = 0; i < buffersCount; i++) {
buffers.add(createRandomByteBuf(random));
}
byte[] expected = byteBufsToByteArray(buffers);
StreamProducer<ByteBuf> source = StreamProducers.ofIterable(eventloop, buffers);
StreamByteChunker preBuf = StreamByteChunker.create(eventloop, 64, 128);
StreamLZ4Compressor compressor = StreamLZ4Compressor.fastCompressor(eventloop);
StreamByteChunker postBuf = StreamByteChunker.create(eventloop, 64, 128);
StreamLZ4Decompressor decompressor = StreamLZ4Decompressor.create(eventloop);
TestStreamConsumers.TestConsumerToList<ByteBuf> consumer = TestStreamConsumers.toListRandomlySuspending(eventloop);
source.streamTo(preBuf.getInput());
preBuf.getOutput().streamTo(compressor.getInput());
compressor.getOutput().streamTo(postBuf.getInput());
postBuf.getOutput().streamTo(decompressor.getInput());
decompressor.getOutput().streamTo(consumer);
eventloop.run();
byte[] actual = byteBufsToByteArray(consumer.getList());
for (ByteBuf buf : consumer.getList()) {
buf.recycle();
}
assertArrayEquals(expected, actual);
assertEquals(END_OF_STREAM, source.getProducerStatus());
assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
assertEquals(END_OF_STREAM, preBuf.getInput().getConsumerStatus());
assertEquals(END_OF_STREAM, preBuf.getOutput().getProducerStatus());
assertEquals(END_OF_STREAM, compressor.getInput().getConsumerStatus());
assertEquals(END_OF_STREAM, compressor.getOutput().getProducerStatus());
assertEquals(END_OF_STREAM, postBuf.getInput().getConsumerStatus());
assertEquals(END_OF_STREAM, postBuf.getOutput().getProducerStatus());
assertEquals(END_OF_STREAM, decompressor.getInput().getConsumerStatus());
assertEquals(END_OF_STREAM, decompressor.getOutput().getProducerStatus());
}
@Test
public void testWithoutConsumer() {
Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
List<ByteBuf> buffers = new ArrayList<>();
Random random = new Random(123456);
int buffersCount = 1000;
for (int i = 0; i < buffersCount; i++) {
ByteBuf buffer = createRandomByteBuf(random);
buffers.add(buffer);
}
byte[] expected = byteBufsToByteArray(buffers);
StreamProducer<ByteBuf> source = StreamProducers.ofIterable(eventloop, buffers);
StreamByteChunker preBuf = StreamByteChunker.create(eventloop, 64, 128);
StreamLZ4Compressor compressor = StreamLZ4Compressor.fastCompressor(eventloop);
StreamByteChunker postBuf = StreamByteChunker.create(eventloop, 64, 128);
StreamLZ4Decompressor decompressor = StreamLZ4Decompressor.create(eventloop);
TestStreamConsumers.TestConsumerToList<ByteBuf> consumer = TestStreamConsumers.toListRandomlySuspending(eventloop);
source.streamTo(preBuf.getInput());
eventloop.run();
preBuf.getOutput().streamTo(compressor.getInput());
eventloop.run();
compressor.getOutput().streamTo(postBuf.getInput());
eventloop.run();
postBuf.getOutput().streamTo(decompressor.getInput());
eventloop.run();
decompressor.getOutput().streamTo(consumer);
eventloop.run();
byte[] actual = byteBufsToByteArray(consumer.getList());
for (ByteBuf buf : consumer.getList()) {
buf.recycle();
}
assertArrayEquals(expected, actual);
assertEquals(END_OF_STREAM, source.getProducerStatus());
assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
assertEquals(END_OF_STREAM, preBuf.getInput().getConsumerStatus());
assertEquals(END_OF_STREAM, preBuf.getOutput().getProducerStatus());
assertEquals(END_OF_STREAM, compressor.getInput().getConsumerStatus());
assertEquals(END_OF_STREAM, compressor.getOutput().getProducerStatus());
assertEquals(END_OF_STREAM, postBuf.getInput().getConsumerStatus());
assertEquals(END_OF_STREAM, postBuf.getOutput().getProducerStatus());
assertEquals(END_OF_STREAM, decompressor.getInput().getConsumerStatus());
assertEquals(END_OF_STREAM, decompressor.getOutput().getProducerStatus());
}
@Test
public void testRaw() {
Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
StreamLZ4Compressor compressor = StreamLZ4Compressor.rawCompressor(eventloop);
doTest(eventloop, compressor);
}
@Test
public void testLz4Fast() {
Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
StreamLZ4Compressor compressor = StreamLZ4Compressor.fastCompressor(eventloop);
doTest(eventloop, compressor);
}
@Test
public void testLz4High() {
Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
StreamLZ4Compressor compressor = StreamLZ4Compressor.highCompressor(eventloop);
doTest(eventloop, compressor);
}
@Test
public void testLz4High10() {
Eventloop eventloop = Eventloop.create().withFatalErrorHandler(rethrowOnAnyError());
StreamLZ4Compressor compressor = StreamLZ4Compressor.highCompressor(eventloop, 10);
doTest(eventloop, compressor);
}
private void doTest(Eventloop eventloop, StreamLZ4Compressor compressor) {
byte data[] = "1".getBytes();
ByteBuf buf = ByteBuf.wrapForReading(data);
List<ByteBuf> buffers = new ArrayList<>();
buffers.add(buf);
StreamProducer<ByteBuf> source = StreamProducers.ofIterable(eventloop, buffers);
StreamLZ4Decompressor decompressor = StreamLZ4Decompressor.create(eventloop);
StreamConsumers.ToList<ByteBuf> consumer = StreamConsumers.toList(eventloop);
source.streamTo(compressor.getInput());
compressor.getOutput().streamTo(decompressor.getInput());
decompressor.getOutput().streamTo(consumer);
eventloop.run();
byte[] actual = byteBufsToByteArray(consumer.getList());
byte[] expected = byteBufsToByteArray(buffers);
for (ByteBuf b : consumer.getList()) {
b.recycle();
}
assertArrayEquals(actual, expected);
assertEquals(END_OF_STREAM, source.getProducerStatus());
assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
}
}