/*
* 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.bytebuf;
import org.junit.Before;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.util.Arrays;
import static io.datakernel.bytebuf.ByteBufPool.*;
import static org.junit.Assert.*;
public class ByteBufTest {
private static final byte[] BYTES = new byte[]{'T', 'e', 's', 't', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e'};
@Before
public void setUp() {
ByteBufPool.clear();
ByteBufPool.setSizes(32, 1 << 30);
}
@Test
public void testSlice() {
byte[] bytes = ByteBufStrings.encodeAscii("Hello, World");
ByteBuf buf = ByteBuf.wrapForReading(bytes);
ByteBuf slice = buf.slice(7, 5);
assertFalse(buf == slice);
assertEquals("World", slice.toString());
buf = createEmptyByteBufOfSize(16);
buf.put(bytes);
slice = buf.slice();
assertFalse(buf == slice);
assertEquals("Hello, World", slice.toString());
}
@Test
public void testEditing() {
ByteBuf buf = createEmptyByteBufOfSize(256);
assertEquals(0, buf.readPosition());
buf.put((byte) 'H');
assertEquals(1, buf.writePosition());
assertEquals('H', buf.at(0));
buf.put(new byte[]{'e', 'l', 'l', 'o'});
buf.put(new byte[]{';', ' ', ',', ' ', '.', ' ', '!', ' '}, 2, 2);
assertEquals(7, buf.writePosition());
ByteBuf worldBuf = ByteBuf.wrapForReading(new byte[]{'W', 'o', 'r', 'l', 'd', '!'});
buf.put(worldBuf);
assertEquals(worldBuf.limit(), worldBuf.readPosition());
assertFalse(worldBuf.canWrite());
assertEquals(13, buf.writePosition());
ByteBuf slice = buf.slice();
ByteBuf newBuf = createEmptyByteBufOfSize(slice.limit());
slice.drainTo(newBuf, 10);
assertEquals(10, slice.readPosition());
assertEquals(10, newBuf.writePosition());
slice.drainTo(newBuf, 3);
assertEquals("Hello, World!", newBuf.toString());
}
@Test
public void transformsToByteBufferInReadMode() {
ByteBuf buf = createEmptyByteBufOfSize(8);
buf.writePosition(5);
buf.readPosition(2);
ByteBuffer buffer = buf.toReadByteBuffer();
assertEquals(2, buffer.position());
assertEquals(5, buffer.limit());
}
@Test
public void transformsToByteBufferInWriteMode() {
ByteBuf buf = createEmptyByteBufOfSize(8);
buf.writePosition(5);
buf.readPosition(2);
ByteBuffer buffer = buf.toWriteByteBuffer();
assertEquals(5, buffer.position());
assertEquals(8, buffer.limit());
}
@Test
public void testPoolAndRecycleMechanism() {
int size = 500;
ByteBuf buf = ByteBufPool.allocate(size);
assertNotEquals(size, buf.limit()); // {expected to create 2^N sized bufs only, 500 not in {a}|a == 2^N } => size != limit
assertEquals(512, buf.limit());
buf.put(BYTES);
buf.recycle();
try {
buf.put((byte) 'a');
} catch (AssertionError e) {
assertEquals(AssertionError.class, e.getClass());
}
buf = ByteBufPool.allocate(300);
buf.writePosition(BYTES.length);
byte[] bytes = new byte[BYTES.length];
buf.drainTo(bytes, 0, bytes.length);
assertArrayEquals(bytes, BYTES);
buf.recycle();
assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
}
@Test
public void testSliceAndRecycleMechanism() {
ByteBuf buf = ByteBufPool.allocate(5);
ByteBuf slice0 = buf.slice(1, 3);
ByteBuf slice01 = slice0.slice(2, 1);
ByteBuf slice1 = buf.slice(4, 1);
assertTrue(buf.canWrite());
slice1.recycle();
assertTrue(buf.canWrite());
slice0.recycle();
assertTrue(buf.canWrite());
slice01.recycle();
}
@Test
public void testViews() {
// emulate engine that receives randomly sized bufs from `net` and sends them to some `consumer`
class MockConsumer {
private int i = 0;
private void consume(ByteBuf buf) {
assertEquals("Test message " + i++, buf.toString());
buf.recycle();
}
}
MockConsumer consumer = new MockConsumer();
for (int i = 0; i < 100; i++) {
ByteBuf buf = ByteBufPool.allocate(32);
ByteBuffer buffer = buf.toWriteByteBuffer();
buffer.put(("Test message " + i).getBytes());
buffer.flip();
buf.writePosition(buffer.limit());
buf.readPosition(buffer.position());
consumer.consume(buf.slice());
buf.recycle();
}
assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
}
@Test
public void testConcat() {
ByteBuf buf = ByteBufPool.allocate(64);
buf.put(BYTES);
ByteBuf secondBuf = ByteBufPool.allocate(32);
secondBuf.put(BYTES);
buf = ByteBufPool.append(buf, secondBuf.slice());
buf = ByteBufPool.append(buf, secondBuf.slice());
buf = ByteBufPool.append(buf, secondBuf.slice());
buf = ByteBufPool.append(buf, secondBuf.slice());
buf = ByteBufPool.append(buf, secondBuf.slice());
assertEquals(new String(BYTES)
+ new String(BYTES)
+ new String(BYTES)
+ new String(BYTES)
+ new String(BYTES)
+ new String(BYTES), buf.toString());
buf.recycle();
secondBuf.recycle();
assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
}
@Test
public void testSkipAndAdvance() {
ByteBuf buf = createEmptyByteBufOfSize(5);
buf.put(new byte[]{'a', 'b', 'c'});
buf.moveReadPosition(2);
assertEquals('c', buf.get());
buf.array[3] = 'd';
buf.array[4] = 'e';
assertFalse(buf.canRead());
buf.moveWritePosition(2);
assertTrue(buf.canRead());
byte[] bytes = new byte[2];
buf.drainTo(bytes, 0, 2);
assertTrue(Arrays.equals(new byte[]{'d', 'e'}, bytes));
}
@Test
public void testGet() {
ByteBuf buf = createEmptyByteBufOfSize(3);
buf.put(new byte[]{'a', 'b', 'c'});
assertEquals('a', buf.get());
assertEquals('b', buf.get());
assertEquals('c', buf.get());
}
@Test
public void testFind() {
ByteBuf buf = createEmptyByteBufOfSize(BYTES.length);
buf.put(BYTES);
assertEquals(5, buf.find((byte) 'm'));
assertEquals(-1, buf.find(new byte[]{'T', 'e', 's', 's'}));
assertEquals(1, buf.find(new byte[]{'T', 'e', 's', 's'}, 1, 2));
}
private ByteBuf createEmptyByteBufOfSize(int size) {
return ByteBuf.wrapForWriting(new byte[size]);
}
}