Skip to content

Commit

Permalink
Refactor LRU cache test asserts (#1418)
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmelnikow authored Jan 15, 2018
1 parent b422e88 commit e358ebe
Showing 1 changed file with 84 additions and 103 deletions.
187 changes: 84 additions & 103 deletions lib/lru-cache.spec.js
Original file line number Diff line number Diff line change
@@ -1,140 +1,121 @@
'use strict';

const assert = require('assert');
const { expect } = require('chai');
const LRU = require('./lru-cache');

function expectCacheSlots(cache, keys) {
expect(cache.cache.size).to.equal(keys.length);

const slots = keys.map(k => cache.cache.get(k));

const first = slots[0];
const last = slots.slice(-1)[0];

expect(cache.oldest).to.equal(first);
expect(cache.newest).to.equal(last);

expect(first.older).to.be.null;
expect(last.newer).to.be.null;

for (let i = 0; i + 1 < slots.length; ++i) {
const current = slots[i];
const next = slots[i+1];
expect(current.newer).to.equal(next);
expect(next.older).to.equal(current);
}
}

describe('The LRU cache', function () {
it('should support being called without new', function () {
const cache = LRU(1);
assert(cache instanceof LRU);
expect(cache).to.be.an.instanceof(LRU);
});

it('should support a zero capacity', function () {
const cache = new LRU(0);
cache.set('key', 'value');
assert.equal(cache.cache.size, 0);
expect(cache.cache.size).to.equal(0);
});

it('should support a one capacity', function () {
const cache = new LRU(1);
cache.set('key1', 'value1');
assert.equal(cache.cache.size, 1);
assert.equal(cache.newest, cache.cache.get('key1'));
assert.equal(cache.oldest, cache.cache.get('key1'));
expectCacheSlots(cache, ['key1']);
cache.set('key2', 'value2');
assert.equal(cache.cache.size, 1);
assert.equal(cache.newest, cache.cache.get('key2'));
assert.equal(cache.oldest, cache.cache.get('key2'));
assert.equal(cache.get('key1'), undefined);
assert.equal(cache.get('key2'), 'value2');
expectCacheSlots(cache, ['key2']);
expect(cache.get('key1')).to.be.undefined;
expect(cache.get('key2')).to.equal('value2');
});

it('should remove the oldest element when reaching capacity', function () {
const cache = new LRU(2);

cache.set('key1', 'value1');
cache.set('key2', 'value2');
cache.set('key3', 'value3');
cache.cache.get('key1');
const slot2 = cache.cache.get('key2');
const slot3 = cache.cache.get('key3');
assert.equal(cache.cache.size, 2);
assert.equal(cache.oldest, slot2);
assert.equal(cache.newest, slot3);
assert.equal(slot2.older, null);
assert.equal(slot2.newer, slot3);
assert.equal(slot3.older, slot2);
assert.equal(slot3.newer, null);
assert.equal(cache.cache.get('key1'), undefined);
assert.equal(cache.get('key1'), undefined);
assert.equal(cache.get('key2'), 'value2');
assert.equal(cache.get('key3'), 'value3');

expectCacheSlots(cache, ['key2', 'key3']);
expect(cache.cache.get('key1')).to.be.undefined;
expect(cache.get('key1')).to.be.undefined;
expect(cache.get('key2')).to.equal('value2');
expect(cache.get('key3')).to.equal('value3');
});

it('should make sure that resetting a key in cache makes it newest', function () {
const cache = new LRU(2);

cache.set('key', 'value');
cache.set('key2', 'value2');
assert.equal(cache.oldest, cache.cache.get('key'));
assert.equal(cache.newest, cache.cache.get('key2'));

expectCacheSlots(cache, ['key', 'key2']);

cache.set('key', 'value');
assert.equal(cache.oldest, cache.cache.get('key2'));
assert.equal(cache.newest, cache.cache.get('key'));

expectCacheSlots(cache, ['key2', 'key']);
});

it('should make sure that getting a key in cache makes it newest', function () {
let slot1, slot2, slot3, cache;
describe('getting a key in the cache', function () {
context('when the requested key is oldest', function () {
it('should leave the keys in the expected order', function () {
const cache = new LRU(2);
cache.set('key1', 'value1');
cache.set('key2', 'value2');

// When the key is oldest.
cache = new LRU(2);
cache.set('key1', 'value1');
cache.set('key2', 'value2');
slot1 = cache.cache.get('key1');
slot2 = cache.cache.get('key2');
assert.equal(cache.oldest, slot1);
assert.equal(cache.newest, slot2);
assert.equal(slot1.older, null);
assert.equal(slot1.newer, slot2);
assert.equal(slot2.older, slot1);
assert.equal(slot2.newer, null);

assert.equal(cache.get('key1'), 'value1');

slot1 = cache.cache.get('key1');
slot2 = cache.cache.get('key2');
assert.equal(cache.oldest, slot2);
assert.equal(cache.newest, slot1);
assert.equal(slot2.older, null);
assert.equal(slot2.newer, slot1);
assert.equal(slot1.older, slot2);
assert.equal(slot1.newer, null);


// When the key is newest.
cache = new LRU(2);
cache.set('key1', 'value1');
cache.set('key2', 'value2');
expectCacheSlots(cache, ['key1', 'key2']);

assert.equal(cache.get('key2'), 'value2');
expect(cache.get('key1')).to.equal('value1');

slot1 = cache.cache.get('key1');
slot2 = cache.cache.get('key2');
assert.equal(cache.oldest, slot1);
assert.equal(cache.newest, slot2);
assert.equal(slot1.older, null);
assert.equal(slot1.newer, slot2);
assert.equal(slot2.older, slot1);
assert.equal(slot2.newer, null);
expectCacheSlots(cache, ['key2', 'key1']);
});
});

// When the key is in the middle.
cache = new LRU(3);
cache.set('key1', 'value1');
cache.set('key2', 'value2');
cache.set('key3', 'value3');
slot1 = cache.cache.get('key1');
slot2 = cache.cache.get('key2');
slot3 = cache.cache.get('key3');
assert.equal(cache.oldest, slot1);
assert.equal(cache.newest, slot3);
assert.equal(slot1.older, null);
assert.equal(slot1.newer, slot2);
assert.equal(slot2.older, slot1);
assert.equal(slot2.newer, slot3);
assert.equal(slot3.older, slot2);
assert.equal(slot3.newer, null);

assert.equal(cache.get('key2'), 'value2');

slot1 = cache.cache.get('key1');
slot2 = cache.cache.get('key2');
slot3 = cache.cache.get('key3');
assert.equal(cache.oldest, slot1);
assert.equal(cache.newest, slot2);
assert.equal(slot1.older, null);
assert.equal(slot1.newer, slot3);
assert.equal(slot3.older, slot1);
assert.equal(slot3.newer, slot2);
assert.equal(slot2.older, slot3);
assert.equal(slot2.newer, null);
context('when the requested key is newest', function () {
it('should leave the keys in the expected order', function () {
const cache = new LRU(2);
cache.set('key1', 'value1');
cache.set('key2', 'value2');

expect(cache.get('key2')).to.equal('value2');

expectCacheSlots(cache, ['key1', 'key2']);
});
});

context('when the requested key is in the middle', function () {
it('should leave the keys in the expected order', function () {
const cache = new LRU(3);
cache.set('key1', 'value1');
cache.set('key2', 'value2');
cache.set('key3', 'value3');

expectCacheSlots(cache, ['key1', 'key2', 'key3']);

expect(cache.get('key2')).to.equal('value2');

expectCacheSlots(cache, ['key1', 'key3', 'key2']);
});
});
});

it('should clear', function () {
Expand All @@ -144,15 +125,15 @@ describe('The LRU cache', function () {
cache.set('key2', 'value2');

// Confidence check.
assert.equal(cache.get('key1'), 'value1');
assert.equal(cache.get('key2'), 'value2');
expect(cache.get('key1')).to.equal('value1');
expect(cache.get('key2')).to.equal('value2');

// Run.
cache.clear();

// Test.
assert.equal(cache.get('key1'), null);
assert.equal(cache.get('key2'), null);
assert.equal(cache.cache.size, 0);
expect(cache.get('key1')).to.be.undefined;
expect(cache.get('key2')).to.be.undefined;
expect(cache.cache.size).to.equal(0);
});
});

0 comments on commit e358ebe

Please sign in to comment.