/**
* diqube: Distributed Query Base.
*
* Copyright (C) 2015 Bastian Gloeckle
*
* This file is part of diqube.
*
* diqube is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diqube.data.types.lng.compression;
import java.util.Arrays;
import java.util.function.Supplier;
import org.diqube.data.types.lng.array.CompressedLongArray;
import org.diqube.data.types.lng.array.ExplorableCompressedLongArray;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.testng.internal.junit.ArrayComparisonFailure;
/**
* Abstract implementation of {@link CompressedLongArray} tests.
*
* @author Bastian Gloeckle
*/
public abstract class AbstractCompressedLongArrayTest {
private Supplier<ExplorableCompressedLongArray<?>> longArraySupplier;
private TestCompressor compressor;
public AbstractCompressedLongArrayTest(Supplier<ExplorableCompressedLongArray<?>> longArraySupplier,
TestCompressor compressor) {
this.longArraySupplier = longArraySupplier;
this.compressor = compressor;
}
public AbstractCompressedLongArrayTest(Supplier<ExplorableCompressedLongArray<?>> longArraySupplier) {
this(longArraySupplier, (longArray, values, isSorted) -> longArray.compress(values, isSorted));
}
@Test
public void exponentTest() {
// GIVEN
// arrays 0..1, 0..2, 0..4, 0..2^n up until n=63
// array containing 2^n for n=0..62
for (int exponent = 0; exponent <= 63; exponent++) {
long[] values = new long[exponent + 1];
values[0] = 1;
for (int i = 1; i < values.length; i++) {
values[i] = values[i - 1] << 1;
}
executeCompressionAndValidate(values, " (exponent == " + exponent + ")");
}
}
@Test
public void exponentNegativeTest() {
// GIVEN
// arrays 0..1, 0..2, 0..4, 0..2^n up until n=63
// array containing 2^n for n=0..62
for (int exponent = 0; exponent <= 63; exponent++) {
long[] values = new long[2 * (exponent + 1)];
values[0] = 1;
values[exponent] = -1;
for (int i = 1; i <= exponent; i++) {
values[i] = values[i - 1] << 1;
values[exponent + 1 + i] = values[exponent + i] << 1;
}
executeCompressionAndValidate(values, " (exponent == " + exponent + ")");
}
}
@Test
public void to63Test() {
// GIVEN
// array containing 0..63
long[] values = new long[64];
for (int i = 0; i < 64; i++) {
values[i] = i;
}
executeCompressionAndValidate(values, null);
}
@Test
public void minus63Test() {
// GIVEN
// array containing -63..63
long[] values = new long[2 * 64 + 1];
values[0] = -63;
for (int i = 1; i < values.length; i++) {
values[i] = values[i - 1] + 1;
}
executeCompressionAndValidate(values, null);
}
@Test
public void minus128Test() {
// GIVEN
// array containing -63..63
long[] values = new long[2 * 129 + 1];
values[0] = -128;
for (int i = 1; i < values.length; i++) {
values[i] = values[i - 1] + 1;
}
executeCompressionAndValidate(values, null);
}
@Test
public void minValueOnlyTest() {
// GIVEN
long[] values = new long[] { Long.MIN_VALUE, Long.MIN_VALUE, Long.MIN_VALUE, Long.MIN_VALUE };
executeCompressionAndValidate(values, null);
}
@Test
public void minValueAndZeroTest() {
// GIVEN
long[] values = new long[] { Long.MIN_VALUE, Long.MIN_VALUE, Long.MIN_VALUE, 0 };
executeCompressionAndValidate(values, null);
}
@Test
public void zeroTest() {
// GIVEN
long[] values = new long[] { 0, 0 };
executeCompressionAndValidate(values, null);
}
@Test
public void minMaxValueTest() {
// GIVEN
long[] values = new long[] { Long.MIN_VALUE, Long.MIN_VALUE, Long.MAX_VALUE, 0 };
executeCompressionAndValidate(values, null);
}
@Test
public void minValuePlus1000Test() {
// GIVEN
long[] values = new long[1001];
values[0] = Long.MIN_VALUE;
for (int i = 1; i < values.length; i++)
values[i] = values[i - 1] + 1;
executeCompressionAndValidate(values, null);
}
@Test
public void maxValueMinus1000Test() {
// GIVEN
long[] values = new long[1001];
values[0] = Long.MAX_VALUE;
for (int i = 1; i < values.length; i++)
values[i] = values[i - 1] - 1;
executeCompressionAndValidate(values, null);
}
private void executeCompressionAndValidate(long[] values, String assertionText) throws ArrayComparisonFailure {
ExplorableCompressedLongArray<?> longArray = longArraySupplier.get();
compressor.compress(longArray, values, false);
long[] decompressed = longArray.decompressedArray();
String txt = "Decompressed (sorted = false) values should match original ones";
if (assertionText != null)
txt += assertionText;
Assert.assertEquals(decompressed, values, txt);
long[] decompressedSingleValues = new long[values.length];
for (int i = 0; i < values.length; i++)
decompressedSingleValues[i] = longArray.get(i);
Assert.assertEquals(decompressedSingleValues, decompressed,
"Expected get(i) to return same values as decompressedArray()");
// make sure values are sorted and run again with sorted = true
Arrays.sort(values);
longArray = longArraySupplier.get();
compressor.compress(longArray, values, true);
decompressed = longArray.decompressedArray();
txt = "Decompressed (sorted = true) values should match original ones";
if (assertionText != null)
txt += assertionText;
Assert.assertEquals(decompressed, values, txt);
decompressedSingleValues = new long[values.length];
for (int i = 0; i < values.length; i++)
decompressedSingleValues[i] = longArray.get(i);
Assert.assertEquals(decompressedSingleValues, decompressed,
"Expected get(i) to return same values as decompressedArray() - sorted");
}
protected static interface TestCompressor {
public void compress(ExplorableCompressedLongArray<?> longArray, long[] values, boolean isSorted);
}
}