import LRUCache from '../../../../src/ol/structs/LRUCache.js'; import expect from '../../expect.js'; describe('ol/structs/LRUCache.js', 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); }); }); });