Organize tests
This commit is contained in:
265
test/browser/spec/ol/structs/linkedlist.test.js
Normal file
265
test/browser/spec/ol/structs/linkedlist.test.js
Normal file
@@ -0,0 +1,265 @@
|
||||
import LinkedList from '../../../../../src/ol/structs/LinkedList.js';
|
||||
|
||||
describe('ol.structs.LinkedList', function () {
|
||||
let ll;
|
||||
const item = {};
|
||||
const item2 = {};
|
||||
beforeEach(function () {
|
||||
ll = new LinkedList();
|
||||
});
|
||||
|
||||
it('defaults to circular', function () {
|
||||
expect(ll.circular_).to.be(true);
|
||||
});
|
||||
|
||||
it('creates an empty list', function () {
|
||||
expect(ll.length_).to.be(0);
|
||||
expect(ll.first_).to.be(undefined);
|
||||
expect(ll.last_).to.be(undefined);
|
||||
expect(ll.head_).to.be(undefined);
|
||||
});
|
||||
|
||||
describe('#insertItem', function () {
|
||||
beforeEach(function () {
|
||||
ll.insertItem(item);
|
||||
});
|
||||
|
||||
it('inserts an item into the list', function () {
|
||||
expect(ll.length_).to.be(1);
|
||||
});
|
||||
|
||||
it('sets the cursor to the inserted item', function () {
|
||||
expect(ll.head_.data).to.be(item);
|
||||
});
|
||||
|
||||
it('links the previous item to the new one', function () {
|
||||
ll.insertItem(item2);
|
||||
expect(ll.head_.prev.data).to.be(item);
|
||||
expect(ll.head_.prev.next.data).to.be(item2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#removeItem', function () {
|
||||
const item3 = {};
|
||||
beforeEach(function () {
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
ll.insertItem(item3);
|
||||
});
|
||||
|
||||
it('removes the current item', function () {
|
||||
ll.removeItem();
|
||||
expect(ll.length_).to.be(2);
|
||||
expect(ll.head_.data).not.to.be(item3);
|
||||
});
|
||||
|
||||
it('sets the cursor to the next item if possible', function () {
|
||||
ll.removeItem();
|
||||
expect(ll.head_.data).to.be(item);
|
||||
});
|
||||
|
||||
it('otherwise sets the cursor to the previous item', function () {
|
||||
ll = new LinkedList(false);
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
ll.insertItem(item3);
|
||||
ll.removeItem();
|
||||
expect(ll.head_.data).to.be(item2);
|
||||
});
|
||||
|
||||
it('empties a list with only one item', function () {
|
||||
ll = new LinkedList();
|
||||
ll.insertItem(item);
|
||||
ll.removeItem();
|
||||
expect(ll.length_).to.be(0);
|
||||
expect(ll.head_).to.be(undefined);
|
||||
expect(ll.first_).to.be(undefined);
|
||||
expect(ll.last_).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#firstItem', function () {
|
||||
it('sets the cursor to the first item and returns its data', function () {
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
const i = ll.firstItem();
|
||||
expect(i).to.be(item);
|
||||
expect(ll.head_.data).to.be(item);
|
||||
});
|
||||
|
||||
it('returns undefined on empty list', function () {
|
||||
const i = ll.firstItem();
|
||||
expect(i).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#lastItem', function () {
|
||||
it('sets the cursor to the last item and returns its data', function () {
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
ll.firstItem();
|
||||
const i = ll.lastItem();
|
||||
expect(i).to.be(item2);
|
||||
expect(ll.head_.data).to.be(item2);
|
||||
});
|
||||
|
||||
it('returns undefined on empty list', function () {
|
||||
const i = ll.lastItem();
|
||||
expect(i).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#nextItem', function () {
|
||||
it('sets the cursor to the next item and returns its data', function () {
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
ll.firstItem();
|
||||
const i = ll.nextItem();
|
||||
expect(i).to.be(item2);
|
||||
expect(ll.head_.data).to.be(item2);
|
||||
});
|
||||
|
||||
it('returns undefined on empty list', function () {
|
||||
const i = ll.nextItem();
|
||||
expect(i).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#prevItem', function () {
|
||||
it('sets the cursor to the previous item and returns its data', function () {
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
const i = ll.prevItem();
|
||||
expect(i).to.be(item);
|
||||
expect(ll.head_.data).to.be(item);
|
||||
});
|
||||
|
||||
it('returns undefined on empty list', function () {
|
||||
const i = ll.prevItem();
|
||||
expect(i).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getNextItem', function () {
|
||||
it('returns the data of the next item without stepping the cursor', function () {
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
ll.firstItem();
|
||||
const i = ll.getNextItem();
|
||||
expect(i).to.be(item2);
|
||||
expect(ll.head_.data).to.be(item);
|
||||
});
|
||||
|
||||
it('returns undefined on empty list', function () {
|
||||
const i = ll.getNextItem();
|
||||
expect(i).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getPrevItem', function () {
|
||||
it('returns the data of the previous item without stepping the cursor', function () {
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
const i = ll.getPrevItem();
|
||||
expect(i).to.be(item);
|
||||
expect(ll.head_.data).to.be(item2);
|
||||
});
|
||||
|
||||
it('returns undefined on empty list', function () {
|
||||
const i = ll.getPrevItem();
|
||||
expect(i).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getCurrItem', function () {
|
||||
it('returns the data of the current item', function () {
|
||||
const item3 = {};
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
ll.insertItem(item3);
|
||||
ll.prevItem();
|
||||
const i = ll.getCurrItem();
|
||||
expect(i).to.be(item2);
|
||||
expect(ll.head_.data).to.be(item2);
|
||||
});
|
||||
|
||||
it('returns undefined on empty list', function () {
|
||||
const i = ll.getCurrItem();
|
||||
expect(i).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getLength', function () {
|
||||
it('returns the length of the list', function () {
|
||||
ll.insertItem(item);
|
||||
ll.insertItem(item2);
|
||||
const l = ll.getLength();
|
||||
expect(l).to.be(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#concat', function () {
|
||||
let ll2, item3;
|
||||
beforeEach(function () {
|
||||
item3 = {};
|
||||
ll2 = new LinkedList();
|
||||
ll2.insertItem(item);
|
||||
ll2.insertItem(item2);
|
||||
ll2.insertItem(item3);
|
||||
});
|
||||
|
||||
it('concatenates a second list with the current one', function () {
|
||||
const item4 = {};
|
||||
const item5 = {};
|
||||
const item6 = {};
|
||||
ll.insertItem(item4);
|
||||
ll.insertItem(item5);
|
||||
ll.insertItem(item6);
|
||||
ll.prevItem();
|
||||
ll.concat(ll2);
|
||||
expect(ll.length_).to.be(6);
|
||||
expect(ll.head_.data).to.be(item5);
|
||||
expect(ll.head_.next.data).to.be(item);
|
||||
expect(ll.head_.next.next.next.next.data).to.be(item6);
|
||||
});
|
||||
|
||||
it('receives the second list if the current one is empty', function () {
|
||||
ll.concat(ll2);
|
||||
expect(ll.length_).to.be(3);
|
||||
expect(ll.first_.data).to.be(item);
|
||||
expect(ll.last_.data).to.be(item3);
|
||||
expect(ll.head_.data).to.be(item3);
|
||||
});
|
||||
|
||||
it('destroys the second list', function () {
|
||||
ll.concat(ll2);
|
||||
expect(ll2.length_).to.be(0);
|
||||
expect(ll2.first_).to.be(undefined);
|
||||
expect(ll2.last_).to.be(undefined);
|
||||
expect(ll2.head_).to.be(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when circular', function () {
|
||||
beforeEach(function () {
|
||||
ll = new LinkedList();
|
||||
ll.insertItem(item);
|
||||
});
|
||||
|
||||
describe('#insertItem', function () {
|
||||
it('initializes the list in a circular way', function () {
|
||||
expect(ll.head_.prev.data).to.be(item);
|
||||
expect(ll.head_.next.data).to.be(item);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setFirstItem', function () {
|
||||
it('resets the first item to the current one', function () {
|
||||
ll.insertItem(item2);
|
||||
ll.setFirstItem();
|
||||
expect(ll.first_.data).to.be(item2);
|
||||
expect(ll.last_.data).to.be(item);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
292
test/browser/spec/ol/structs/lrucache.test.js
Normal file
292
test/browser/spec/ol/structs/lrucache.test.js
Normal file
@@ -0,0 +1,292 @@
|
||||
import LRUCache from '../../../../../src/ol/structs/LRUCache.js';
|
||||
|
||||
describe('ol.structs.LRUCache', function () {
|
||||
let lruCache;
|
||||
|
||||
function fillLRUCache(lruCache) {
|
||||
lruCache.set('a', 0);
|
||||
lruCache.set('b', 1);
|
||||
lruCache.set('c', 2);
|
||||
lruCache.set('d', 3);
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
lruCache = new LRUCache();
|
||||
});
|
||||
|
||||
describe('empty cache', function () {
|
||||
it('has size zero', function () {
|
||||
expect(lruCache.getCount()).to.eql(0);
|
||||
});
|
||||
it('has no keys', function () {
|
||||
expect(lruCache.getKeys()).to.eql([]);
|
||||
});
|
||||
it('has no values', function () {
|
||||
expect(lruCache.getValues()).to.eql([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('populating', function () {
|
||||
it('returns the correct size', function () {
|
||||
fillLRUCache(lruCache);
|
||||
expect(lruCache.getCount()).to.eql(4);
|
||||
});
|
||||
it('contains the correct keys in the correct order', function () {
|
||||
fillLRUCache(lruCache);
|
||||
expect(lruCache.getKeys()).to.eql(['d', 'c', 'b', 'a']);
|
||||
});
|
||||
it('contains the correct values in the correct order', function () {
|
||||
fillLRUCache(lruCache);
|
||||
expect(lruCache.getValues()).to.eql([3, 2, 1, 0]);
|
||||
});
|
||||
it('reports which keys are contained', function () {
|
||||
fillLRUCache(lruCache);
|
||||
expect(lruCache.containsKey('a')).to.be.ok();
|
||||
expect(lruCache.containsKey('b')).to.be.ok();
|
||||
expect(lruCache.containsKey('c')).to.be.ok();
|
||||
expect(lruCache.containsKey('d')).to.be.ok();
|
||||
expect(lruCache.containsKey('e')).to.not.be();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getting the oldest key', function () {
|
||||
it('moves the key to newest position', function () {
|
||||
fillLRUCache(lruCache);
|
||||
lruCache.get('a');
|
||||
expect(lruCache.getCount()).to.eql(4);
|
||||
expect(lruCache.getKeys()).to.eql(['a', 'd', 'c', 'b']);
|
||||
expect(lruCache.getValues()).to.eql([0, 3, 2, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getting a key in the middle', function () {
|
||||
it('moves the key to newest position', function () {
|
||||
fillLRUCache(lruCache);
|
||||
lruCache.get('b');
|
||||
expect(lruCache.getCount()).to.eql(4);
|
||||
expect(lruCache.getKeys()).to.eql(['b', 'd', 'c', 'a']);
|
||||
expect(lruCache.getValues()).to.eql([1, 3, 2, 0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getting the newest key', function () {
|
||||
it('maintains the key to newest position', function () {
|
||||
fillLRUCache(lruCache);
|
||||
lruCache.get('d');
|
||||
expect(lruCache.getCount()).to.eql(4);
|
||||
expect(lruCache.getKeys()).to.eql(['d', 'c', 'b', 'a']);
|
||||
expect(lruCache.getValues()).to.eql([3, 2, 1, 0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('replacing value of a key', function () {
|
||||
it('moves the key to newest position', function () {
|
||||
fillLRUCache(lruCache);
|
||||
lruCache.replace('b', 4);
|
||||
expect(lruCache.getCount()).to.eql(4);
|
||||
expect(lruCache.getKeys()).to.eql(['b', 'd', 'c', 'a']);
|
||||
expect(lruCache.getValues()).to.eql([4, 3, 2, 0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setting a new value', function () {
|
||||
it('adds it as the newest value', function () {
|
||||
fillLRUCache(lruCache);
|
||||
lruCache.set('e', 4);
|
||||
expect(lruCache.getKeys()).to.eql(['e', 'd', 'c', 'b', 'a']);
|
||||
expect(lruCache.getValues()).to.eql([4, 3, 2, 1, 0]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setting an existing value', function () {
|
||||
it('raises an exception', function () {
|
||||
fillLRUCache(lruCache);
|
||||
expect(function () {
|
||||
lruCache.set('a', 0);
|
||||
}).to.throwException();
|
||||
});
|
||||
});
|
||||
|
||||
describe('disallowed keys', function () {
|
||||
it('setting raises an exception', function () {
|
||||
expect(function () {
|
||||
lruCache.set('constructor', 0);
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
lruCache.set('hasOwnProperty', 0);
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
lruCache.set('isPrototypeOf', 0);
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
lruCache.set('propertyIsEnumerable', 0);
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
lruCache.set('toLocaleString', 0);
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
lruCache.set('toString', 0);
|
||||
}).to.throwException();
|
||||
expect(function () {
|
||||
lruCache.set('valueOf', 0);
|
||||
}).to.throwException();
|
||||
});
|
||||
it('getting returns false', function () {
|
||||
expect(lruCache.containsKey('constructor')).to.not.be();
|
||||
expect(lruCache.containsKey('hasOwnProperty')).to.not.be();
|
||||
expect(lruCache.containsKey('isPrototypeOf')).to.not.be();
|
||||
expect(lruCache.containsKey('propertyIsEnumerable')).to.not.be();
|
||||
expect(lruCache.containsKey('toLocaleString')).to.not.be();
|
||||
expect(lruCache.containsKey('toString')).to.not.be();
|
||||
expect(lruCache.containsKey('valueOf')).to.not.be();
|
||||
});
|
||||
});
|
||||
|
||||
describe('popping a value', function () {
|
||||
it('returns the least-recent-used value', function () {
|
||||
fillLRUCache(lruCache);
|
||||
expect(lruCache.pop()).to.eql(0);
|
||||
expect(lruCache.getCount()).to.eql(3);
|
||||
expect(lruCache.containsKey('a')).to.not.be();
|
||||
expect(lruCache.pop()).to.eql(1);
|
||||
expect(lruCache.getCount()).to.eql(2);
|
||||
expect(lruCache.containsKey('b')).to.not.be();
|
||||
expect(lruCache.pop()).to.eql(2);
|
||||
expect(lruCache.getCount()).to.eql(1);
|
||||
expect(lruCache.containsKey('c')).to.not.be();
|
||||
expect(lruCache.pop()).to.eql(3);
|
||||
expect(lruCache.getCount()).to.eql(0);
|
||||
expect(lruCache.containsKey('d')).to.not.be();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#peekFirstKey()', function () {
|
||||
it('returns the newest key in the cache', function () {
|
||||
const cache = new LRUCache();
|
||||
cache.set('oldest', 'oldest');
|
||||
cache.set('oldish', 'oldish');
|
||||
cache.set('newish', 'newish');
|
||||
cache.set('newest', 'newest');
|
||||
expect(cache.peekFirstKey()).to.eql('newest');
|
||||
});
|
||||
|
||||
it('works if the cache has one item', function () {
|
||||
const cache = new LRUCache();
|
||||
cache.set('key', 'value');
|
||||
expect(cache.peekFirstKey()).to.eql('key');
|
||||
});
|
||||
|
||||
it('throws if the cache is empty', function () {
|
||||
const cache = new LRUCache();
|
||||
expect(function () {
|
||||
cache.peekFirstKey();
|
||||
}).to.throwException();
|
||||
});
|
||||
});
|
||||
|
||||
describe('peeking at the last value', function () {
|
||||
it('returns the last key', function () {
|
||||
fillLRUCache(lruCache);
|
||||
expect(lruCache.peekLast()).to.eql(0);
|
||||
});
|
||||
it('throws an exception when the cache is empty', function () {
|
||||
expect(function () {
|
||||
lruCache.peekLast();
|
||||
}).to.throwException();
|
||||
});
|
||||
});
|
||||
|
||||
describe('peeking at the last key', function () {
|
||||
it('returns the last key', function () {
|
||||
fillLRUCache(lruCache);
|
||||
expect(lruCache.peekLastKey()).to.eql('a');
|
||||
});
|
||||
it('throws an exception when the cache is empty', function () {
|
||||
expect(function () {
|
||||
lruCache.peekLastKey();
|
||||
}).to.throwException();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#remove()', function () {
|
||||
it('removes an item from the cache', function () {
|
||||
const cache = new LRUCache();
|
||||
cache.set('oldest', 'oldest');
|
||||
cache.set('oldish', 'oldish');
|
||||
cache.set('newish', 'newish');
|
||||
cache.set('newest', 'newest');
|
||||
|
||||
cache.remove('oldish');
|
||||
expect(cache.getCount()).to.eql(3);
|
||||
expect(cache.getValues()).to.eql(['newest', 'newish', 'oldest']);
|
||||
});
|
||||
|
||||
it('works when removing the oldest item', function () {
|
||||
const cache = new LRUCache();
|
||||
cache.set('oldest', 'oldest');
|
||||
cache.set('oldish', 'oldish');
|
||||
cache.set('newish', 'newish');
|
||||
cache.set('newest', 'newest');
|
||||
|
||||
cache.remove('oldest');
|
||||
expect(cache.getCount()).to.eql(3);
|
||||
expect(cache.peekLastKey()).to.eql('oldish');
|
||||
expect(cache.getValues()).to.eql(['newest', 'newish', 'oldish']);
|
||||
});
|
||||
|
||||
it('works when removing the newest item', function () {
|
||||
const cache = new LRUCache();
|
||||
cache.set('oldest', 'oldest');
|
||||
cache.set('oldish', 'oldish');
|
||||
cache.set('newish', 'newish');
|
||||
cache.set('newest', 'newest');
|
||||
|
||||
cache.remove('newest');
|
||||
expect(cache.getCount()).to.eql(3);
|
||||
expect(cache.peekFirstKey()).to.eql('newish');
|
||||
expect(cache.getValues()).to.eql(['newish', 'oldish', 'oldest']);
|
||||
});
|
||||
|
||||
it('returns the removed item', function () {
|
||||
const cache = new LRUCache();
|
||||
const item = {};
|
||||
cache.set('key', item);
|
||||
|
||||
const returned = cache.remove('key');
|
||||
expect(returned).to.be(item);
|
||||
});
|
||||
|
||||
it('throws if the key does not exist', function () {
|
||||
const cache = new LRUCache();
|
||||
cache.set('foo', 'foo');
|
||||
cache.set('bar', 'bar');
|
||||
|
||||
const call = function () {
|
||||
cache.remove('bam');
|
||||
};
|
||||
expect(call).to.throwException();
|
||||
});
|
||||
});
|
||||
|
||||
describe('clearing the cache', function () {
|
||||
it('clears the cache', function () {
|
||||
fillLRUCache(lruCache);
|
||||
lruCache.clear();
|
||||
expect(lruCache.getCount()).to.eql(0);
|
||||
expect(lruCache.getKeys()).to.eql([]);
|
||||
expect(lruCache.getValues()).to.eql([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setting the cache size', function () {
|
||||
it('sets the cache size', function () {
|
||||
lruCache.setSize(2);
|
||||
expect(lruCache.highWaterMark).to.be(2);
|
||||
fillLRUCache(lruCache);
|
||||
while (lruCache.canExpireCache()) {
|
||||
lruCache.pop();
|
||||
}
|
||||
expect(lruCache.getKeys().length).to.be(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
158
test/browser/spec/ol/structs/priorityqueue.test.js
Normal file
158
test/browser/spec/ol/structs/priorityqueue.test.js
Normal file
@@ -0,0 +1,158 @@
|
||||
import PriorityQueue, {
|
||||
DROP,
|
||||
} from '../../../../../src/ol/structs/PriorityQueue.js';
|
||||
|
||||
describe('ol.structs.PriorityQueue', function () {
|
||||
const identity = function (a) {
|
||||
return a;
|
||||
};
|
||||
|
||||
describe('when empty', function () {
|
||||
let pq;
|
||||
beforeEach(function () {
|
||||
pq = new PriorityQueue(identity, identity);
|
||||
});
|
||||
|
||||
it('is empty', function () {
|
||||
expect(pq.isEmpty()).to.be(true);
|
||||
});
|
||||
|
||||
it('enqueue adds an element', function () {
|
||||
const added = pq.enqueue(0);
|
||||
expect(added).to.be(true);
|
||||
expect(pq.elements_).to.eql([0]);
|
||||
expect(pq.priorities_).to.eql([0]);
|
||||
});
|
||||
|
||||
it('do not enqueue element with DROP priority', function () {
|
||||
const added = pq.enqueue(Infinity);
|
||||
expect(added).to.be(false);
|
||||
expect(pq.elements_).to.eql([]);
|
||||
expect(pq.priorities_).to.eql([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when populated', function () {
|
||||
let elements, pq;
|
||||
beforeEach(function () {
|
||||
elements = [];
|
||||
pq = new PriorityQueue(identity, identity);
|
||||
let element, i;
|
||||
for (i = 0; i < 32; ++i) {
|
||||
element = Math.random();
|
||||
pq.enqueue(element);
|
||||
elements.push(element);
|
||||
}
|
||||
});
|
||||
|
||||
it('dequeues elements in the correct order', function () {
|
||||
elements.sort();
|
||||
let i;
|
||||
for (i = 0; i < elements.length; ++i) {
|
||||
expect(pq.dequeue()).to.be(elements[i]);
|
||||
}
|
||||
expect(pq.isEmpty()).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with an impure priority function', function () {
|
||||
let pq, target;
|
||||
beforeEach(function () {
|
||||
target = 0.5;
|
||||
pq = new PriorityQueue(function (element) {
|
||||
return Math.abs(element - target);
|
||||
}, identity);
|
||||
let i;
|
||||
for (i = 0; i < 32; ++i) {
|
||||
pq.enqueue(Math.random());
|
||||
}
|
||||
});
|
||||
|
||||
it('dequeue elements in the correct order', function () {
|
||||
let lastDelta = 0;
|
||||
let delta;
|
||||
while (!pq.isEmpty()) {
|
||||
delta = Math.abs(pq.dequeue() - target);
|
||||
expect(lastDelta <= delta).to.be(true);
|
||||
lastDelta = delta;
|
||||
}
|
||||
});
|
||||
|
||||
it('allows reprioritization', function () {
|
||||
const target = 0.5;
|
||||
pq.reprioritize();
|
||||
let lastDelta = 0;
|
||||
let delta;
|
||||
while (!pq.isEmpty()) {
|
||||
delta = Math.abs(pq.dequeue() - target);
|
||||
expect(lastDelta <= delta).to.be(true);
|
||||
lastDelta = delta;
|
||||
}
|
||||
});
|
||||
|
||||
it('allows dropping during reprioritization', function () {
|
||||
const target = 0.5;
|
||||
let i = 0;
|
||||
pq.priorityFunction_ = function (element) {
|
||||
if (i++ % 2 === 0) {
|
||||
return Math.abs(element - target);
|
||||
} else {
|
||||
return DROP;
|
||||
}
|
||||
};
|
||||
pq.reprioritize();
|
||||
expect(pq.getCount()).to.be(16);
|
||||
let lastDelta = 0;
|
||||
let delta;
|
||||
while (!pq.isEmpty()) {
|
||||
delta = Math.abs(pq.dequeue() - target);
|
||||
expect(lastDelta <= delta).to.be(true);
|
||||
lastDelta = delta;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('tracks elements in the queue', function () {
|
||||
let pq;
|
||||
beforeEach(function () {
|
||||
pq = new PriorityQueue(identity, identity);
|
||||
pq.enqueue('a');
|
||||
pq.enqueue('b');
|
||||
pq.enqueue('c');
|
||||
});
|
||||
|
||||
it('tracks which elements have been queued', function () {
|
||||
expect(pq.isQueued('a')).to.be(true);
|
||||
expect(pq.isQueued('b')).to.be(true);
|
||||
expect(pq.isQueued('c')).to.be(true);
|
||||
});
|
||||
|
||||
it('tracks which elements have not been queued', function () {
|
||||
expect(pq.isQueued('d')).to.be(false);
|
||||
});
|
||||
|
||||
it('raises an error when an queued element is re-queued', function () {
|
||||
expect(function () {
|
||||
pq.enqueue('a');
|
||||
}).to.throwException();
|
||||
});
|
||||
|
||||
it('tracks which elements have be dequeued', function () {
|
||||
expect(pq.isQueued('a')).to.be(true);
|
||||
expect(pq.isQueued('b')).to.be(true);
|
||||
expect(pq.isQueued('c')).to.be(true);
|
||||
expect(pq.dequeue()).to.be('a');
|
||||
expect(pq.isQueued('a')).to.be(false);
|
||||
expect(pq.isQueued('b')).to.be(true);
|
||||
expect(pq.isQueued('c')).to.be(true);
|
||||
expect(pq.dequeue()).to.be('b');
|
||||
expect(pq.isQueued('a')).to.be(false);
|
||||
expect(pq.isQueued('b')).to.be(false);
|
||||
expect(pq.isQueued('c')).to.be(true);
|
||||
expect(pq.dequeue()).to.be('c');
|
||||
expect(pq.isQueued('a')).to.be(false);
|
||||
expect(pq.isQueued('b')).to.be(false);
|
||||
expect(pq.isQueued('c')).to.be(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
307
test/browser/spec/ol/structs/rbush.test.js
Normal file
307
test/browser/spec/ol/structs/rbush.test.js
Normal file
@@ -0,0 +1,307 @@
|
||||
import RBush from '../../../../../src/ol/structs/RBush.js';
|
||||
|
||||
describe('ol.structs.RBush', function () {
|
||||
let rBush;
|
||||
beforeEach(function () {
|
||||
rBush = new RBush();
|
||||
});
|
||||
|
||||
describe('when empty', function () {
|
||||
describe('#getAll', function () {
|
||||
it('returns the expected number of objects', function () {
|
||||
expect(rBush.getAll()).to.be.empty();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isEmpty', function () {
|
||||
it('returns true', function () {
|
||||
expect(rBush.isEmpty()).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a single object', function () {
|
||||
let obj;
|
||||
beforeEach(function () {
|
||||
obj = {};
|
||||
rBush.insert([0, 0, 1, 1], obj);
|
||||
});
|
||||
|
||||
it('can update the object', function () {
|
||||
expect(rBush.getInExtent([0, 0, 1, 1])).to.eql([obj]);
|
||||
rBush.update([2, 2, 3, 3], obj);
|
||||
expect(rBush.getInExtent([0, 0, 1, 1])).to.be.empty();
|
||||
expect(rBush.getAll()).to.eql([obj]);
|
||||
expect(rBush.getInExtent([2, 2, 3, 3])).to.eql([obj]);
|
||||
});
|
||||
|
||||
it("don't throws an exception if the extent is not modified", function () {
|
||||
expect(function () {
|
||||
rBush.forEach(function (value) {
|
||||
rBush.update([0, 0, 1, 1], obj);
|
||||
});
|
||||
}).not.to.throwException();
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a few objects', function () {
|
||||
let objs;
|
||||
beforeEach(function () {
|
||||
objs = [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}];
|
||||
rBush.insert([0, 0, 1, 1], objs[0]);
|
||||
rBush.insert([1, 1, 4, 4], objs[1]);
|
||||
rBush.insert([2, 2, 3, 3], objs[2]);
|
||||
rBush.insert([-5, -5, -4, -4], objs[3]);
|
||||
rBush.insert([-4, -4, -1, -1], objs[4]);
|
||||
rBush.insert([-3, -3, -2, -2], objs[5]);
|
||||
rBush.insert([-3, -3, -2, -2], objs[6]);
|
||||
rBush.insert([-3, -3, -2, -2], objs[7]);
|
||||
rBush.insert([-3, -3, -2, -2], objs[8]);
|
||||
rBush.insert([-3, -3, -2, -2], objs[9]);
|
||||
rBush.insert([-3, -3, -2, -2], objs[10]);
|
||||
});
|
||||
|
||||
describe('#forEach', function () {
|
||||
it('called for all the objects', function () {
|
||||
let i = 0;
|
||||
rBush.forEach(function () {
|
||||
++i;
|
||||
});
|
||||
expect(i).to.be(objs.length);
|
||||
});
|
||||
|
||||
it('stops when the function returns true', function () {
|
||||
let i = 0;
|
||||
const result = rBush.forEach(function () {
|
||||
return ++i >= 4;
|
||||
});
|
||||
expect(i).to.be(4);
|
||||
expect(result).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getInExtent', function () {
|
||||
it('returns the expected objects', function () {
|
||||
let result;
|
||||
result = rBush.getInExtent([2, 2, 3, 3]);
|
||||
expect(result).to.contain(objs[1]);
|
||||
expect(result).to.contain(objs[2]);
|
||||
expect(result.length).to.be(2);
|
||||
result = rBush.getInExtent([-1, -1, 2, 2]);
|
||||
expect(result).to.contain(objs[0]);
|
||||
expect(result).to.contain(objs[1]);
|
||||
expect(result).to.contain(objs[2]);
|
||||
expect(result).to.contain(objs[4]);
|
||||
expect(result.length).to.be(4);
|
||||
});
|
||||
|
||||
it('returns an empty array when given a disjoint extent', function () {
|
||||
expect(rBush.getInExtent([5, 5, 6, 6]).length).to.be(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isEmpty', function () {
|
||||
it('returns false', function () {
|
||||
expect(rBush.isEmpty()).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#remove', function () {
|
||||
it('can remove each object', function () {
|
||||
let i, ii;
|
||||
for (i = 0, ii = objs.length; i < ii; ++i) {
|
||||
expect(rBush.getAll()).to.contain(objs[i]);
|
||||
rBush.remove(objs[i]);
|
||||
expect(rBush.getAll()).not.to.contain(objs[i]);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with 100 objects', function () {
|
||||
let extents, objs;
|
||||
beforeEach(function () {
|
||||
extents = [];
|
||||
objs = [];
|
||||
let i;
|
||||
for (i = 0; i < 100; ++i) {
|
||||
extents[i] = [i - 0.1, i - 0.1, i + 0.1, i + 0.1];
|
||||
objs[i] = {id: i};
|
||||
rBush.insert(extents[i], objs[i]);
|
||||
}
|
||||
});
|
||||
|
||||
describe('#getInExtent', function () {
|
||||
it('returns the expected objects', function () {
|
||||
let i, ii;
|
||||
for (i = 0, ii = objs.length; i < ii; ++i) {
|
||||
expect(rBush.getInExtent(extents[i])).to.eql([objs[i]]);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isEmpty', function () {
|
||||
it('returns false', function () {
|
||||
expect(rBush.isEmpty()).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#remove', function () {
|
||||
it('can remove each object in turn', function () {
|
||||
let i, ii;
|
||||
for (i = 0, ii = objs.length; i < ii; ++i) {
|
||||
expect(rBush.getInExtent(extents[i])).to.eql([objs[i]]);
|
||||
rBush.remove(objs[i]);
|
||||
expect(rBush.getInExtent(extents[i])).to.be.empty();
|
||||
}
|
||||
expect(rBush.getAll()).to.be.empty();
|
||||
expect(rBush.isEmpty()).to.be(true);
|
||||
});
|
||||
|
||||
it('can remove objects in random order', function () {
|
||||
let i, ii, j;
|
||||
// https://en.wikipedia.org/wiki/Random_permutation
|
||||
const indexes = [];
|
||||
for (i = 0, ii = objs.length; i < ii; ++i) {
|
||||
j = Math.floor(Math.random() * (i + 1));
|
||||
indexes[i] = indexes[j];
|
||||
indexes[j] = i;
|
||||
}
|
||||
for (i = 0, ii = objs.length; i < ii; ++i) {
|
||||
const index = indexes[i];
|
||||
expect(rBush.getInExtent(extents[index])).to.eql([objs[index]]);
|
||||
rBush.remove(objs[index]);
|
||||
expect(rBush.getInExtent(extents[index])).to.be.empty();
|
||||
}
|
||||
expect(rBush.getAll()).to.be.empty();
|
||||
expect(rBush.isEmpty()).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with 1000 objects', function () {
|
||||
beforeEach(function () {
|
||||
let i;
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
const min = [Math.random() * 10000, Math.random() * 10000];
|
||||
const max = [
|
||||
min[0] + Math.random() * 500,
|
||||
min[1] + Math.random() * 500,
|
||||
];
|
||||
const extent = [min[0], min[1], max[0], max[1]];
|
||||
rBush.insert(extent, {id: i});
|
||||
}
|
||||
});
|
||||
|
||||
describe('#getAll', function () {
|
||||
it('returns the expected number of objects', function () {
|
||||
expect(rBush.getAll().length).to.be(1000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getInExtent', function () {
|
||||
it('returns the expected number of objects', function () {
|
||||
expect(rBush.getInExtent([0, 0, 10600, 10600]).length).to.be(1000);
|
||||
});
|
||||
|
||||
it('can perform 1000 in-extent searches', function () {
|
||||
let n = 0;
|
||||
let i;
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
const min = [Math.random() * 10000, Math.random() * 10000];
|
||||
const max = [
|
||||
min[0] + Math.random() * 500,
|
||||
min[1] + Math.random() * 500,
|
||||
];
|
||||
const extent = [min[0], min[1], max[0], max[1]];
|
||||
n += rBush.getInExtent(extent).length;
|
||||
}
|
||||
expect(n).not.to.be(0);
|
||||
});
|
||||
|
||||
it('can perform 1000 out-of-extent searches', function () {
|
||||
let n = 0;
|
||||
let i;
|
||||
for (i = 0; i < 1000; ++i) {
|
||||
const min = [
|
||||
-(Math.random() * 10000 + 501),
|
||||
-(Math.random() * 10000 + 501),
|
||||
];
|
||||
const max = [
|
||||
min[0] + Math.random() * 500,
|
||||
min[1] + Math.random() * 500,
|
||||
];
|
||||
const extent = [min[0], min[1], max[0], max[1]];
|
||||
n += rBush.getInExtent(extent).length;
|
||||
}
|
||||
expect(n).to.be(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#insert', function () {
|
||||
it('can insert another 1000 objects', function () {
|
||||
let i;
|
||||
for (i = 1000; i < 2000; ++i) {
|
||||
const min = [Math.random() * 10000, Math.random() * 10000];
|
||||
const max = [
|
||||
min[0] + Math.random() * 500,
|
||||
min[1] + Math.random() * 500,
|
||||
];
|
||||
const extent = [min[0], min[1], max[0], max[1]];
|
||||
rBush.insert(extent, {id: i});
|
||||
}
|
||||
expect(rBush.getInExtent([0, 0, 10600, 10600]).length).to.be(2000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#isEmpty', function () {
|
||||
it('returns false', function () {
|
||||
expect(rBush.isEmpty()).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#remove', function () {
|
||||
it('can remove all 1000 objects', function () {
|
||||
const objs = rBush.getAll();
|
||||
let i, value;
|
||||
for (i = objs.length - 1; i >= 0; --i) {
|
||||
value = objs[i];
|
||||
rBush.remove(value);
|
||||
}
|
||||
expect(rBush.isEmpty()).to.be(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getExtent', function () {
|
||||
it('gets the extent', function () {
|
||||
const obj = {};
|
||||
rBush.insert([0, 0, 1, 1], obj);
|
||||
expect(rBush.getExtent()).to.eql([0, 0, 1, 1]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#concat', function () {
|
||||
it('concatenates two RBush objects', function () {
|
||||
const obj1 = {};
|
||||
const obj2 = {};
|
||||
const rBush2 = new RBush();
|
||||
rBush.insert([0, 0, 1, 1], obj1);
|
||||
rBush2.insert([0, 0, 2, 2], obj2);
|
||||
rBush.concat(rBush2);
|
||||
expect(rBush.getExtent()).to.eql([0, 0, 2, 2]);
|
||||
expect(rBush.getAll().length).to.be(2);
|
||||
});
|
||||
|
||||
it("preserves the concatenated object's references", function () {
|
||||
const obj1 = {};
|
||||
const obj2 = {};
|
||||
const rBush2 = new RBush();
|
||||
rBush.insert([0, 0, 1, 1], obj1);
|
||||
rBush2.insert([0, 0, 2, 2], obj2);
|
||||
rBush.concat(rBush2);
|
||||
rBush.update([0, 0, 3, 3], obj2);
|
||||
expect(rBush.getExtent()).to.eql([0, 0, 3, 3]);
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user