blob: 63245c78b3061b4800fcb86d1f97b7ea21ba4150 [file] [log] [blame]
/*
* 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.druid.query.groupby.epinephelinae;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import org.junit.Assert;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class ByteBufferMinMaxOffsetHeapTest
{
@Test
public void testSimple()
{
int limit = 15;
ByteBuffer myBuffer = ByteBuffer.allocate(1000000);
ByteBufferMinMaxOffsetHeap heap = new ByteBufferMinMaxOffsetHeap(myBuffer, limit, Ordering.natural(), null);
//CHECKSTYLE.OFF: Regexp
ArrayList<Integer> values = Lists.newArrayList(
30, 45, 81, 92, 68, 54, 66, 33, 89, 98,
87, 62, 84, 39, 13, 32, 67, 50, 21, 53,
93, 18, 86, 41, 14, 56, 51, 69, 91, 60,
6, 2, 79, 4, 35, 17, 71, 22, 29, 76,
57, 97, 73, 24, 94, 77, 80, 15, 52, 88,
95, 96, 9, 3, 48, 58, 75, 82, 90, 65,
36, 85, 20, 34, 37, 72, 11, 78, 28, 43,
27, 12, 83, 38, 59, 19, 31, 46, 40, 63,
23, 70, 26, 8, 64, 16, 10, 74, 7, 25,
5, 42, 47, 44, 1, 49, 99
);
//CHECKSTYLE.ON: Regexp
for (Integer value : values) {
heap.addOffset(value);
}
int x = heap.removeAt(8);
heap.addOffset(x);
x = heap.removeAt(2);
heap.addOffset(x);
Collections.sort(values);
List<Integer> expected = values.subList(0, limit);
List<Integer> actual = new ArrayList<>();
for (int i = 0; i < limit; i++) {
int min = heap.removeMin();
actual.add(min);
}
Assert.assertEquals(expected, actual);
}
@Test
public void testRandom()
{
int limit = 20;
Random rng = new Random(999);
ArrayList<Integer> values = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
values.add(rng.nextInt(1000000));
}
ArrayList<Integer> deletedValues = new ArrayList<>();
ByteBuffer myBuffer = ByteBuffer.allocate(1000000);
ByteBufferMinMaxOffsetHeap heap = new ByteBufferMinMaxOffsetHeap(myBuffer, limit, Ordering.natural(), null);
for (int i = 0; i < values.size(); i++) {
int droppedOffset = heap.addOffset(values.get(i));
Assert.assertTrue(heap.isIntact());
if (droppedOffset > 0) {
deletedValues.add(droppedOffset);
}
// 15% chance to delete a random value for every two values added when heap is > 50% full
if (heap.getHeapSize() > (limit / 2) && i % 2 == 1) {
double deleteRoll = rng.nextDouble();
if (deleteRoll > 0.15) {
int indexToRemove = rng.nextInt(heap.getHeapSize());
int deadOffset = heap.removeAt(indexToRemove);
Assert.assertTrue(heap.isIntact());
deletedValues.add(deadOffset);
}
}
}
Collections.sort(values);
Collections.sort(deletedValues);
for (int deletedValue : deletedValues) {
int idx = values.indexOf(deletedValue);
values.remove(idx);
}
Assert.assertTrue(heap.getHeapSize() <= limit);
List<Integer> expected = values.subList(0, heap.getHeapSize());
List<Integer> actual = new ArrayList<>();
int initialHeapSize = heap.getHeapSize();
for (int i = 0; i < initialHeapSize; i++) {
int min = heap.removeMin();
actual.add(min);
}
Assert.assertEquals(expected, actual);
}
@Test
public void testRandom2()
{
int limit = 5000;
Random rng = new Random(9999);
ArrayList<Integer> values = new ArrayList<>();
for (int i = 0; i < 20000; i++) {
values.add(rng.nextInt(1000000));
}
ArrayList<Integer> deletedValues = new ArrayList<>();
ByteBuffer myBuffer = ByteBuffer.allocate(1000000);
ByteBufferMinMaxOffsetHeap heap = new ByteBufferMinMaxOffsetHeap(myBuffer, limit, Ordering.natural(), null);
for (int i = 0; i < values.size(); i++) {
int droppedOffset = heap.addOffset(values.get(i));
Assert.assertTrue(heap.isIntact());
if (droppedOffset > 0) {
deletedValues.add(droppedOffset);
}
// 15% chance to delete a random value for every two values added when heap is > 50% full
if (heap.getHeapSize() > (limit / 2) && i % 2 == 1) {
double deleteRoll = rng.nextDouble();
if (deleteRoll > 0.15) {
int indexToRemove = rng.nextInt(heap.getHeapSize());
int deadOffset = heap.removeAt(indexToRemove);
Assert.assertTrue(heap.isIntact());
deletedValues.add(deadOffset);
}
}
}
Collections.sort(values);
Collections.sort(deletedValues);
for (int deletedValue : deletedValues) {
int idx = values.indexOf(deletedValue);
values.remove(idx);
}
Assert.assertTrue(heap.getHeapSize() <= limit);
List<Integer> expected = values.subList(0, heap.getHeapSize());
List<Integer> actual = new ArrayList<>();
int initialHeapSize = heap.getHeapSize();
for (int i = 0; i < initialHeapSize; i++) {
int min = heap.removeMin();
actual.add(min);
}
Assert.assertEquals(expected, actual);
}
@Test
public void testRemove()
{
int limit = 100;
IntList values = new IntArrayList(new int[] {
1, 20, 1000, 2, 3, 30, 40, 10, 11, 12, 13, 300, 400, 500, 600
});
ByteBuffer myBuffer = ByteBuffer.allocate(1000000);
ByteBufferMinMaxOffsetHeap heap = new ByteBufferMinMaxOffsetHeap(myBuffer, limit, Ordering.natural(), null);
for (Integer value : values) {
heap.addOffset(value);
Assert.assertTrue(heap.isIntact());
}
heap.removeOffset(12);
Assert.assertTrue(heap.isIntact());
Collections.sort(values);
values.rem(12);
List<Integer> actual = new ArrayList<>();
for (int i = 0; i < values.size(); i++) {
int min = heap.removeMin();
actual.add(min);
}
Assert.assertEquals(values, actual);
}
@Test
public void testRemove2()
{
int limit = 100;
IntList values = new IntArrayList(new int[] {
1, 20, 1000, 2, 3, 30, 40, 10, 11, 12, 13, 300, 400, 500, 600, 4, 5,
6, 7, 8, 9, 4, 5, 200, 250
});
ByteBuffer myBuffer = ByteBuffer.allocate(1000000);
ByteBufferMinMaxOffsetHeap heap = new ByteBufferMinMaxOffsetHeap(myBuffer, limit, Ordering.natural(), null);
for (Integer value : values) {
heap.addOffset(value);
}
Assert.assertTrue(heap.isIntact());
heap.removeOffset(2);
Assert.assertTrue(heap.isIntact());
Collections.sort(values);
values.rem(2);
Assert.assertTrue(heap.isIntact());
List<Integer> actual = new ArrayList<>();
for (int i = 0; i < values.size(); i++) {
int min = heap.removeMin();
actual.add(min);
}
Assert.assertTrue(heap.isIntact());
Assert.assertEquals(values, actual);
}
}