/* * Copyright 2014 NAVER Corp. * * 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 com.navercorp.pinpoint.common.buffer; import com.google.common.primitives.Ints; import com.navercorp.pinpoint.common.Charsets; import com.navercorp.pinpoint.common.util.BytesUtils; import org.apache.commons.lang3.StringUtils; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.Arrays; import java.util.Random; /** * @author emeroad */ public class FixedBufferTest { public static final Charset UTF8_CHARSET = Charsets.UTF_8; private Logger logger = LoggerFactory.getLogger(this.getClass()); private Random random = new Random(); @Test public void testPutPrefixedBytes() throws Exception { String test = "test"; int endExpected = 3333; testPutPrefixedBytes(test, endExpected); testPutPrefixedBytes(null, endExpected); testPutPrefixedBytes("", endExpected); } private void testPutPrefixedBytes(String test, int expected) { Buffer buffer = new FixedBuffer(1024); if (test != null) { buffer.putPrefixedBytes(test.getBytes(UTF8_CHARSET)); } else { buffer.putPrefixedString(null); } buffer.putInt(expected); byte[] buffer1 = buffer.getBuffer(); Buffer actual = new FixedBuffer(buffer1); String s = actual.readPrefixedString(); Assert.assertEquals(test, s); int i = actual.readInt(); Assert.assertEquals(expected, i); } @Test public void testPadBytes() throws Exception { int TOTAL_LENGTH = 20; int TEST_SIZE = 10; Buffer buffer = new FixedBuffer(32); byte[] test = new byte[10]; random.nextBytes(test); buffer.putPadBytes(test, TOTAL_LENGTH); byte[] result = buffer.getBuffer(); Assert.assertEquals(result.length, TOTAL_LENGTH); Assert.assertTrue("check data", Arrays.equals(Arrays.copyOfRange(test, 0, TEST_SIZE), Arrays.copyOfRange(result, 0, TEST_SIZE))); byte[] padBytes = new byte[TOTAL_LENGTH - TEST_SIZE]; Assert.assertTrue("check pad", Arrays.equals(Arrays.copyOfRange(padBytes, 0, TEST_SIZE), Arrays.copyOfRange(result, TEST_SIZE, TOTAL_LENGTH))); } @Test public void readPadBytes() { byte[] bytes = new byte[10]; random.nextBytes(bytes); Buffer writeBuffer = new FixedBuffer(32); writeBuffer.putPadBytes(bytes, 20); writeBuffer.putInt(255); Buffer readBuffer = new FixedBuffer(writeBuffer.getBuffer()); byte[] readPadBytes = readBuffer.readPadBytes(20); Assert.assertArrayEquals(bytes, Arrays.copyOf(readPadBytes, 10)); int readInt = readBuffer.readInt(); Assert.assertEquals(255, readInt); } @Test public void testPadBytes_Error() throws Exception { Buffer buffer1_1 = new FixedBuffer(32); try { buffer1_1.putPadBytes(new byte[11], 10); Assert.fail("error"); } catch (IndexOutOfBoundsException ignore) { } Buffer buffer1_2 = new FixedBuffer(32); try { buffer1_2.putPadBytes(new byte[20], 10); Assert.fail("error"); } catch (IndexOutOfBoundsException ignore) { } Buffer buffer2 = new FixedBuffer(32); buffer2.putPadBytes(new byte[10], 10); } @Test public void testPadString() throws Exception { int TOTAL_LENGTH = 20; int TEST_SIZE = 10; int PAD_SIZE = TOTAL_LENGTH - TEST_SIZE; Buffer buffer= new FixedBuffer(32); String test = StringUtils.repeat('a', TEST_SIZE); buffer.putPadString(test, TOTAL_LENGTH); byte[] result = buffer.getBuffer(); String decodedString = new String(result); String trimString = decodedString.trim(); Assert.assertEquals(result.length, TOTAL_LENGTH); Assert.assertEquals("check data", test, trimString); String padString = new String(result, TOTAL_LENGTH - TEST_SIZE, PAD_SIZE, UTF8_CHARSET.name()); byte[] padBytes = new byte[TOTAL_LENGTH - TEST_SIZE]; Assert.assertEquals("check pad", padString, new String(padBytes, UTF8_CHARSET)); } @Test public void readPadString() { String testString = StringUtils.repeat('a', 10); Buffer writeBuffer = new FixedBuffer(32); writeBuffer.putPadString(testString, 20); writeBuffer.putInt(255); Buffer readBuffer = new FixedBuffer(writeBuffer.getBuffer()); String readPadString = readBuffer.readPadString(20); Assert.assertEquals(testString, readPadString.substring(0, 10)); int readInt = readBuffer.readInt(); Assert.assertEquals(255, readInt); } @Test public void readPadStringAndRightTrim() { String testString = StringUtils.repeat('a', 10); Buffer writeBuffer = new FixedBuffer(32); writeBuffer.putPadString(testString, 20); writeBuffer.putInt(255); Buffer readBuffer = new FixedBuffer(writeBuffer.getBuffer()); String readPadString = readBuffer.readPadStringAndRightTrim(20); Assert.assertEquals(testString, readPadString); int readInt = readBuffer.readInt(); Assert.assertEquals(255, readInt); } @Test public void testPadString_Error() throws Exception { Buffer buffer1_1 = new FixedBuffer(32); try { buffer1_1.putPadString(StringUtils.repeat('a', 11), 10); } catch (IndexOutOfBoundsException ignore) { } Buffer buffer1_2 = new FixedBuffer(32); try { buffer1_2.putPadString(StringUtils.repeat('a', 20), 10); Assert.fail("error"); } catch (IndexOutOfBoundsException ignore) { } Buffer buffer2 = new FixedBuffer(32); buffer2.putPadString(StringUtils.repeat('a', 10), 10); } @Test public void testPut2PrefixedBytes() throws Exception { String test = "test"; int endExpected = 3333; checkPut2PrefixedBytes(test, endExpected); checkPut2PrefixedBytes(null, endExpected); checkPut2PrefixedBytes("", endExpected); byte[] bytes = new byte[Short.MAX_VALUE]; checkPut2PrefixedBytes(BytesUtils.toString(bytes), endExpected, Short.MAX_VALUE * 2); try { byte[] bytes2 = new byte[Short.MAX_VALUE + 1]; checkPut2PrefixedBytes(BytesUtils.toString(bytes2), endExpected, Short.MAX_VALUE * 2); Assert.fail("too large bytes"); } catch (IndexOutOfBoundsException ignore) { } } private void checkPut2PrefixedBytes(String test, int expected) { checkPut2PrefixedBytes(test, expected, 1024); } private void checkPut2PrefixedBytes(String test, int expected, int bufferSize) { Buffer buffer = new FixedBuffer(bufferSize); if (test != null) { buffer.put2PrefixedBytes(test.getBytes(UTF8_CHARSET)); } else { buffer.put2PrefixedBytes(null); } buffer.putInt(expected); byte[] buffer1 = buffer.getBuffer(); Buffer actual = new FixedBuffer(buffer1); String s = actual.read2PrefixedString(); Assert.assertEquals(test, s); int i = actual.readInt(); Assert.assertEquals(expected, i); } @Test public void testPut4PrefixedBytes() throws Exception { String test = "test"; int endExpected = 3333; checkPut4PrefixedBytes(test, endExpected); checkPut4PrefixedBytes(null, endExpected); checkPut4PrefixedBytes("", endExpected); } private void checkPut4PrefixedBytes(String test, int expected) { Buffer buffer = new FixedBuffer(1024); if (test != null) { buffer.put4PrefixedBytes(test.getBytes(UTF8_CHARSET)); } else { buffer.put4PrefixedBytes(null); } buffer.putInt(expected); byte[] buffer1 = buffer.getBuffer(); Buffer actual = new FixedBuffer(buffer1); String s = actual.read4PrefixedString(); Assert.assertEquals(test, s); int i = actual.readInt(); Assert.assertEquals(expected, i); } @Test public void testReadByte() throws Exception { } @Test public void testReadBoolean() throws Exception { } @Test public void testReadInt() throws Exception { } @Test public void testReadLong() throws Exception { } @Test public void testReadPrefixedString() throws Exception { } @Test public void testRead4PrefixedString() throws Exception { String value = "test"; byte[] length = Ints.toByteArray(value.length()); byte[] string = value.getBytes(); byte[] result = BytesUtils.merge(length, string); Buffer buffer = new FixedBuffer(result); String prefixedString = buffer.read4PrefixedString(); Assert.assertEquals(prefixedString, value); } @Test public void testRead4PrefixedString_Null() throws Exception { byte[] length = Ints.toByteArray(-1); Buffer buffer = new FixedBuffer(length); String prefixedString = buffer.read4PrefixedString(); Assert.assertEquals(prefixedString, null); } @Test public void testPut() throws Exception { checkUnsignedByte(255); checkUnsignedByte(0); } /** * bound 1->0 * bound 2->128 * bound 3->16384 * bound 4->2097152 * bound 5->268435456 */ @Test public void testPutVInt() throws Exception { checkVInt(Integer.MAX_VALUE, 5); checkVInt(25, 1); checkVInt(100, 1); checkVInt(Integer.MIN_VALUE, -1); checkVInt(Integer.MAX_VALUE / 2, -1); checkVInt(Integer.MAX_VALUE / 10, -1); checkVInt(Integer.MAX_VALUE / 10000, -1); checkVInt(Integer.MIN_VALUE / 2, -1); checkVInt(Integer.MIN_VALUE / 10, -1); checkVInt(Integer.MIN_VALUE / 10000, -1); checkVInt(0, -1); checkVInt(127, -1); checkVInt(128, -1); checkVInt(16383, -1); checkVInt(16384, -1); checkVInt(268435455, -1); checkVInt(268435456, -1); } private void checkVInt(int v, int offset) { checkVInt_bufferSize(v, offset, 32); if (v >= 0) { final int bufferSize = BytesUtils.computeVar32Size(v); checkVInt_bufferSize(v, offset, bufferSize); } else { final int bufferSize = BytesUtils.computeVar64Size(v); checkVInt_bufferSize(v, offset, bufferSize); } } private void checkVInt_bufferSize(int v, int offset, int bufferSize) { final Buffer buffer = new FixedBuffer(bufferSize); buffer.putVInt(v); if (offset != -1) { Assert.assertEquals(buffer.getOffset(), offset); } else { logger.debug("{} offsetSize:{}", v, buffer.getOffset()); } buffer.setOffset(0); int readV = buffer.readVInt(); Assert.assertEquals(readV, v); } @Test public void testPutSVInt() throws Exception { // 63 is the boundary for a 1 byte number checkSVInt(63, -1); // 8191 is the boundary for a 2 byte number checkSVInt((1024*8)-1, -1); checkSVInt(3, -1); checkSVInt(Integer.MAX_VALUE, 5); checkSVInt(Integer.MIN_VALUE, 5); checkSVInt(0, -1); checkSVInt(Integer.MAX_VALUE / 2, -1); checkSVInt(Integer.MAX_VALUE / 10, -1); checkSVInt(Integer.MAX_VALUE / 10000, -1); checkSVInt(Integer.MIN_VALUE / 2, -1); checkSVInt(Integer.MIN_VALUE / 10, -1); checkSVInt(Integer.MIN_VALUE / 10000, -1); } // @Test public void find_SVInt_errorCode() throws Exception { Random random = new Random(); byte[] bytes = new byte[10]; while(true) { random.nextBytes(bytes); Buffer buffer = new FixedBuffer(bytes); try { int i = buffer.readVInt(); } catch (IllegalArgumentException e) { logger.debug(e.getMessage(), e); String binaryString = BytesUtils.toString(bytes); logger.debug(binaryString); for (byte aByte : bytes) { String code = String.valueOf((int) aByte); logger.debug(code); } return; } } } // @Test public void find_SVLong_errorCode() throws Exception { Random random = new Random(); byte[] bytes = new byte[10]; while(true) { random.nextBytes(bytes); Buffer buffer = new FixedBuffer(bytes); try { long i = buffer.readVLong(); } catch (IllegalArgumentException e) { logger.debug(e.getMessage(), e); String binaryString = BytesUtils.toString(bytes); logger.debug(binaryString); for (byte aByte : bytes) { String code = String.valueOf((int) aByte); logger.debug(code); } return; } } } @Test public void readVInt_errorCase() { byte[] errorCode = new byte[] {-118, -41, -17, -117, -81, -115, -64, -64, -108, -88}; Buffer buffer = new FixedBuffer(errorCode); try { buffer.readVInt(); Assert.fail("invalid VInt"); } catch (IllegalArgumentException ignore) { } Assert.assertEquals(0, buffer.getOffset()); } @Test public void readVLong_errorCase() { byte[] errorCode = new byte[] {-25, -45, -47, -14, -16, -104, -53, -48, -72, -9}; Buffer buffer = new FixedBuffer(errorCode); try { buffer.readVLong(); Assert.fail("invalid VLong"); } catch (IllegalArgumentException ignore) { } Assert.assertEquals(0, buffer.getOffset()); } private void checkSVInt(int v, int offset) { Buffer buffer = new FixedBuffer(32); buffer.putSVInt(v); if (offset != -1) { Assert.assertEquals(buffer.getOffset(), offset); } else { logger.debug("{} offsetSize:{}", v, buffer.getOffset()); } buffer.setOffset(0); int readV = buffer.readSVInt(); Assert.assertEquals(readV, v); } @Test public void testPutVLong() throws Exception { checkVLong(1); checkVLong(-1); checkVLong(Long.MAX_VALUE); checkVLong(Long.MIN_VALUE); checkVLong(Long.MAX_VALUE/2); checkVLong(Long.MIN_VALUE/2); checkVLong(Long.MAX_VALUE/128); checkVLong(Long.MAX_VALUE/102400); checkVLong(900719925474L); checkVLong(9007199254L); checkVLong(225179981); checkVLong(1179981); checkVLong(9981); checkVLong(127); checkVLong(-127); checkVLong(0L); checkVLong(127L); checkVLong(128L); checkVLong(16383L); checkVLong(16384L); checkVLong(268435455L); checkVLong(268435456L); checkVLong(34359738367L); checkVLong(34359738368L); } private void checkVLong(long v) { checkVLong_bufferSize(v, 32); final int bufferSize = BytesUtils.computeVar64Size(v); checkVLong_bufferSize(v, bufferSize); } private void checkVLong_bufferSize(long v, int bufferSize) { final Buffer buffer = new FixedBuffer(bufferSize); buffer.putVLong(v); buffer.setOffset(0); long readV = buffer.readVLong(); Assert.assertEquals(readV, v); if (logger.isTraceEnabled()) { logger.trace("v:{} offset:{}", v, buffer.getOffset()); } } private void checkUnsignedByte(int value) { Buffer buffer = new FixedBuffer(1024); buffer.putByte((byte) value); byte[] buffer1 = buffer.getBuffer(); Buffer reader = new FixedBuffer(buffer1); int i = reader.readUnsignedByte(); Assert.assertEquals(value, i); } @Test public void testGetBuffer() throws Exception { Buffer buffer = new FixedBuffer(4); buffer.putInt(1); Assert.assertEquals(buffer.getOffset(), 4); Assert.assertEquals(buffer.getBuffer().length, 4); } @Test public void testWrapByteBuffer() throws Exception { FixedBuffer buffer = new FixedBuffer(8); buffer.putInt(1); buffer.putInt(2); final ByteBuffer byteBuffer = buffer.wrapByteBuffer(); Assert.assertEquals(byteBuffer.getInt(), 1); Assert.assertEquals(byteBuffer.getInt(), 2); } @Test public void testSliceGetBuffer() throws Exception { Buffer buffer = new FixedBuffer(5); buffer.putInt(1); Assert.assertEquals(buffer.getOffset(), 4); Assert.assertEquals(buffer.getBuffer().length, 4); byte[] buffer1 = buffer.getBuffer(); byte[] buffer2 = buffer.getBuffer(); Assert.assertTrue(buffer1 != buffer2); } @Test public void testBoolean() { Buffer buffer = new FixedBuffer(16); buffer.putBoolean(true); buffer.putBoolean(false); Buffer read = new FixedBuffer(buffer.getBuffer()); boolean b = read.readBoolean(); Assert.assertEquals(true, b); boolean c = read.readBoolean(); Assert.assertEquals(false, c); } @Test public void testGetOffset() throws Exception { Buffer buffer = new FixedBuffer(); Assert.assertEquals(buffer.getOffset(), 0); buffer.putInt(4); Assert.assertEquals(buffer.getOffset(), 4); } @Test public void test_remaining() throws Exception { final byte[] bytes = new byte[BytesUtils.INT_BYTE_LENGTH]; Buffer buffer = new FixedBuffer(bytes); Assert.assertEquals(buffer.remaining(), 4); Assert.assertTrue(buffer.hasRemaining()); buffer.putInt(1234); Assert.assertEquals(buffer.remaining(), 0); Assert.assertFalse(buffer.hasRemaining()); buffer.setOffset(0); buffer.putShort((short)12); Assert.assertEquals(buffer.remaining(), 2); Assert.assertTrue(buffer.hasRemaining()); buffer.putByte((byte)1); Assert.assertEquals(buffer.remaining(), 1); Assert.assertTrue(buffer.hasRemaining()); } }