/**
* Copyright 2014 National University of Ireland, Galway.
*
* This file is part of the SIREn project. Project and contact information:
*
* https://github.com/rdelbru/SIREn
*
* 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 org.sindice.siren.index.codecs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.IntsRef;
import org.apache.lucene.util._TestUtil;
import org.junit.After;
import org.junit.Before;
import org.sindice.siren.index.codecs.block.BlockCompressor;
import org.sindice.siren.index.codecs.block.BlockDecompressor;
import org.sindice.siren.util.SirenTestCase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class CodecTestCase extends SirenTestCase {
private static final int MIN_LIST_SIZE = 32768;
protected Directory directory;
@Override
@Before
public void setUp()
throws Exception {
super.setUp();
directory = newDirectory();
}
@Override
@After
public void tearDown()
throws Exception {
directory.close();
super.tearDown();
}
/**
* The different block sizes to test
*/
protected static final int[] BLOCK_SIZES = {32, 64, 128, 256, 512, 1024, 2048};
protected static final Logger logger = LoggerFactory.getLogger(CodecTestCase.class);
/**
* Generate a random long value uniformly distributed between
* <code>lower</code> and <code>upper</code>, inclusive.
*
* @param lower
* the lower bound.
* @param upper
* the upper bound.
* @return the random integer.
* @throws IllegalArgumentException if {@code lower >= upper}.
*/
protected long nextLong(final long lower, final long upper) {
if (lower >= upper) {
throw new IllegalArgumentException();
}
final double r = random().nextDouble();
return (long) ((r * upper) + ((1.0 - r) * lower) + r);
}
private void doTest(final int[] values, final int blockSize,
final BlockCompressor compressor,
final BlockDecompressor decompressor)
throws Exception {
final BytesRef compressedData = new BytesRef(compressor.maxCompressedSize(blockSize));
final IntsRef input = new IntsRef(blockSize);
final IntsRef output = new IntsRef(blockSize);
for (int i = 0; i < values.length; i += blockSize) {
int offset = 0;
// copy first block into the uncompressed data buffer
for (int j = i; offset < blockSize && j < values.length; j++, offset++) {
input.ints[offset] = values[j];
}
input.offset = 0;
input.length = offset;
// compress
compressor.compress(input, compressedData);
// decompress
decompressor.decompress(compressedData, output);
// check if they are equals
for (int j = 0; j < input.length; j++) {
assertEquals(input.ints[j], output.ints[j]);
}
}
}
public void doTestIntegerRange(final int minBits, final int maxBits, final int[] blockSizes,
final BlockCompressor compressor,
final BlockDecompressor decompressor)
throws Exception {
for (int i = minBits; i <= maxBits; i++) {
// different length for each run
final int length = _TestUtil.nextInt(random(), MIN_LIST_SIZE, MIN_LIST_SIZE * 2);
final int[] input = new int[length];
final long min = i == 1 ? 0 : (1L << (i - 1));
final long max = ((1L << i) - 1);
// generate integers per frame of max 8 ints
for (int j = 0; j < length; j += 8) {
final int size = j + 8 < length ? 8 : length - j;
// generate randomly a sequence of 8 zero integers, in order to force
// frame-based compression to use instructions for different frame sizes
final boolean bool = random().nextBoolean();
int[] ints;
if (bool) {
ints = this.getRandomInteger(size, min, max);
}
else {
ints = new int[size]; // initialised by default with 0
}
System.arraycopy(ints, 0, input, j, ints.length);
}
for (final int blockSize : blockSizes) {
// logger.debug("Perform Integer Range Test: length = {}, bits = {}, block size = {}",
// new Object[]{length, i, blockSize});
this.doTest(input, blockSize, compressor, decompressor);
}
}
}
private int[] getRandomInteger(final int size, final long min, final long max) {
final int[] ints = new int[size];
for (int i = 0; i < size; i++) {
ints[i] = (int) this.nextLong(min, max);;
}
return ints;
}
public void doTestIntegerRange(final int minBits, final int maxBits,
final BlockCompressor compressor,
final BlockDecompressor decompressor)
throws Exception {
this.doTestIntegerRange(minBits, maxBits, BLOCK_SIZES, compressor, decompressor);
}
}