TestCopyFrom.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.apache.arrow.vector.TestUtils.newVector;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Period;
import java.util.Objects;
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.memory.RootAllocator;
import org.apache.arrow.vector.types.Types.MinorType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/*
* Tested field types:
*
* NullableInt
* NullableBigInt
* NullableFloat4
* NullableFloat8
* NullableBit
* NullableDecimal
* NullableIntervalDay
* NullableIntervalYear
* NullableSmallInt
* NullableTinyInt
* NullableVarChar
* NullableTimeMicro
* NullableTimeMilli
* NullableTimeStamp*
*/
public class TestCopyFrom {
private static final String EMPTY_SCHEMA_PATH = "";
private BufferAllocator allocator;
@BeforeEach
public void init() {
allocator = new RootAllocator(Long.MAX_VALUE);
}
@AfterEach
public void terminate() throws Exception {
allocator.close();
}
@Test /* NullableVarChar */
public void testCopyFromWithNulls() {
try (final VarCharVector vector =
newVector(VarCharVector.class, EMPTY_SCHEMA_PATH, MinorType.VARCHAR, allocator);
final VarCharVector vector2 =
newVector(VarCharVector.class, EMPTY_SCHEMA_PATH, MinorType.VARCHAR, allocator)) {
vector.allocateNew();
assertTrue(vector.getValueCapacity() >= 1);
assertEquals(0, vector.getValueCount());
int initialCapacity = vector.getValueCapacity();
for (int i = 0; i < initialCapacity; i++) {
if (i % 3 == 0) {
continue;
}
byte[] b = Integer.toString(i).getBytes(StandardCharsets.UTF_8);
vector.setSafe(i, b, 0, b.length);
}
/* NO reAlloc() should have happened in setSafe() */
int capacity = vector.getValueCapacity();
assertEquals(initialCapacity, capacity);
vector.setValueCount(initialCapacity);
for (int i = 0; i < initialCapacity; i++) {
if (i % 3 == 0) {
assertNull(vector.getObject(i));
} else {
assertEquals(
Integer.toString(i),
vector.getObject(i).toString(),
"unexpected value at index: " + i);
}
}
vector2.setInitialCapacity(initialCapacity);
vector2.allocateNew();
capacity = vector2.getValueCapacity();
assertEquals(initialCapacity, capacity);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector);
if (i % 3 == 0) {
assertNull(vector2.getObject(i));
} else {
assertEquals(
Integer.toString(i),
vector2.getObject(i).toString(),
"unexpected value at index: " + i);
}
}
/* NO reAlloc() should have happened in copyFrom */
capacity = vector2.getValueCapacity();
assertEquals(initialCapacity, capacity);
vector2.setValueCount(initialCapacity);
for (int i = 0; i < initialCapacity; i++) {
if (i % 3 == 0) {
assertNull(vector2.getObject(i));
} else {
assertEquals(
Integer.toString(i),
vector2.getObject(i).toString(),
"unexpected value at index: " + i);
}
}
}
}
@Test /* NullableVarChar */
public void testCopyFromWithNulls1() {
try (final VarCharVector vector =
newVector(VarCharVector.class, EMPTY_SCHEMA_PATH, MinorType.VARCHAR, allocator);
final VarCharVector vector2 =
newVector(VarCharVector.class, EMPTY_SCHEMA_PATH, MinorType.VARCHAR, allocator)) {
vector.allocateNew();
assertTrue(vector.getValueCapacity() >= 1);
assertEquals(0, vector.getValueCount());
int initialCapacity = vector.getValueCapacity();
for (int i = 0; i < initialCapacity; i++) {
if (i % 3 == 0) {
continue;
}
byte[] b = Integer.toString(i).getBytes(StandardCharsets.UTF_8);
vector.setSafe(i, b, 0, b.length);
}
/* NO reAlloc() should have happened in setSafe() */
int capacity = vector.getValueCapacity();
assertEquals(initialCapacity, capacity);
vector.setValueCount(initialCapacity);
for (int i = 0; i < initialCapacity; i++) {
if (i % 3 == 0) {
assertNull(vector.getObject(i));
} else {
assertEquals(
Integer.toString(i),
vector.getObject(i).toString(),
"unexpected value at index: " + i);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew((initialCapacity / 4) * 10, initialCapacity / 4);
capacity = vector2.getValueCapacity();
assertTrue(capacity >= initialCapacity / 4);
assertTrue(capacity < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector);
if (i % 3 == 0) {
assertNull(vector2.getObject(i));
} else {
assertEquals(
Integer.toString(i),
vector2.getObject(i).toString(),
"unexpected value at index: " + i);
}
}
/* 2 reAllocs should have happened in copyFromSafe() */
capacity = vector2.getValueCapacity();
assertTrue(capacity >= initialCapacity);
vector2.setValueCount(initialCapacity);
for (int i = 0; i < initialCapacity; i++) {
if (i % 3 == 0) {
assertNull(vector2.getObject(i));
} else {
assertEquals(
Integer.toString(i),
vector2.getObject(i).toString(),
"unexpected value at index: " + i);
}
}
}
}
@Test /* IntVector */
public void testCopyFromWithNulls2() {
try (final IntVector vector1 = new IntVector(EMPTY_SCHEMA_PATH, allocator);
final IntVector vector2 = new IntVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, 1000 + i);
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
assertEquals(1000 + i, vector1.get(i), "unexpected value at index: " + i);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
assertEquals(1000 + i, vector2.get(i), "unexpected value at index: " + i);
}
}
}
}
@Test /* BigIntVector */
public void testCopyFromWithNulls3() {
try (final BigIntVector vector1 = new BigIntVector(EMPTY_SCHEMA_PATH, allocator);
final BigIntVector vector2 = new BigIntVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, 10000000000L + (long) i);
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
assertEquals(10000000000L + (long) i, vector1.get(i), "unexpected value at index: " + i);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
assertEquals(10000000000L + (long) i, vector2.get(i), "unexpected value at index: " + i);
}
}
}
}
@Test /* BitVector */
public void testCopyFromWithNulls4() {
try (final BitVector vector1 = new BitVector(EMPTY_SCHEMA_PATH, allocator);
final BitVector vector2 = new BitVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.setInitialCapacity(4096);
vector1.allocateNew();
assertEquals(4096, vector1.getValueCapacity());
assertEquals(0, vector1.getValueCount());
int counter = 0;
for (int i = 0; i < 4096; i++) {
if ((i & 1) == 0) {
continue;
}
if ((counter & 1) == 0) {
vector1.setSafe(i, 1);
} else {
vector1.setSafe(i, 0);
}
counter++;
}
vector1.setValueCount(4096);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(4096, vector1.getValueCapacity());
assertEquals(4096, vector1.getValueCount());
counter = 0;
for (int i = 0; i < 4096; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
if ((counter & 1) == 0) {
assertTrue(vector1.getObject(i));
} else {
assertFalse(vector1.getObject(i));
}
counter++;
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(1024);
assertEquals(1024, vector2.getValueCapacity());
for (int i = 0; i < 4096; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertEquals(4096, vector2.getValueCapacity());
vector2.setValueCount(8192);
/* setValueCount() should have done another realloc */
assertEquals(8192, vector2.getValueCount());
assertEquals(8192, vector2.getValueCapacity());
/* check vector data after copy and realloc */
counter = 0;
for (int i = 0; i < 8192; i++) {
if (((i & 1) == 0) || (i >= 4096)) {
assertNull(vector2.getObject(i));
} else {
if ((counter & 1) == 0) {
assertTrue(vector2.getObject(i));
} else {
assertFalse(vector2.getObject(i));
}
counter++;
}
}
}
}
@Test /* Float4Vector */
public void testCopyFromWithNulls5() {
try (final Float4Vector vector1 = new Float4Vector(EMPTY_SCHEMA_PATH, allocator);
final Float4Vector vector2 = new Float4Vector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, 100.25f + (float) i);
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
assertEquals(100.25f + (float) i, vector1.get(i), 0, "unexpected value at index: " + i);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
assertEquals(100.25f + i * 1.0f, vector2.get(i), 0, "unexpected value at index: " + i);
}
}
}
}
@Test /* Float8Vector */
public void testCopyFromWithNulls6() {
try (final Float8Vector vector1 = new Float8Vector(EMPTY_SCHEMA_PATH, allocator);
final Float8Vector vector2 = new Float8Vector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, 123456.7865 + (double) i);
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
assertEquals(
123456.7865 + (double) i, vector1.get(i), 0, "unexpected value at index: " + i);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
assertEquals(
123456.7865 + (double) i, vector2.get(i), 0, "unexpected value at index: " + i);
}
}
}
}
@Test /* IntervalDayVector */
public void testCopyFromWithNulls7() {
try (final IntervalDayVector vector1 = new IntervalDayVector(EMPTY_SCHEMA_PATH, allocator);
final IntervalDayVector vector2 = new IntervalDayVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
final int days = 10;
final int milliseconds = 10000;
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, days + i, milliseconds + i);
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
final Duration d = vector1.getObject(i);
assertEquals(days + i, d.toDays());
assertEquals(milliseconds + i, d.minusDays(days + i).toMillis());
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
final Duration d = vector2.getObject(i);
assertEquals(days + i, d.toDays());
assertEquals(milliseconds + i, d.minusDays(days + i).toMillis());
}
}
}
}
@Test /* IntervalYearVector */
public void testCopyFromWithNulls8() {
try (final IntervalYearVector vector1 = new IntervalYearVector(EMPTY_SCHEMA_PATH, allocator);
final IntervalYearVector vector2 = new IntervalYearVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
final int interval = 30; /* 2 years 6 months */
final Period[] periods = new Period[4096];
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, interval + i);
final int years = (interval + i) / org.apache.arrow.vector.util.DateUtility.yearsToMonths;
final int months = (interval + i) % org.apache.arrow.vector.util.DateUtility.yearsToMonths;
periods[i] = Period.ofYears(years).plusMonths(months).normalized();
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
final Period p = vector1.getObject(i).normalized();
assertEquals(interval + i, vector1.get(i));
assertEquals(periods[i], p);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
final Period p = vector2.getObject(i).normalized();
assertEquals(periods[i], p);
}
}
}
}
@Test /* SmallIntVector */
public void testCopyFromWithNulls9() {
try (final SmallIntVector vector1 = new SmallIntVector(EMPTY_SCHEMA_PATH, allocator);
final SmallIntVector vector2 = new SmallIntVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
final short val = 1000;
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, val + (short) i);
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
assertEquals(val + (short) i, vector1.get(i), "unexpected value at index: " + i);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
assertEquals(val + (short) i, vector2.get(i), "unexpected value at index: " + i);
}
}
}
}
@Test /* TimeMicroVector */
public void testCopyFromWithNulls10() {
try (final TimeMicroVector vector1 = new TimeMicroVector(EMPTY_SCHEMA_PATH, allocator);
final TimeMicroVector vector2 = new TimeMicroVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
final long val = 100485765432L;
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, val + (long) i);
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
assertEquals(val + (long) i, vector1.get(i), "unexpected value at index: " + i);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
assertEquals(val + (long) i, vector2.get(i), "unexpected value at index: " + i);
}
}
}
}
@Test /* TimeMilliVector */
public void testCopyFromWithNulls11() {
try (final TimeMilliVector vector1 = new TimeMilliVector(EMPTY_SCHEMA_PATH, allocator);
final TimeMilliVector vector2 = new TimeMilliVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
final int val = 1000;
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, val + i);
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
assertEquals(val + i, vector1.get(i), "unexpected value at index: " + i);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
assertEquals(val + i, vector2.get(i), "unexpected value at index: " + i);
}
}
}
}
@Test /* TinyIntVector */
public void testCopyFromWithNulls12() {
try (final TinyIntVector vector1 = new TinyIntVector(EMPTY_SCHEMA_PATH, allocator);
final TinyIntVector vector2 = new TinyIntVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
byte val = -128;
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, val);
val++;
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
val = -128;
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
assertEquals(val, vector1.get(i), "unexpected value at index: " + i);
val++;
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
val = -128;
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
assertEquals(val, vector2.get(i), "unexpected value at index: " + i);
val++;
}
}
}
}
@Test /* DecimalVector */
public void testCopyFromWithNulls13() {
try (final DecimalVector vector1 = new DecimalVector(EMPTY_SCHEMA_PATH, allocator, 30, 16);
final DecimalVector vector2 = new DecimalVector(EMPTY_SCHEMA_PATH, allocator, 30, 16)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
final double baseValue = 104567897654.87654;
final BigDecimal[] decimals = new BigDecimal[4096];
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
BigDecimal decimal = new BigDecimal(baseValue + (double) i);
vector1.setSafe(i, decimal);
decimals[i] = decimal;
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
final BigDecimal decimal = vector1.getObject(i);
assertEquals(decimals[i], decimal);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
final BigDecimal decimal = vector2.getObject(i);
assertEquals(decimals[i], decimal);
}
}
}
}
@Test /* TimeStampVector */
public void testCopyFromWithNulls14() {
try (final TimeStampVector vector1 = new TimeStampMicroVector(EMPTY_SCHEMA_PATH, allocator);
final TimeStampVector vector2 = new TimeStampMicroVector(EMPTY_SCHEMA_PATH, allocator)) {
vector1.allocateNew();
assertTrue(vector1.getValueCapacity() >= vector1.INITIAL_VALUE_ALLOCATION);
assertEquals(0, vector1.getValueCount());
int initialCapacity = vector1.getValueCapacity();
final long val = 20145678912L;
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
continue;
}
vector1.setSafe(i, val + (long) i);
}
vector1.setValueCount(initialCapacity);
/* No realloc should have happened in setSafe or
* setValueCount
*/
assertEquals(initialCapacity, vector1.getValueCapacity());
assertEquals(initialCapacity, vector1.getValueCount());
for (int i = 0; i < initialCapacity; i++) {
if ((i & 1) == 0) {
assertNull(vector1.getObject(i));
} else {
assertEquals(val + (long) i, vector1.get(i), "unexpected value at index: " + i);
}
}
/* set lesser initial capacity than actually needed
* to trigger reallocs in copyFromSafe()
*/
vector2.allocateNew(initialCapacity / 4);
assertTrue(vector2.getValueCapacity() >= initialCapacity / 4);
assertTrue(vector2.getValueCapacity() < initialCapacity / 2);
for (int i = 0; i < initialCapacity; i++) {
vector2.copyFromSafe(i, i, vector1);
}
/* 2 realloc should have happened in copyFromSafe() */
assertTrue(vector2.getValueCapacity() >= initialCapacity);
vector2.setValueCount(initialCapacity * 2);
/* setValueCount() should have done another realloc */
assertEquals(initialCapacity * 2, vector2.getValueCount());
assertTrue(vector2.getValueCapacity() >= initialCapacity * 2);
/* check vector data after copy and realloc */
for (int i = 0; i < initialCapacity * 2; i++) {
if (((i & 1) == 0) || (i >= initialCapacity)) {
assertNull(vector2.getObject(i));
} else {
assertEquals(val + (long) i, vector2.get(i), "unexpected value at index: " + i);
}
}
}
}
@Test // https://issues.apache.org/jira/browse/ARROW-7837
public void testCopySafeArrow7837() {
// this test exposes a bug in `handleSafe` where
// it reads a stale index and as a result missed a required resize of the value vector.
try (VarCharVector vc1 = new VarCharVector("vc1", allocator);
VarCharVector vc2 = new VarCharVector("vc2", allocator); ) {
// initial size is carefully set in order to force the second 'copyFromSafe' operation
// to trigger a reallocation of the vector.
vc2.setInitialCapacity(/*valueCount*/ 20, /*density*/ 0.5);
vc1.setSafe(0, "1234567890".getBytes(StandardCharsets.UTF_8));
assertFalse(vc1.isNull(0));
assertEquals("1234567890", Objects.requireNonNull(vc1.getObject(0)).toString());
vc2.copyFromSafe(0, 0, vc1);
assertFalse(vc2.isNull(0));
assertEquals("1234567890", Objects.requireNonNull(vc2.getObject(0)).toString());
vc2.copyFromSafe(0, 5, vc1);
assertTrue(vc2.isNull(1));
assertTrue(vc2.isNull(2));
assertTrue(vc2.isNull(3));
assertTrue(vc2.isNull(4));
assertFalse(vc2.isNull(5));
assertEquals("1234567890", Objects.requireNonNull(vc2.getObject(5)).toString());
}
}
}