| var chai = require('chai') |
| var sinon = require('sinon') |
| var expect = chai.expect |
| chai.use(require('sinon-chai')) |
| |
| var TtlSet = require('../../lib/util/ttlset') |
| |
| describe('TtlSet', function() { |
| it('should emit "drop" for entries with expired TTL', function(done) { |
| var ttlset = new TtlSet(50) |
| |
| var spy = sinon.spy() |
| ttlset.on('drop', spy) |
| |
| ttlset.bump(1, Date.now()) |
| ttlset.bump(2, Date.now() + 100) |
| ttlset.bump(3, Date.now() + 200) |
| ttlset.bump(4, Date.now() + 1000) |
| |
| setTimeout(function() { |
| expect(spy).to.have.been.calledThrice |
| expect(spy).to.have.been.calledWith(1) |
| expect(spy).to.have.been.calledWith(2) |
| expect(spy).to.have.been.calledWith(3) |
| expect(ttlset.head).to.equal(ttlset.tail) |
| ttlset.stop() |
| done() |
| }, 300) |
| }) |
| |
| describe('bump', function() { |
| it('should emit "insert" for new entries', function(done) { |
| var ttlset = new TtlSet(50) |
| |
| var spy = sinon.spy() |
| ttlset.on('insert', spy) |
| |
| ttlset.bump(1) |
| ttlset.bump(2) |
| ttlset.bump(3) |
| |
| expect(spy).to.have.been.calledThrice |
| expect(spy).to.have.been.calledWith(1) |
| expect(spy).to.have.been.calledWith(2) |
| expect(spy).to.have.been.calledWith(3) |
| |
| ttlset.stop() |
| done() |
| }) |
| |
| it('should not emit "insert" for new entries if SILENT', function(done) { |
| var ttlset = new TtlSet(50) |
| |
| var spy = sinon.spy() |
| ttlset.on('insert', spy) |
| |
| ttlset.bump(1, Date.now(), TtlSet.SILENT) |
| ttlset.bump(2, Date.now()) |
| ttlset.bump(3, Date.now(), TtlSet.SILENT) |
| |
| expect(spy).to.have.been.calledOnce |
| expect(spy).to.have.been.calledWith(2) |
| |
| ttlset.stop() |
| done() |
| }) |
| |
| it('should create an item for the value if none exists', function(done) { |
| var ttlset = new TtlSet(5000) |
| ttlset.bump(5) |
| expect(ttlset.head).to.equal(ttlset.tail) |
| expect(ttlset.head.value).to.equal(5) |
| done() |
| }) |
| |
| it('should make the item the new tail', function(done) { |
| var ttlset = new TtlSet(5000) |
| ttlset.bump(5) |
| expect(ttlset.tail.value).to.equal(5) |
| ttlset.bump(6) |
| expect(ttlset.tail.value).to.equal(6) |
| done() |
| }) |
| |
| it('should set head if none exists', function(done) { |
| var ttlset = new TtlSet(5000) |
| expect(ttlset.head).to.be.null |
| ttlset.bump(5) |
| expect(ttlset.head.value).to.equal(5) |
| ttlset.bump(6) |
| expect(ttlset.head.value).to.equal(5) |
| done() |
| }) |
| |
| it('should take old item out and make it the tail', function(done) { |
| var ttlset = new TtlSet(5000) |
| ttlset.bump(1) |
| expect(ttlset.head.value).to.equal(1) |
| expect(ttlset.tail.value).to.equal(1) |
| expect(ttlset.head.next).to.be.null |
| expect(ttlset.head.prev).to.be.null |
| expect(ttlset.tail.next).to.be.null |
| expect(ttlset.tail.prev).to.be.null |
| ttlset.bump(2) |
| expect(ttlset.head.value).to.equal(1) |
| expect(ttlset.tail.value).to.equal(2) |
| expect(ttlset.head.next).to.equal(ttlset.tail) |
| expect(ttlset.head.prev).to.be.null |
| expect(ttlset.tail.next).to.be.null |
| expect(ttlset.tail.prev).to.equal(ttlset.head) |
| ttlset.bump(1) |
| expect(ttlset.head.value).to.equal(2) |
| expect(ttlset.tail.value).to.equal(1) |
| expect(ttlset.head.next).to.equal(ttlset.tail) |
| expect(ttlset.head.prev).to.be.null |
| expect(ttlset.tail.next).to.be.null |
| expect(ttlset.tail.prev).to.equal(ttlset.head) |
| ttlset.bump(1) |
| expect(ttlset.head.value).to.equal(2) |
| expect(ttlset.tail.value).to.equal(1) |
| expect(ttlset.head.next).to.equal(ttlset.tail) |
| expect(ttlset.head.prev).to.be.null |
| expect(ttlset.tail.next).to.be.null |
| expect(ttlset.tail.prev).to.equal(ttlset.head) |
| done() |
| }) |
| }) |
| |
| describe('drop', function() { |
| it('should emit "drop" for the dropped entry', function(done) { |
| var ttlset = new TtlSet(50) |
| |
| var spy = sinon.spy() |
| ttlset.on('drop', spy) |
| |
| ttlset.bump(1) |
| ttlset.bump(2) |
| ttlset.bump(3) |
| ttlset.drop(1) |
| ttlset.drop(3) |
| |
| expect(spy).to.have.been.calledTwice |
| expect(spy).to.have.been.calledWith(1) |
| expect(spy).to.have.been.calledWith(3) |
| |
| ttlset.stop() |
| done() |
| }) |
| |
| it('should not emit "drop" for the dropped entry if SILENT', function(done) { |
| var ttlset = new TtlSet(50) |
| |
| var spy = sinon.spy() |
| ttlset.on('drop', spy) |
| |
| ttlset.bump(1) |
| ttlset.bump(2) |
| ttlset.bump(3) |
| ttlset.drop(1, TtlSet.SILENT) |
| ttlset.drop(3) |
| |
| expect(spy).to.have.been.calledOnce |
| expect(spy).to.have.been.calledWith(3) |
| |
| ttlset.stop() |
| done() |
| }) |
| |
| it('should silently ignore unknown values', function(done) { |
| var ttlset = new TtlSet(5000) |
| ttlset.drop(5) |
| done() |
| }) |
| |
| it('should remove the value from the set', function(done) { |
| var ttlset = new TtlSet(5000) |
| ttlset.bump(5) |
| ttlset.drop(5) |
| expect(ttlset.tail).to.be.null |
| expect(ttlset.head).to.be.null |
| ttlset.bump(1) |
| ttlset.bump(2) |
| ttlset.drop(1) |
| expect(ttlset.tail).to.equal(ttlset.head) |
| expect(ttlset.tail.value).to.equal(2) |
| ttlset.bump(3) |
| ttlset.drop(3) |
| expect(ttlset.tail).to.equal(ttlset.head) |
| expect(ttlset.tail.value).to.equal(2) |
| done() |
| }) |
| }) |
| }) |