| <!DOCTYPE html> |
| <!-- |
| Copyright 2021 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> |
| <title>lru-cache tests</title> |
| |
| <script src="../node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js"></script> |
| <script src="../node_modules/web-component-tester/browser.js"></script> |
| |
| <script type="module"> |
| import { |
| CacheObject, |
| } from '../src/main/resources/static/cache-object.js'; |
| import { |
| LRUMemoryCacheObject, |
| } from '../src/main/resources/static/lru-memory-cache-object.js'; |
| import { |
| LRUStorageCacheObject, |
| } from '../src/main/resources/static/lru-storage-cache-object.js'; |
| |
| suite('LRUMemoryCacheObject', () => { |
| let cache; |
| |
| setup(() => { |
| cache = new LRUMemoryCacheObject(2); |
| }); |
| |
| teardown(() => { |
| cache.clear(); |
| }); |
| |
| test('read with no entry for key returns undefined', () => { |
| assert.strictEqual(cache.read('a'), undefined); |
| }); |
| |
| test('write followed by read succeeds', () => { |
| cache.write('a', 1); |
| assert.strictEqual(cache.read('a'), 1); |
| }); |
| |
| test('write then clear then read yields empty cache', () => { |
| cache.write('a', 1); |
| cache.clear(); |
| assert.strictEqual(cache.read('a'), undefined); |
| }); |
| |
| test('delete deletes keys', () => { |
| cache.write('a', 'c'); |
| cache.write('b', 'd'); |
| cache.delete('a'); |
| assert.strictEqual(cache.read('a'), undefined); |
| assert.strictEqual(cache.read('b'), 'd'); |
| }); |
| |
| test('cache evicts LRU element', () => { |
| cache.write('a', 1); |
| cache.write('b', 2); |
| cache.write('c', 3); |
| assert.strictEqual(cache.read('a'), undefined); |
| cache.clear(); |
| |
| cache.write('a', 1); |
| cache.write('b', 2); |
| assert.strictEqual(cache.read('a'), 1); |
| cache.write('c', 3); |
| assert.strictEqual(cache.read('b'), undefined); |
| cache.clear(); |
| |
| cache.write('a', 1); |
| cache.write('b', 2); |
| cache.write('a', 3); |
| cache.write('c', 3); |
| assert.strictEqual(cache.read('b'), undefined); |
| }); |
| }); |
| |
| suite('LRUStorageCacheObject', () => { |
| let sandbox; |
| let cache; |
| const cacheKey = 'key'; |
| |
| setup(() => { |
| sandbox = sinon.sandbox.create(); |
| cache = new LRUStorageCacheObject(2, cacheKey); |
| }); |
| |
| teardown(() => { |
| cache.clear(); |
| }); |
| |
| test('read with no entry for key returns undefined', () => { |
| assert.strictEqual(cache.read('a'), undefined); |
| }); |
| |
| test('write followed by read succeeds', () => { |
| cache.write('a', 1); |
| assert.strictEqual(cache.read('a'), 1); |
| }); |
| |
| test('write then clear then read yields empty cache', () => { |
| cache.write('a', 1); |
| const key = cache.formatKey('a'); |
| assert.deepEqual(JSON.parse(localStorage.getItem(key)), {value: 1}); |
| cache.clear(); |
| assert.strictEqual(cache.read('a'), undefined); |
| assert.deepEqual(cache.accessKeys, []); |
| assert.strictEqual(JSON.parse(localStorage.getItem(key)), null); |
| }); |
| |
| test('delete deletes keys', () => { |
| cache.write('a', 'c'); |
| cache.write('b', 'd'); |
| cache.delete('a'); |
| assert.strictEqual(cache.read('a'), undefined); |
| assert.strictEqual(cache.read('b'), 'd'); |
| }); |
| |
| test('cache evicts LRU element', () => { |
| cache.write('a', 1); |
| cache.write('b', 2); |
| cache.write('c', 3); |
| assert.strictEqual(cache.read('a'), undefined); |
| cache.clear(); |
| |
| cache.write('a', 1); |
| cache.write('b', 2); |
| assert.strictEqual(cache.read('a'), 1); |
| cache.write('c', 3); |
| assert.strictEqual(cache.read('b'), undefined); |
| cache.clear(); |
| |
| cache.write('a', 1); |
| cache.write('b', 2); |
| cache.write('a', 3); |
| cache.write('c', 3); |
| assert.strictEqual(cache.read('b'), undefined); |
| }); |
| |
| test('cache persists', () => { |
| cache.write('a', 1); |
| cache.write('b', 2); |
| |
| const otherCache = new LRUStorageCacheObject(2, cacheKey); |
| assert.strictEqual(otherCache.read('a'), 1); |
| assert.strictEqual(otherCache.read('b'), 2); |
| }); |
| |
| test('cache resizes', () => { |
| cache.write('a', 1); |
| cache.write('b', 2); |
| const smallerCache = new LRUStorageCacheObject(1, cacheKey); |
| assert.strictEqual(smallerCache.read('a'), undefined); |
| assert.strictEqual(JSON.parse(localStorage.getItem('a')), null); |
| assert.strictEqual(smallerCache.read('b'), 2); |
| smallerCache.clear(); |
| |
| cache = new LRUStorageCacheObject(2, cacheKey); |
| cache.write('a', 1); |
| cache.write('b', 2); |
| const biggerCache = new LRUStorageCacheObject(3, cacheKey); |
| biggerCache.write('c', 3); |
| assert.strictEqual(biggerCache.read('a'), 1); |
| assert.strictEqual(biggerCache.read('b'), 2); |
| assert.strictEqual(biggerCache.read('c'), 3); |
| }); |
| |
| test('cache halves when storage capacity is reached', () => { |
| const cache = new LRUStorageCacheObject(4, 'foo'); |
| cache.write('a', 1); |
| cache.write('b', 2); |
| cache.write('c', 3); |
| cache.write('d', 4); |
| |
| const stub = sandbox.stub(CacheObject.prototype, 'write'); |
| stub.onCall(0).throws('QuotaExceededError'); |
| stub.onCall(1).returns(( |
| () => localStorage.setItem( |
| cache.formatKey('e'), JSON.stringify({value: 5})) |
| )()); |
| cache.write('e', 5); |
| |
| assert.strictEqual(cache.read('a'), undefined); |
| assert.strictEqual(cache.read('b'), undefined); |
| assert.strictEqual(cache.read('c'), 3); |
| assert.strictEqual(cache.read('d'), 4); |
| assert.strictEqual(cache.read('e'), 5); |
| }); |
| }); |
| </script> |