lru.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * This file is part of the storage node for the Joystream project.
  3. * Copyright (C) 2019 Joystream Contributors
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. 'use strict';
  19. const mocha = require('mocha');
  20. const expect = require('chai').expect;
  21. const lru = require('@joystream/storage-utils/lru');
  22. const DEFAULT_SLEEP = 1;
  23. function sleep(ms = DEFAULT_SLEEP)
  24. {
  25. return new Promise(resolve => {
  26. setTimeout(resolve, ms)
  27. })
  28. }
  29. describe('util/lru', function()
  30. {
  31. describe('simple usage', function()
  32. {
  33. it('does not contain keys that were not added', function()
  34. {
  35. var cache = new lru.LRUCache();
  36. expect(cache.size()).to.equal(0);
  37. var val = cache.get('something');
  38. expect(val).to.be.undefined;
  39. expect(cache.has('something')).to.be.false;
  40. });
  41. it('contains keys that were added', function()
  42. {
  43. var cache = new lru.LRUCache();
  44. cache.put('something', 'yay!');
  45. expect(cache.size()).to.equal(1);
  46. var val = cache.get('something');
  47. expect(val).to.be.equal('yay!');
  48. expect(cache.has('something')).to.be.true;
  49. });
  50. it('does not contain keys that were deleted', function()
  51. {
  52. var cache = new lru.LRUCache();
  53. cache.put('something', 'yay!');
  54. expect(cache.size()).to.equal(1);
  55. var val = cache.get('something');
  56. expect(val).to.be.equal('yay!');
  57. expect(cache.has('something')).to.be.true;
  58. cache.del('something');
  59. expect(cache.size()).to.equal(0);
  60. val = cache.get('something');
  61. expect(val).to.be.undefined;
  62. expect(cache.has('something')).to.be.false;
  63. });
  64. it('can be cleared', function()
  65. {
  66. var cache = new lru.LRUCache();
  67. cache.put('something', 'yay!');
  68. expect(cache.size()).to.equal(1);
  69. cache.clear();
  70. expect(cache.size()).to.equal(0);
  71. });
  72. });
  73. describe('capacity management', function()
  74. {
  75. it('does not grow beyond capacity', async function()
  76. {
  77. var cache = new lru.LRUCache(2); // Small capacity
  78. expect(cache.size()).to.equal(0);
  79. cache.put('foo', '42');
  80. expect(cache.size()).to.equal(1);
  81. await sleep();
  82. cache.put('bar', '42');
  83. expect(cache.size()).to.equal(2);
  84. await sleep();
  85. cache.put('baz', '42');
  86. expect(cache.size()).to.equal(2); // Capacity exceeded
  87. });
  88. it('removes the oldest key when pruning', async function()
  89. {
  90. var cache = new lru.LRUCache(2); // Small capacity
  91. expect(cache.size()).to.equal(0);
  92. cache.put('foo', '42');
  93. expect(cache.size()).to.equal(1);
  94. expect(cache.has('foo')).to.be.true;
  95. await sleep();
  96. cache.put('bar', '42');
  97. expect(cache.size()).to.equal(2);
  98. expect(cache.has('foo')).to.be.true;
  99. expect(cache.has('bar')).to.be.true;
  100. await sleep();
  101. cache.put('baz', '42');
  102. expect(cache.size()).to.equal(2); // Capacity exceeded
  103. expect(cache.has('bar')).to.be.true;
  104. expect(cache.has('baz')).to.be.true;
  105. });
  106. it('updates LRU timestamp when reading', async function()
  107. {
  108. var cache = new lru.LRUCache(2); // Small capacity
  109. expect(cache.size()).to.equal(0);
  110. cache.put('foo', '42');
  111. expect(cache.size()).to.equal(1);
  112. expect(cache.has('foo')).to.be.true;
  113. await sleep();
  114. cache.put('bar', '42');
  115. expect(cache.size()).to.equal(2);
  116. expect(cache.has('foo')).to.be.true;
  117. expect(cache.has('bar')).to.be.true;
  118. await sleep();
  119. // 'foo' is older than 'bar' right now, so should be pruned first. But
  120. // if we get 'foo', it would be 'bar' that has to go.
  121. var _ = cache.get('foo');
  122. // Makes debugging a bit more obvious
  123. await sleep();
  124. cache.put('baz', '42');
  125. expect(cache.size()).to.equal(2); // Capacity exceeded
  126. expect(cache.has('foo')).to.be.true;
  127. expect(cache.has('baz')).to.be.true;
  128. });
  129. });
  130. });