TestFixedSizeBinaryVector.java
/*
* 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 org.apache.arrow.vector;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.apache.arrow.memory.ArrowBuf;
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.vector.holders.FixedSizeBinaryHolder;
import org.apache.arrow.vector.holders.NullableFixedSizeBinaryHolder;
import org.apache.arrow.vector.util.ReusableByteArray;
import org.apache.arrow.vector.util.TransferPair;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class TestFixedSizeBinaryVector {
private static final int numValues = 123;
private static final int typeWidth = 9;
private static final int smallDataSize = 6;
private static final int largeDataSize = 12;
private static byte[][] values;
static {
values = new byte[numValues][typeWidth];
for (int i = 0; i < numValues; i++) {
for (int j = 0; j < typeWidth; j++) {
values[i][j] = ((byte) i);
}
}
}
private ArrowBuf[] bufs = new ArrowBuf[numValues];
private FixedSizeBinaryHolder[] holders = new FixedSizeBinaryHolder[numValues];
private NullableFixedSizeBinaryHolder[] nullableHolders =
new NullableFixedSizeBinaryHolder[numValues];
private static byte[] smallValue;
static {
smallValue = new byte[smallDataSize];
for (int i = 0; i < smallDataSize; i++) {
smallValue[i] = ((byte) i);
}
}
private ArrowBuf smallBuf;
private FixedSizeBinaryHolder smallHolder;
private NullableFixedSizeBinaryHolder smallNullableHolder;
private static byte[] largeValue;
static {
largeValue = new byte[largeDataSize];
for (int i = 0; i < largeDataSize; i++) {
largeValue[i] = ((byte) i);
}
}
private ArrowBuf largeBuf;
private FixedSizeBinaryHolder largeHolder;
private NullableFixedSizeBinaryHolder largeNullableHolder;
private BufferAllocator allocator;
private FixedSizeBinaryVector vector;
private static void failWithException(String message) throws Exception {
throw new Exception(message);
}
@BeforeEach
public void init() throws Exception {
allocator = new DirtyRootAllocator(Integer.MAX_VALUE, (byte) 100);
vector = new FixedSizeBinaryVector("fixedSizeBinary", allocator, typeWidth);
vector.allocateNew();
for (int i = 0; i < numValues; i++) {
bufs[i] = allocator.buffer(typeWidth);
bufs[i].setBytes(0, values[i]);
holders[i] = new FixedSizeBinaryHolder();
holders[i].byteWidth = typeWidth;
holders[i].buffer = bufs[i];
nullableHolders[i] = new NullableFixedSizeBinaryHolder();
nullableHolders[i].byteWidth = typeWidth;
nullableHolders[i].buffer = bufs[i];
nullableHolders[i].isSet = 1;
}
smallBuf = allocator.buffer(smallDataSize);
smallBuf.setBytes(0, smallValue);
smallHolder = new FixedSizeBinaryHolder();
smallHolder.byteWidth = smallDataSize;
smallHolder.buffer = smallBuf;
smallNullableHolder = new NullableFixedSizeBinaryHolder();
smallNullableHolder.byteWidth = smallDataSize;
smallNullableHolder.buffer = smallBuf;
largeBuf = allocator.buffer(largeDataSize);
largeBuf.setBytes(0, largeValue);
largeHolder = new FixedSizeBinaryHolder();
largeHolder.byteWidth = typeWidth;
largeHolder.buffer = largeBuf;
largeNullableHolder = new NullableFixedSizeBinaryHolder();
largeNullableHolder.byteWidth = typeWidth;
largeNullableHolder.buffer = largeBuf;
}
@AfterEach
public void terminate() throws Exception {
for (int i = 0; i < numValues; i++) {
bufs[i].close();
}
smallBuf.close();
largeBuf.close();
vector.close();
allocator.close();
}
@Test
public void testSetUsingByteArray() {
for (int i = 0; i < numValues; i++) {
vector.set(i, values[i]);
}
vector.setValueCount(numValues);
for (int i = 0; i < numValues; i++) {
assertArrayEquals(values[i], vector.getObject(i));
}
}
@Test
public void testSetUsingNull() {
final byte[] value = null;
for (int i = 0; i < numValues; i++) {
final int index = i;
Exception e =
assertThrows(
NullPointerException.class,
() -> {
vector.set(index, value);
});
assertEquals("expecting a valid byte array", e.getMessage());
}
}
@Test
public void testSetUsingHolder() {
for (int i = 0; i < numValues; i++) {
vector.set(i, holders[i]);
}
vector.setValueCount(numValues);
for (int i = 0; i < numValues; i++) {
assertArrayEquals(values[i], vector.getObject(i));
}
}
@Test
public void testSetUsingNullableHolder() {
for (int i = 0; i < numValues; i++) {
vector.set(i, nullableHolders[i]);
}
vector.setValueCount(numValues);
for (int i = 0; i < numValues; i++) {
assertArrayEquals(values[i], vector.getObject(i));
}
}
@Test
public void testGetUsingNullableHolder() {
for (int i = 0; i < numValues; i++) {
vector.set(i, holders[i]);
}
vector.setValueCount(numValues);
for (int i = 0; i < numValues; i++) {
vector.get(i, nullableHolders[i]);
assertEquals(typeWidth, nullableHolders[i].byteWidth);
assertTrue(nullableHolders[i].isSet > 0);
byte[] actual = new byte[typeWidth];
nullableHolders[i].buffer.getBytes(0, actual, 0, typeWidth);
assertArrayEquals(values[i], actual);
}
}
@Test
public void testSetWithInvalidInput() throws Exception {
String errorMsg = "input data needs to be at least " + typeWidth + " bytes";
// test small inputs, byteWidth matches but value or buffer is too small
try {
vector.set(0, smallValue);
failWithException(errorMsg);
} catch (AssertionError | IllegalArgumentException ignore) {
}
try {
vector.set(0, smallHolder);
failWithException(errorMsg);
} catch (AssertionError | IllegalArgumentException ignore) {
}
try {
vector.set(0, smallNullableHolder);
failWithException(errorMsg);
} catch (AssertionError | IllegalArgumentException ignore) {
}
try {
vector.set(0, smallBuf);
failWithException(errorMsg);
} catch (AssertionError | IllegalArgumentException ignore) {
}
// test large inputs, byteWidth matches but value or buffer is bigger than byteWidth
vector.set(0, largeValue);
vector.set(0, largeHolder);
vector.set(0, largeNullableHolder);
vector.set(0, largeBuf);
}
@Test
public void setSetSafeWithInvalidInput() throws Exception {
String errorMsg = "input data needs to be at least " + typeWidth + " bytes";
// test small inputs, byteWidth matches but value or buffer is too small
try {
vector.setSafe(0, smallValue);
failWithException(errorMsg);
} catch (AssertionError | IllegalArgumentException ignore) {
}
try {
vector.setSafe(0, smallHolder);
failWithException(errorMsg);
} catch (AssertionError | IllegalArgumentException ignore) {
}
try {
vector.setSafe(0, smallNullableHolder);
failWithException(errorMsg);
} catch (AssertionError | IllegalArgumentException ignore) {
}
try {
vector.setSafe(0, smallBuf);
failWithException(errorMsg);
} catch (AssertionError | IllegalArgumentException ignore) {
}
// test large inputs, byteWidth matches but value or buffer is bigger than byteWidth
vector.setSafe(0, largeValue);
vector.setSafe(0, largeHolder);
vector.setSafe(0, largeNullableHolder);
vector.setSafe(0, largeBuf);
}
@Test
public void testGetNull() {
vector.setNull(0);
assertNull(vector.get(0));
}
@Test
public void testGetTransferPairWithField() {
final FixedSizeBinaryVector fromVector =
new FixedSizeBinaryVector("fixedSizeBinary", allocator, typeWidth);
final TransferPair transferPair = fromVector.getTransferPair(fromVector.getField(), allocator);
final FixedSizeBinaryVector toVector = (FixedSizeBinaryVector) transferPair.getTo();
// Field inside a new vector created by reusing a field should be the same in memory as the
// original field.
assertSame(fromVector.getField(), toVector.getField());
}
@Test
public void testGetBytesRepeatedly() {
for (int i = 0; i < numValues; i++) {
vector.set(i, values[i]);
}
vector.setValueCount(numValues);
ReusableByteArray reusableByteArray = new ReusableByteArray();
for (int i = 0; i < numValues; i++) {
// verify results
vector.read(i, reusableByteArray);
assertArrayEquals(values[i], reusableByteArray.getBuffer());
}
}
}