You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
220 lines
5.3 KiB
JavaScript
220 lines
5.3 KiB
JavaScript
import { Heap } from "../../Source/Cesium.js";
|
|
|
|
describe("Core/Heap", function () {
|
|
var length = 100;
|
|
|
|
function expectTrailingReferenceToBeRemoved(heap) {
|
|
var array = heap._array;
|
|
var length = heap._length;
|
|
var reservedLength = array.length;
|
|
for (var i = length; i < reservedLength; ++i) {
|
|
expect(array[i]).toBeUndefined();
|
|
}
|
|
}
|
|
|
|
function checkHeap(heap, comparator) {
|
|
var array = heap.internalArray;
|
|
var pass = true;
|
|
var length = heap.length;
|
|
for (var i = 0; i < length; ++i) {
|
|
var left = 2 * (i + 1) - 1;
|
|
var right = 2 * (i + 1);
|
|
if (left < heap.length) {
|
|
pass = pass && comparator(array[i], array[left]) <= 0;
|
|
}
|
|
if (right < heap.length) {
|
|
pass = pass && comparator(array[i], array[right]) <= 0;
|
|
}
|
|
}
|
|
return pass;
|
|
}
|
|
|
|
// min heap
|
|
function comparator(a, b) {
|
|
return a - b;
|
|
}
|
|
|
|
it("maintains heap property on insert", function () {
|
|
var heap = new Heap({
|
|
comparator: comparator,
|
|
});
|
|
var pass = true;
|
|
for (var i = 0; i < length; ++i) {
|
|
heap.insert(Math.random());
|
|
pass = pass && checkHeap(heap, comparator);
|
|
}
|
|
|
|
expect(pass).toBe(true);
|
|
});
|
|
|
|
it("maintains heap property on pop", function () {
|
|
var heap = new Heap({
|
|
comparator: comparator,
|
|
});
|
|
var i;
|
|
for (i = 0; i < length; ++i) {
|
|
heap.insert(Math.random());
|
|
}
|
|
var pass = true;
|
|
for (i = 0; i < length; ++i) {
|
|
heap.pop();
|
|
pass = pass && checkHeap(heap, comparator);
|
|
}
|
|
expect(pass).toBe(true);
|
|
});
|
|
|
|
it("limited by maximum length", function () {
|
|
var heap = new Heap({
|
|
comparator: comparator,
|
|
});
|
|
heap.maximumLength = length / 2;
|
|
var pass = true;
|
|
for (var i = 0; i < length; ++i) {
|
|
heap.insert(Math.random());
|
|
pass = pass && checkHeap(heap, comparator);
|
|
}
|
|
expect(pass).toBe(true);
|
|
expect(heap.length).toBeLessThanOrEqualTo(heap.maximumLength);
|
|
// allowed one extra slot for swapping
|
|
expect(heap.internalArray.length).toBeLessThanOrEqualTo(
|
|
heap.maximumLength + 1
|
|
);
|
|
});
|
|
|
|
it("pops in sorted order", function () {
|
|
var heap = new Heap({
|
|
comparator: comparator,
|
|
});
|
|
var i;
|
|
for (i = 0; i < length; ++i) {
|
|
heap.insert(Math.random());
|
|
}
|
|
var curr = heap.pop();
|
|
var pass = true;
|
|
for (i = 0; i < length - 1; ++i) {
|
|
var next = heap.pop();
|
|
pass = pass && comparator(curr, next) <= 0;
|
|
curr = next;
|
|
}
|
|
expect(pass).toBe(true);
|
|
});
|
|
|
|
it("pop removes trailing references", function () {
|
|
var heap = new Heap({
|
|
comparator: comparator,
|
|
});
|
|
|
|
for (var i = 0; i < 10; ++i) {
|
|
heap.insert(Math.random());
|
|
}
|
|
|
|
heap.pop();
|
|
heap.pop();
|
|
|
|
expectTrailingReferenceToBeRemoved(heap);
|
|
});
|
|
|
|
it("setting maximum length less than current length removes trailing references", function () {
|
|
var heap = new Heap({
|
|
comparator: comparator,
|
|
});
|
|
|
|
for (var i = 0; i < 10; ++i) {
|
|
heap.insert(Math.random());
|
|
}
|
|
|
|
heap.maximumLength = 5;
|
|
expectTrailingReferenceToBeRemoved(heap);
|
|
});
|
|
|
|
it("insert returns the removed element when maximumLength is set", function () {
|
|
var heap = new Heap({
|
|
comparator: comparator,
|
|
});
|
|
heap.maximumLength = length;
|
|
|
|
var i;
|
|
var max = 0.0;
|
|
var min = 1.0;
|
|
var values = new Array(length);
|
|
for (i = 0; i < length; ++i) {
|
|
var value = Math.random();
|
|
max = Math.max(max, value);
|
|
min = Math.min(min, value);
|
|
values[i] = value;
|
|
}
|
|
|
|
// Push 99 values
|
|
for (i = 0; i < length - 1; ++i) {
|
|
heap.insert(values[i]);
|
|
}
|
|
|
|
// Push 100th, nothing is removed so it returns undefined
|
|
var removed = heap.insert(values[length - 1]);
|
|
expect(removed).toBeUndefined();
|
|
|
|
// Insert value, an element is removed
|
|
removed = heap.insert(max - 0.1);
|
|
expect(removed).toBeDefined();
|
|
|
|
// If this value is the least priority it will be returned
|
|
removed = heap.insert(max + 0.1);
|
|
expect(removed).toBe(max + 0.1);
|
|
});
|
|
|
|
it("resort", function () {
|
|
function comparator(a, b) {
|
|
return a.distance - b.distance;
|
|
}
|
|
|
|
var i;
|
|
var heap = new Heap({
|
|
comparator: comparator,
|
|
});
|
|
for (i = 0; i < length; ++i) {
|
|
heap.insert({
|
|
distance: i / (length - 1),
|
|
id: i,
|
|
});
|
|
}
|
|
|
|
// Check that elements are initially sorted
|
|
var element;
|
|
var elements = [];
|
|
var currentId = 0;
|
|
while (heap.length > 0) {
|
|
element = heap.pop();
|
|
elements.push(element);
|
|
expect(element.id).toBeGreaterThanOrEqualTo(currentId);
|
|
currentId = element.id;
|
|
}
|
|
|
|
// Add back into heap
|
|
for (i = 0; i < length; ++i) {
|
|
heap.insert(elements[i]);
|
|
}
|
|
|
|
// Invert priority
|
|
for (i = 0; i < length; ++i) {
|
|
elements[i].distance = 1.0 - elements[i].distance;
|
|
}
|
|
|
|
// Resort and check the the elements are popped in the opposite order now
|
|
heap.resort();
|
|
while (heap.length > 0) {
|
|
element = heap.pop();
|
|
expect(element.id).toBeLessThanOrEqualTo(currentId);
|
|
currentId = element.id;
|
|
}
|
|
});
|
|
|
|
it("maximumLength setter throws if length is less than 0", function () {
|
|
var heap = new Heap({
|
|
comparator: comparator,
|
|
});
|
|
expect(function () {
|
|
heap.maximumLength = -1;
|
|
}).toThrowDeveloperError();
|
|
});
|
|
});
|