/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 parquet.bytes;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import org.junit.Test;
public class TestCapacityByteArrayOutputStream {
@Test
public void testWrite() throws Throwable {
CapacityByteArrayOutputStream capacityByteArrayOutputStream = new CapacityByteArrayOutputStream(10);
final int expectedSize = 54;
for (int i = 0; i < expectedSize; i++) {
capacityByteArrayOutputStream.write(i);
assertEquals(i + 1, capacityByteArrayOutputStream.size());
}
validate(capacityByteArrayOutputStream, expectedSize);
}
@Test
public void testWriteArray() throws Throwable {
CapacityByteArrayOutputStream capacityByteArrayOutputStream = new CapacityByteArrayOutputStream(10);
int v = 23;
writeArraysOf3(capacityByteArrayOutputStream, v);
validate(capacityByteArrayOutputStream, v * 3);
}
@Test
public void testWriteArrayAndInt() throws Throwable {
CapacityByteArrayOutputStream capacityByteArrayOutputStream = new CapacityByteArrayOutputStream(10);
for (int i = 0; i < 23; i++) {
byte[] toWrite = { (byte)(i * 3), (byte)(i * 3 + 1)};
capacityByteArrayOutputStream.write(toWrite);
capacityByteArrayOutputStream.write((byte)(i * 3 + 2));
assertEquals((i + 1) * 3, capacityByteArrayOutputStream.size());
}
validate(capacityByteArrayOutputStream, 23 * 3);
}
@Test
public void testReset() throws Throwable {
CapacityByteArrayOutputStream capacityByteArrayOutputStream = new CapacityByteArrayOutputStream(10);
for (int i = 0; i < 54; i++) {
capacityByteArrayOutputStream.write(i);
assertEquals(i + 1, capacityByteArrayOutputStream.size());
}
capacityByteArrayOutputStream.reset();
for (int i = 0; i < 54; i++) {
capacityByteArrayOutputStream.write(54 + i);
assertEquals(i + 1, capacityByteArrayOutputStream.size());
}
final byte[] byteArray = BytesInput.from(capacityByteArrayOutputStream).toByteArray();
assertEquals(54, byteArray.length);
for (int i = 0; i < 54; i++) {
assertEquals(i + " in " + Arrays.toString(byteArray) ,54 + i, byteArray[i]);
}
}
@Test
public void testWriteArrayBiggerThanSlab() throws Throwable {
CapacityByteArrayOutputStream capacityByteArrayOutputStream = new CapacityByteArrayOutputStream(10);
int v = 23;
writeArraysOf3(capacityByteArrayOutputStream, v);
int n = v * 3;
byte[] toWrite = { // bigger than 2 slabs of size of 10
(byte)n, (byte)(n + 1), (byte)(n + 2), (byte)(n + 3), (byte)(n + 4), (byte)(n + 5),
(byte)(n + 6), (byte)(n + 7), (byte)(n + 8), (byte)(n + 9), (byte)(n + 10),
(byte)(n + 11), (byte)(n + 12), (byte)(n + 13), (byte)(n + 14), (byte)(n + 15),
(byte)(n + 16), (byte)(n + 17), (byte)(n + 18), (byte)(n + 19), (byte)(n + 20)};
capacityByteArrayOutputStream.write(toWrite);
n = n + toWrite.length;
assertEquals(n, capacityByteArrayOutputStream.size());
validate(capacityByteArrayOutputStream, n);
capacityByteArrayOutputStream.reset();
// check it works after reset too
capacityByteArrayOutputStream.write(toWrite);
assertEquals(toWrite.length, capacityByteArrayOutputStream.size());
byte[] byteArray = BytesInput.from(capacityByteArrayOutputStream).toByteArray();
assertEquals(toWrite.length, byteArray.length);
for (int i = 0; i < toWrite.length; i++) {
assertEquals(toWrite[i], byteArray[i]);
}
}
@Test
public void testWriteArrayManySlabs() throws Throwable {
CapacityByteArrayOutputStream capacityByteArrayOutputStream = new CapacityByteArrayOutputStream(10);
int it = 500;
int v = 23;
for (int j = 0; j < it; j++) {
for (int i = 0; i < v; i++) {
byte[] toWrite = { (byte)(i * 3), (byte)(i * 3 + 1), (byte)(i * 3 + 2)};
capacityByteArrayOutputStream.write(toWrite);
assertEquals((i + 1) * 3 + v * 3 * j, capacityByteArrayOutputStream.size());
}
}
byte[] byteArray = BytesInput.from(capacityByteArrayOutputStream).toByteArray();
assertEquals(v * 3 * it, byteArray.length);
for (int i = 0; i < v * 3 * it; i++) {
assertEquals(i % (v * 3), byteArray[i]);
}
// verifying we have not created 500 * 23 / 10 slabs
assertTrue("slab count: " + capacityByteArrayOutputStream.getSlabCount(),capacityByteArrayOutputStream.getSlabCount() <= 20);
capacityByteArrayOutputStream.reset();
writeArraysOf3(capacityByteArrayOutputStream, v);
validate(capacityByteArrayOutputStream, v * 3);
// verifying we use less slabs now
assertTrue("slab count: " + capacityByteArrayOutputStream.getSlabCount(),capacityByteArrayOutputStream.getSlabCount() <= 2);
}
@Test
public void testReplaceByte() throws Throwable {
// test replace the first value
{
CapacityByteArrayOutputStream cbaos = new CapacityByteArrayOutputStream(5);
cbaos.write(10);
assertEquals(0, cbaos.getCurrentIndex());
cbaos.setByte(0, (byte) 7);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cbaos.writeTo(baos);
assertEquals(7, baos.toByteArray()[0]);
}
// test replace value in the first slab
{
CapacityByteArrayOutputStream cbaos = new CapacityByteArrayOutputStream(5);
cbaos.write(10);
cbaos.write(13);
cbaos.write(15);
cbaos.write(17);
assertEquals(3, cbaos.getCurrentIndex());
cbaos.write(19);
cbaos.setByte(3, (byte) 7);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cbaos.writeTo(baos);
assertArrayEquals(new byte[]{10, 13, 15, 7, 19}, baos.toByteArray());
}
// test replace in *not* the first slab
{
CapacityByteArrayOutputStream cbaos = new CapacityByteArrayOutputStream(5);
// advance part way through the 3rd slab
for (int i = 0; i < 12; i++) {
cbaos.write(100 + i);
}
assertEquals(11, cbaos.getCurrentIndex());
cbaos.setByte(6, (byte) 7);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cbaos.writeTo(baos);
assertArrayEquals(
new byte[]{100, 101, 102, 103, 104, 105, 7, 107, 108, 109, 110, 111},
baos.toByteArray());
}
// test replace last value of a slab
{
CapacityByteArrayOutputStream cbaos = new CapacityByteArrayOutputStream(5);
// advance part way through the 3rd slab
for (int i = 0; i < 12; i++) {
cbaos.write(100 + i);
}
assertEquals(11, cbaos.getCurrentIndex());
cbaos.setByte(9, (byte) 7);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cbaos.writeTo(baos);
assertArrayEquals(
new byte[]{100, 101, 102, 103, 104, 105, 106, 107, 108, 7, 110, 111},
baos.toByteArray());
}
// test replace last value
{
CapacityByteArrayOutputStream cbaos = new CapacityByteArrayOutputStream(5);
// advance part way through the 3rd slab
for (int i = 0; i < 12; i++) {
cbaos.write(100 + i);
}
assertEquals(11, cbaos.getCurrentIndex());
cbaos.setByte(11, (byte) 7);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
cbaos.writeTo(baos);
assertArrayEquals(
new byte[]{100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 7},
baos.toByteArray());
}
}
private void writeArraysOf3(CapacityByteArrayOutputStream capacityByteArrayOutputStream, int n)
throws IOException {
for (int i = 0; i < n; i++) {
byte[] toWrite = { (byte)(i * 3), (byte)(i * 3 + 1), (byte)(i * 3 + 2)};
capacityByteArrayOutputStream.write(toWrite);
assertEquals((i + 1) * 3, capacityByteArrayOutputStream.size());
}
}
private void validate(
CapacityByteArrayOutputStream capacityByteArrayOutputStream,
final int expectedSize) throws IOException {
final byte[] byteArray = BytesInput.from(capacityByteArrayOutputStream).toByteArray();
assertEquals(expectedSize, byteArray.length);
for (int i = 0; i < expectedSize; i++) {
assertEquals(i, byteArray[i]);
}
}
}