/script-kiddie/002_script_kiddie/script-kiddie/node_modules/lru-cache/README.md |
@@ -0,0 +1,132 @@ |
# lru cache |
|
A cache object that deletes the least-recently-used items. |
|
## Usage: |
|
```javascript |
var LRU = require("lru-cache") |
, options = { max: 500 |
, length: function (n, key) { return n * 2 + key.length } |
, dispose: function (key, n) { n.close() } |
, maxAge: 1000 * 60 * 60 } |
, cache = LRU(options) |
, otherCache = LRU(50) // sets just the max size |
|
cache.set("key", "value") |
cache.get("key") // "value" |
|
// non-string keys ARE fully supported |
var someObject = {} |
cache.set(someObject, 'a value') |
cache.set('[object Object]', 'a different value') |
assert.equal(cache.get(someObject), 'a value') |
|
cache.reset() // empty the cache |
``` |
|
If you put more stuff in it, then items will fall out. |
|
If you try to put an oversized thing in it, then it'll fall out right |
away. |
|
## Options |
|
* `max` The maximum size of the cache, checked by applying the length |
function to all values in the cache. Not setting this is kind of |
silly, since that's the whole purpose of this lib, but it defaults |
to `Infinity`. |
* `maxAge` Maximum age in ms. Items are not pro-actively pruned out |
as they age, but if you try to get an item that is too old, it'll |
drop it and return undefined instead of giving it to you. |
* `length` Function that is used to calculate the length of stored |
items. If you're storing strings or buffers, then you probably want |
to do something like `function(n, key){return n.length}`. The default is |
`function(){return 1}`, which is fine if you want to store `max` |
like-sized things. They item is passed as the first argument, and |
the key is passed as the second argumnet. |
* `dispose` Function that is called on items when they are dropped |
from the cache. This can be handy if you want to close file |
descriptors or do other cleanup tasks when items are no longer |
accessible. Called with `key, value`. It's called *before* |
actually removing the item from the internal cache, so if you want |
to immediately put it back in, you'll have to do that in a |
`nextTick` or `setTimeout` callback or it won't do anything. |
* `stale` By default, if you set a `maxAge`, it'll only actually pull |
stale items out of the cache when you `get(key)`. (That is, it's |
not pre-emptively doing a `setTimeout` or anything.) If you set |
`stale:true`, it'll return the stale value before deleting it. If |
you don't set this, then it'll return `undefined` when you try to |
get a stale entry, as if it had already been deleted. |
|
## API |
|
* `set(key, value, maxAge)` |
* `get(key) => value` |
|
Both of these will update the "recently used"-ness of the key. |
They do what you think. `max` is optional and overrides the |
cache `max` option if provided. |
|
* `peek(key)` |
|
Returns the key value (or `undefined` if not found) without |
updating the "recently used"-ness of the key. |
|
(If you find yourself using this a lot, you *might* be using the |
wrong sort of data structure, but there are some use cases where |
it's handy.) |
|
* `del(key)` |
|
Deletes a key out of the cache. |
|
* `reset()` |
|
Clear the cache entirely, throwing away all values. |
|
* `has(key)` |
|
Check if a key is in the cache, without updating the recent-ness |
or deleting it for being stale. |
|
* `forEach(function(value,key,cache), [thisp])` |
|
Just like `Array.prototype.forEach`. Iterates over all the keys |
in the cache, in order of recent-ness. (Ie, more recently used |
items are iterated over first.) |
|
* `rforEach(function(value,key,cache), [thisp])` |
|
The same as `cache.forEach(...)` but items are iterated over in |
reverse order. (ie, less recently used items are iterated over |
first.) |
|
* `keys()` |
|
Return an array of the keys in the cache. |
|
* `values()` |
|
Return an array of the values in the cache. |
|
* `length()` |
|
Return total length of objects in cache taking into account |
`length` options function. |
|
* `itemCount` |
|
Return total quantity of objects currently in cache. Note, that |
`stale` (see options) items are returned as part of this item |
count. |
|
* `dump()` |
|
Return an array of the cache entries ready for serialization and usage |
with 'destinationCache.load(arr)`. |
|
* `load(cacheEntriesArray)` |
|
Loads another cache entries array, obtained with `sourceCache.dump()`, |
into the cache. The destination cache is reset before loading new entries |
/script-kiddie/002_script_kiddie/script-kiddie/node_modules/lru-cache/lib/lru-cache.js |
@@ -0,0 +1,356 @@ |
module.exports = LRUCache |
|
// This will be a proper iterable 'Map' in engines that support it, |
// or a fakey-fake PseudoMap in older versions. |
var Map = require('pseudomap') |
|
function naiveLength () { return 1 } |
|
function LRUCache (options) { |
if (!(this instanceof LRUCache)) |
return new LRUCache(options) |
|
if (typeof options === 'number') |
options = { max: options } |
|
if (!options) |
options = {} |
|
this._max = options.max |
// Kind of weird to have a default max of Infinity, but oh well. |
if (!this._max || !(typeof this._max === "number") || this._max <= 0 ) |
this._max = Infinity |
|
this._lengthCalculator = options.length || naiveLength |
if (typeof this._lengthCalculator !== "function") |
this._lengthCalculator = naiveLength |
|
this._allowStale = options.stale || false |
this._maxAge = options.maxAge || null |
this._dispose = options.dispose |
this.reset() |
} |
|
// resize the cache when the max changes. |
Object.defineProperty(LRUCache.prototype, "max", |
{ set : function (mL) { |
if (!mL || !(typeof mL === "number") || mL <= 0 ) mL = Infinity |
this._max = mL |
if (this._length > this._max) trim(this) |
} |
, get : function () { return this._max } |
, enumerable : true |
}) |
|
// resize the cache when the lengthCalculator changes. |
Object.defineProperty(LRUCache.prototype, "lengthCalculator", |
{ set : function (lC) { |
if (typeof lC !== "function") { |
this._lengthCalculator = naiveLength |
this._length = this._lruList.size |
this._cache.forEach(function (value, key) { |
value.length = 1 |
}) |
} else { |
this._lengthCalculator = lC |
this._length = 0 |
this._cache.forEach(function (value, key) { |
value.length = this._lengthCalculator(value.value, key) |
this._length += value.length |
}, this) |
} |
|
if (this._length > this._max) trim(this) |
} |
, get : function () { return this._lengthCalculator } |
, enumerable : true |
}) |
|
Object.defineProperty(LRUCache.prototype, "length", |
{ get : function () { return this._length } |
, enumerable : true |
}) |
|
Object.defineProperty(LRUCache.prototype, "itemCount", |
{ get : function () { return this._lruList.size } |
, enumerable : true |
}) |
|
function reverseKeys (map) { |
// keys live in lruList map in insertion order. |
// we want them in reverse insertion order. |
// flip the list of keys. |
var itemCount = map.size |
var keys = new Array(itemCount) |
var i = itemCount |
map.forEach(function (value, key) { |
keys[--i] = key |
}) |
|
return keys |
} |
|
LRUCache.prototype.rforEach = function (fn, thisp) { |
thisp = thisp || this |
this._lruList.forEach(function (hit) { |
forEachStep(this, fn, hit, thisp) |
}, this) |
} |
|
function forEachStep (self, fn, hit, thisp) { |
if (isStale(self, hit)) { |
del(self, hit) |
if (!self._allowStale) { |
hit = undefined |
} |
} |
if (hit) { |
fn.call(thisp, hit.value, hit.key, self) |
} |
} |
|
|
LRUCache.prototype.forEach = function (fn, thisp) { |
thisp = thisp || this |
|
var keys = reverseKeys(this._lruList) |
for (var k = 0; k < keys.length; k++) { |
var hit = this._lruList.get(keys[k]) |
forEachStep(this, fn, hit, thisp) |
} |
} |
|
LRUCache.prototype.keys = function () { |
return reverseKeys(this._lruList).map(function (k) { |
return this._lruList.get(k).key |
}, this) |
} |
|
LRUCache.prototype.values = function () { |
return reverseKeys(this._lruList).map(function (k) { |
return this._lruList.get(k).value |
}, this) |
} |
|
LRUCache.prototype.reset = function () { |
if (this._dispose && this._cache) { |
this._cache.forEach(function (entry, key) { |
this._dispose(key, entry.value) |
}, this) |
} |
|
this._cache = new Map() // hash of items by key |
this._lruList = new Map() // list of items in order of use recency |
this._mru = 0 // most recently used |
this._lru = 0 // least recently used |
this._length = 0 // number of items in the list |
} |
|
LRUCache.prototype.dump = function () { |
var arr = [] |
var i = 0 |
var size = this._lruList.size |
return reverseKeys(this._lruList).map(function (k) { |
var hit = this._lruList.get(k) |
if (!isStale(this, hit)) { |
return { |
k: hit.key, |
v: hit.value, |
e: hit.now + (hit.maxAge || 0) |
} |
} |
}, this).filter(function (h) { |
return h |
}) |
} |
|
LRUCache.prototype.dumpLru = function () { |
return this._lruList |
} |
|
LRUCache.prototype.set = function (key, value, maxAge) { |
maxAge = maxAge || this._maxAge |
|
var now = maxAge ? Date.now() : 0 |
var len = this._lengthCalculator(value, key) |
|
if (this._cache.has(key)) { |
if (len > this._max) { |
del(this, this._cache.get(key)) |
return false |
} |
|
var item = this._cache.get(key) |
|
// dispose of the old one before overwriting |
if (this._dispose) |
this._dispose(key, item.value) |
|
item.now = now |
item.maxAge = maxAge |
item.value = value |
this._length += (len - item.length) |
item.length = len |
this.get(key) |
|
if (this._length > this._max) |
trim(this) |
|
return true |
} |
|
var hit = new Entry(key, value, this._mru, len, now, maxAge) |
incMru(this) |
|
// oversized objects fall out of cache automatically. |
if (hit.length > this._max) { |
if (this._dispose) this._dispose(key, value) |
return false |
} |
|
this._length += hit.length |
this._cache.set(key, hit) |
this._lruList.set(hit.lu, hit) |
|
if (this._length > this._max) |
trim(this) |
|
return true |
} |
|
LRUCache.prototype.has = function (key) { |
if (!this._cache.has(key)) return false |
var hit = this._cache.get(key) |
if (isStale(this, hit)) { |
return false |
} |
return true |
} |
|
LRUCache.prototype.get = function (key) { |
return get(this, key, true) |
} |
|
LRUCache.prototype.peek = function (key) { |
return get(this, key, false) |
} |
|
LRUCache.prototype.pop = function () { |
var hit = this._lruList.get(this._lru) |
del(this, hit) |
return hit || null |
} |
|
LRUCache.prototype.del = function (key) { |
del(this, this._cache.get(key)) |
} |
|
LRUCache.prototype.load = function (arr) { |
//reset the cache |
this.reset(); |
|
var now = Date.now() |
// A previous serialized cache has the most recent items first |
for (var l = arr.length - 1; l >= 0; l--) { |
var hit = arr[l] |
var expiresAt = hit.e || 0 |
if (expiresAt === 0) { |
// the item was created without expiration in a non aged cache |
this.set(hit.k, hit.v) |
} else { |
var maxAge = expiresAt - now |
// dont add already expired items |
if (maxAge > 0) { |
this.set(hit.k, hit.v, maxAge) |
} |
} |
} |
} |
|
function get (self, key, doUse) { |
var hit = self._cache.get(key) |
if (hit) { |
if (isStale(self, hit)) { |
del(self, hit) |
if (!self._allowStale) hit = undefined |
} else { |
if (doUse) use(self, hit) |
} |
if (hit) hit = hit.value |
} |
return hit |
} |
|
function isStale(self, hit) { |
if (!hit || (!hit.maxAge && !self._maxAge)) return false |
var stale = false; |
var diff = Date.now() - hit.now |
if (hit.maxAge) { |
stale = diff > hit.maxAge |
} else { |
stale = self._maxAge && (diff > self._maxAge) |
} |
return stale; |
} |
|
function use (self, hit) { |
shiftLU(self, hit) |
hit.lu = self._mru |
incMru(self) |
self._lruList.set(hit.lu, hit) |
} |
|
function trim (self) { |
if (self._length > self._max) { |
var keys = reverseKeys(self._lruList) |
for (var k = keys.length - 1; self._length > self._max; k--) { |
// We know that we're about to delete this one, and also |
// what the next least recently used key will be, so just |
// go ahead and set it now. |
self._lru = keys[k - 1] |
del(self, self._lruList.get(keys[k])) |
} |
} |
} |
|
function shiftLU (self, hit) { |
self._lruList.delete(hit.lu) |
if (hit.lu === self._lru) |
self._lru = reverseKeys(self._lruList).pop() |
} |
|
function del (self, hit) { |
if (hit) { |
if (self._dispose) self._dispose(hit.key, hit.value) |
self._length -= hit.length |
self._cache.delete(hit.key) |
shiftLU(self, hit) |
} |
} |
|
// classy, since V8 prefers predictable objects. |
function Entry (key, value, lu, length, now, maxAge) { |
this.key = key |
this.value = value |
this.lu = lu |
this.length = length |
this.now = now |
if (maxAge) this.maxAge = maxAge |
} |
|
|
// Incrementers and decrementers that loop at MAX_SAFE_INTEGER |
// only relevant for the lu, lru, and mru counters, since they |
// get touched a lot and can get very large. Also, since they |
// only go upwards, and the sets will tend to be much smaller than |
// the max, we can very well assume that a very small number comes |
// after a very large number, rather than before it. |
var maxSafeInt = Number.MAX_SAFE_INTEGER || 9007199254740991 |
function intInc (number) { |
return (number === maxSafeInt) ? 0 : number + 1 |
} |
function incMru (self) { |
do { |
self._mru = intInc(self._mru) |
} while (self._lruList.has(self._mru)) |
} |
/script-kiddie/002_script_kiddie/script-kiddie/node_modules/lru-cache/test/basic.js |
@@ -0,0 +1,427 @@ |
var test = require("tap").test |
, LRU = require("../") |
|
test("basic", function (t) { |
var cache = new LRU({max: 10}) |
cache.set("key", "value") |
t.equal(cache.get("key"), "value") |
t.equal(cache.get("nada"), undefined) |
t.equal(cache.length, 1) |
t.equal(cache.max, 10) |
t.end() |
}) |
|
test("least recently set", function (t) { |
var cache = new LRU(2) |
cache.set("a", "A") |
cache.set("b", "B") |
cache.set("c", "C") |
t.equal(cache.get("c"), "C") |
t.equal(cache.get("b"), "B") |
t.equal(cache.get("a"), undefined) |
t.end() |
}) |
|
test("lru recently gotten", function (t) { |
var cache = new LRU(2) |
cache.set("a", "A") |
cache.set("b", "B") |
cache.get("a") |
cache.set("c", "C") |
t.equal(cache.get("c"), "C") |
t.equal(cache.get("b"), undefined) |
t.equal(cache.get("a"), "A") |
t.end() |
}) |
|
test("del", function (t) { |
var cache = new LRU(2) |
cache.set("a", "A") |
cache.del("a") |
t.equal(cache.get("a"), undefined) |
t.end() |
}) |
|
test("max", function (t) { |
var cache = new LRU(3) |
|
// test changing the max, verify that the LRU items get dropped. |
cache.max = 100 |
for (var i = 0; i < 100; i ++) cache.set(i, i) |
t.equal(cache.length, 100) |
for (var i = 0; i < 100; i ++) { |
t.equal(cache.get(i), i) |
} |
cache.max = 3 |
t.equal(cache.length, 3) |
for (var i = 0; i < 97; i ++) { |
t.equal(cache.get(i), undefined) |
} |
for (var i = 98; i < 100; i ++) { |
t.equal(cache.get(i), i) |
} |
|
// now remove the max restriction, and try again. |
cache.max = "hello" |
for (var i = 0; i < 100; i ++) cache.set(i, i) |
t.equal(cache.length, 100) |
for (var i = 0; i < 100; i ++) { |
t.equal(cache.get(i), i) |
} |
// should trigger an immediate resize |
cache.max = 3 |
t.equal(cache.length, 3) |
for (var i = 0; i < 97; i ++) { |
t.equal(cache.get(i), undefined) |
} |
for (var i = 98; i < 100; i ++) { |
t.equal(cache.get(i), i) |
} |
t.end() |
}) |
|
test("reset", function (t) { |
var cache = new LRU(10) |
cache.set("a", "A") |
cache.set("b", "B") |
cache.reset() |
t.equal(cache.length, 0) |
t.equal(cache.max, 10) |
t.equal(cache.get("a"), undefined) |
t.equal(cache.get("b"), undefined) |
t.end() |
}) |
|
|
test("basic with weighed length", function (t) { |
var cache = new LRU({ |
max: 100, |
length: function (item, key) { |
t.isa(key, 'string') |
return item.size |
} |
}) |
cache.set("key", {val: "value", size: 50}) |
t.equal(cache.get("key").val, "value") |
t.equal(cache.get("nada"), undefined) |
t.equal(cache.lengthCalculator(cache.get("key"), 'key'), 50) |
t.equal(cache.length, 50) |
t.equal(cache.max, 100) |
t.end() |
}) |
|
|
test("weighed length item too large", function (t) { |
var cache = new LRU({ |
max: 10, |
length: function (item) { return item.size } |
}) |
t.equal(cache.max, 10) |
|
// should fall out immediately |
cache.set("key", {val: "value", size: 50}) |
|
t.equal(cache.length, 0) |
t.equal(cache.get("key"), undefined) |
t.end() |
}) |
|
test("least recently set with weighed length", function (t) { |
var cache = new LRU({ |
max:8, |
length: function (item) { return item.length } |
}) |
cache.set("a", "A") |
cache.set("b", "BB") |
cache.set("c", "CCC") |
cache.set("d", "DDDD") |
t.equal(cache.get("d"), "DDDD") |
t.equal(cache.get("c"), "CCC") |
t.equal(cache.get("b"), undefined) |
t.equal(cache.get("a"), undefined) |
t.end() |
}) |
|
test("lru recently gotten with weighed length", function (t) { |
var cache = new LRU({ |
max: 8, |
length: function (item) { return item.length } |
}) |
cache.set("a", "A") |
cache.set("b", "BB") |
cache.set("c", "CCC") |
cache.get("a") |
cache.get("b") |
cache.set("d", "DDDD") |
t.equal(cache.get("c"), undefined) |
t.equal(cache.get("d"), "DDDD") |
t.equal(cache.get("b"), "BB") |
t.equal(cache.get("a"), "A") |
t.end() |
}) |
|
test("lru recently updated with weighed length", function (t) { |
var cache = new LRU({ |
max: 8, |
length: function (item) { return item.length } |
}) |
cache.set("a", "A") |
cache.set("b", "BB") |
cache.set("c", "CCC") |
t.equal(cache.length, 6) //CCC BB A |
cache.set("a", "+A") |
t.equal(cache.length, 7) //+A CCC BB |
cache.set("b", "++BB") |
t.equal(cache.length, 6) //++BB +A |
t.equal(cache.get("c"), undefined) |
|
cache.set("c", "oversized") |
t.equal(cache.length, 6) //++BB +A |
t.equal(cache.get("c"), undefined) |
|
cache.set("a", "oversized") |
t.equal(cache.length, 4) //++BB |
t.equal(cache.get("a"), undefined) |
t.equal(cache.get("b"), "++BB") |
t.end() |
}) |
|
test("set returns proper booleans", function(t) { |
var cache = new LRU({ |
max: 5, |
length: function (item) { return item.length } |
}) |
|
t.equal(cache.set("a", "A"), true) |
|
// should return false for max exceeded |
t.equal(cache.set("b", "donuts"), false) |
|
t.equal(cache.set("b", "B"), true) |
t.equal(cache.set("c", "CCCC"), true) |
t.end() |
}) |
|
test("drop the old items", function(t) { |
var cache = new LRU({ |
max: 5, |
maxAge: 50 |
}) |
|
cache.set("a", "A") |
|
setTimeout(function () { |
cache.set("b", "b") |
t.equal(cache.get("a"), "A") |
}, 25) |
|
setTimeout(function () { |
cache.set("c", "C") |
// timed out |
t.notOk(cache.get("a")) |
}, 60 + 25) |
|
setTimeout(function () { |
t.notOk(cache.get("b")) |
t.equal(cache.get("c"), "C") |
}, 90) |
|
setTimeout(function () { |
t.notOk(cache.get("c")) |
t.end() |
}, 155) |
}) |
|
test("individual item can have its own maxAge", function(t) { |
var cache = new LRU({ |
max: 5, |
maxAge: 50 |
}) |
|
cache.set("a", "A", 20) |
setTimeout(function () { |
t.notOk(cache.get("a")) |
t.end() |
}, 25) |
}) |
|
test("individual item can have its own maxAge > cache's", function(t) { |
var cache = new LRU({ |
max: 5, |
maxAge: 20 |
}) |
|
cache.set("a", "A", 50) |
setTimeout(function () { |
t.equal(cache.get("a"), "A") |
t.end() |
}, 25) |
}) |
|
test("disposal function", function(t) { |
var disposed = false |
var cache = new LRU({ |
max: 1, |
dispose: function (k, n) { |
disposed = n |
} |
}) |
|
cache.set(1, 1) |
cache.set(2, 2) |
t.equal(disposed, 1) |
cache.set(3, 3) |
t.equal(disposed, 2) |
cache.reset() |
t.equal(disposed, 3) |
t.end() |
}) |
|
test("disposal function on too big of item", function(t) { |
var disposed = false |
var cache = new LRU({ |
max: 1, |
length: function (k) { |
return k.length |
}, |
dispose: function (k, n) { |
disposed = n |
} |
}) |
var obj = [ 1, 2 ] |
|
t.equal(disposed, false) |
cache.set("obj", obj) |
t.equal(disposed, obj) |
t.end() |
}) |
|
test("has()", function(t) { |
var cache = new LRU({ |
max: 1, |
maxAge: 10 |
}) |
|
cache.set('foo', 'bar') |
t.equal(cache.has('foo'), true) |
cache.set('blu', 'baz') |
t.equal(cache.has('foo'), false) |
t.equal(cache.has('blu'), true) |
setTimeout(function() { |
t.equal(cache.has('blu'), false) |
t.end() |
}, 15) |
}) |
|
test("stale", function(t) { |
var cache = new LRU({ |
maxAge: 10, |
stale: true |
}) |
|
cache.set('foo', 'bar') |
t.equal(cache.get('foo'), 'bar') |
t.equal(cache.has('foo'), true) |
setTimeout(function() { |
t.equal(cache.has('foo'), false) |
t.equal(cache.get('foo'), 'bar') |
t.equal(cache.get('foo'), undefined) |
t.end() |
}, 15) |
}) |
|
test("lru update via set", function(t) { |
var cache = LRU({ max: 2 }); |
|
cache.set('foo', 1); |
cache.set('bar', 2); |
cache.del('bar'); |
cache.set('baz', 3); |
cache.set('qux', 4); |
|
t.equal(cache.get('foo'), undefined) |
t.equal(cache.get('bar'), undefined) |
t.equal(cache.get('baz'), 3) |
t.equal(cache.get('qux'), 4) |
t.end() |
}) |
|
test("least recently set w/ peek", function (t) { |
var cache = new LRU(2) |
cache.set("a", "A") |
cache.set("b", "B") |
t.equal(cache.peek("a"), "A") |
cache.set("c", "C") |
t.equal(cache.get("c"), "C") |
t.equal(cache.get("b"), "B") |
t.equal(cache.get("a"), undefined) |
t.end() |
}) |
|
test("pop the least used item", function (t) { |
var cache = new LRU(3) |
, last |
|
cache.set("a", "A") |
cache.set("b", "B") |
cache.set("c", "C") |
|
t.equal(cache.length, 3) |
t.equal(cache.max, 3) |
|
// Ensure we pop a, c, b |
cache.get("b", "B") |
|
last = cache.pop() |
t.equal(last.key, "a") |
t.equal(last.value, "A") |
t.equal(cache.length, 2) |
t.equal(cache.max, 3) |
|
last = cache.pop() |
t.equal(last.key, "c") |
t.equal(last.value, "C") |
t.equal(cache.length, 1) |
t.equal(cache.max, 3) |
|
last = cache.pop() |
t.equal(last.key, "b") |
t.equal(last.value, "B") |
t.equal(cache.length, 0) |
t.equal(cache.max, 3) |
|
last = cache.pop() |
t.equal(last, null) |
t.equal(cache.length, 0) |
t.equal(cache.max, 3) |
|
t.end() |
}) |
|
test("get and set only accepts strings and numbers as keys", function(t) { |
var cache = new LRU() |
|
cache.set("key", "value") |
cache.set(123, 456) |
|
t.equal(cache.get("key"), "value") |
t.equal(cache.get(123), 456) |
|
t.end() |
}) |
|
test("peek with wierd keys", function(t) { |
var cache = new LRU() |
|
cache.set("key", "value") |
cache.set(123, 456) |
|
t.equal(cache.peek("key"), "value") |
t.equal(cache.peek(123), 456) |
|
t.equal(cache.peek({ |
toString: function() { return "key" } |
}), undefined) |
|
t.end() |
}) |
/script-kiddie/002_script_kiddie/script-kiddie/node_modules/lru-cache/test/foreach.js |
@@ -0,0 +1,130 @@ |
var test = require('tap').test |
var LRU = require('../') |
|
test('forEach', function (t) { |
var l = new LRU(5) |
for (var i = 0; i < 10; i ++) { |
l.set(i, i.toString(2)) |
} |
|
var i = 9 |
l.forEach(function (val, key, cache) { |
t.equal(cache, l) |
t.equal(key, i) |
t.equal(val, i.toString(2)) |
i -= 1 |
}) |
|
// get in order of most recently used |
l.get(6) |
l.get(8) |
|
var order = [ 8, 6, 9, 7, 5 ] |
var i = 0 |
|
l.forEach(function (val, key, cache) { |
var j = order[i ++] |
t.equal(cache, l) |
t.equal(key, j) |
t.equal(val, j.toString(2)) |
}) |
t.equal(i, order.length) |
|
i = 0 |
order.reverse() |
l.rforEach(function (val, key, cache) { |
var j = order[i ++] |
t.equal(cache, l) |
t.equal(key, j) |
t.equal(val, j.toString(2)) |
}) |
t.equal(i, order.length) |
|
t.end() |
}) |
|
test('keys() and values()', function (t) { |
var l = new LRU(5) |
for (var i = 0; i < 10; i ++) { |
l.set(i, i.toString(2)) |
} |
|
t.similar(l.keys(), [9, 8, 7, 6, 5]) |
t.similar(l.values(), ['1001', '1000', '111', '110', '101']) |
|
// get in order of most recently used |
l.get(6) |
l.get(8) |
|
t.similar(l.keys(), [8, 6, 9, 7, 5]) |
t.similar(l.values(), ['1000', '110', '1001', '111', '101']) |
|
t.end() |
}) |
|
test('all entries are iterated over', function(t) { |
var l = new LRU(5) |
for (var i = 0; i < 10; i ++) { |
l.set(i.toString(), i.toString(2)) |
} |
|
var i = 0 |
l.forEach(function (val, key, cache) { |
if (i > 0) { |
cache.del(key) |
} |
i += 1 |
}) |
|
t.equal(i, 5) |
t.equal(l.keys().length, 1) |
|
t.end() |
}) |
|
test('all stale entries are removed', function(t) { |
var l = new LRU({ max: 5, maxAge: -5, stale: true }) |
for (var i = 0; i < 10; i ++) { |
l.set(i.toString(), i.toString(2)) |
} |
|
var i = 0 |
l.forEach(function () { |
i += 1 |
}) |
|
t.equal(i, 5) |
t.equal(l.keys().length, 0) |
|
t.end() |
}) |
|
test('expires', function (t) { |
var l = new LRU({ |
max: 10, |
maxAge: 50 |
}) |
for (var i = 0; i < 10; i++) { |
l.set(i.toString(), i.toString(2), ((i % 2) ? 25 : undefined)) |
} |
|
var i = 0 |
var order = [ 8, 6, 4, 2, 0 ] |
setTimeout(function () { |
l.forEach(function (val, key, cache) { |
var j = order[i++] |
t.equal(cache, l) |
t.equal(key, j.toString()) |
t.equal(val, j.toString(2)) |
}) |
t.equal(i, order.length); |
|
setTimeout(function () { |
var count = 0; |
l.forEach(function (val, key, cache) { count++; }) |
t.equal(0, count); |
t.end() |
}, 25) |
|
}, 26) |
}) |
/script-kiddie/002_script_kiddie/script-kiddie/node_modules/lru-cache/test/serialize.js |
@@ -0,0 +1,224 @@ |
var test = require('tap').test |
var LRU = require('../') |
|
test('dump', function (t) { |
var cache = new LRU() |
|
t.equal(cache.dump().length, 0, "nothing in dump for empty cache") |
|
cache.set("a", "A") |
cache.set("b", "B") |
t.deepEqual(cache.dump(), [ |
{ k: "b", v: "B", e: 0 }, |
{ k: "a", v: "A", e: 0 } |
]) |
|
cache.set(123, 456) |
t.deepEqual(cache.dump(), [ |
{ k: 123, v: 456, e: 0 }, |
{ k: "b", v: "B", e: 0 }, |
{ k: "a", v: "A", e: 0 }, |
]) |
cache.del(123) |
|
cache.set("a", "A"); |
t.deepEqual(cache.dump(), [ |
{ k: "a", v: "A", e: 0 }, |
{ k: "b", v: "B", e: 0 } |
]) |
|
cache.get("b"); |
t.deepEqual(cache.dump(), [ |
{ k: "b", v: "B", e: 0 }, |
{ k: "a", v: "A", e: 0 } |
]) |
|
cache.del("a"); |
t.deepEqual(cache.dump(), [ |
{ k: "b", v: "B", e: 0 } |
]) |
|
t.end() |
}) |
|
test("do not dump stale items", function(t) { |
var cache = new LRU({ |
max: 5, |
maxAge: 50 |
}) |
|
//expires at 50 |
cache.set("a", "A") |
|
setTimeout(function () { |
//expires at 75 |
cache.set("b", "B") |
var s = cache.dump() |
t.equal(s.length, 2) |
t.equal(s[0].k, "b") |
t.equal(s[1].k, "a") |
}, 25) |
|
setTimeout(function () { |
//expires at 110 |
cache.set("c", "C") |
var s = cache.dump() |
t.equal(s.length, 2) |
t.equal(s[0].k, "c") |
t.equal(s[1].k, "b") |
}, 60) |
|
setTimeout(function () { |
//expires at 130 |
cache.set("d", "D", 40) |
var s = cache.dump() |
t.equal(s.length, 2) |
t.equal(s[0].k, "d") |
t.equal(s[1].k, "c") |
}, 90) |
|
setTimeout(function () { |
var s = cache.dump() |
t.equal(s.length, 1) |
t.equal(s[0].k, "d") |
}, 120) |
|
setTimeout(function () { |
var s = cache.dump() |
t.deepEqual(s, []) |
t.end() |
}, 155) |
}) |
|
test("load basic cache", function(t) { |
var cache = new LRU(), |
copy = new LRU() |
|
cache.set("a", "A") |
cache.set("b", "B") |
cache.set(123, 456) |
|
copy.load(cache.dump()) |
t.deepEquals(cache.dump(), copy.dump()) |
|
t.end() |
}) |
|
|
test("load staled cache", function(t) { |
var cache = new LRU({maxAge: 50}), |
copy = new LRU({maxAge: 50}), |
arr |
|
//expires at 50 |
cache.set("a", "A") |
setTimeout(function () { |
//expires at 80 |
cache.set("b", "B") |
arr = cache.dump() |
t.equal(arr.length, 2) |
}, 30) |
|
setTimeout(function () { |
copy.load(arr) |
t.equal(copy.get("a"), undefined) |
t.equal(copy.get("b"), "B") |
}, 60) |
|
setTimeout(function () { |
t.equal(copy.get("b"), undefined) |
t.end() |
}, 90) |
}) |
|
test("load to other size cache", function(t) { |
var cache = new LRU({max: 2}), |
copy = new LRU({max: 1}) |
|
cache.set("a", "A") |
cache.set("b", "B") |
|
copy.load(cache.dump()) |
t.equal(copy.get("a"), undefined) |
t.equal(copy.get("b"), "B") |
|
//update the last read from original cache |
cache.get("a") |
copy.load(cache.dump()) |
t.equal(copy.get("a"), "A") |
t.equal(copy.get("b"), undefined) |
|
t.end() |
}) |
|
|
test("load to other age cache", function(t) { |
var cache = new LRU({maxAge: 50}), |
aged = new LRU({maxAge: 100}), |
simple = new LRU(), |
arr, |
expired |
|
//created at 0 |
//a would be valid till 0 + 50 |
cache.set("a", "A") |
setTimeout(function () { |
//created at 20 |
//b would be valid till 20 + 50 |
cache.set("b", "B") |
//b would be valid till 20 + 70 |
cache.set("c", "C", 70) |
arr = cache.dump() |
t.equal(arr.length, 3) |
}, 20) |
|
setTimeout(function () { |
t.equal(cache.get("a"), undefined) |
t.equal(cache.get("b"), "B") |
t.equal(cache.get("c"), "C") |
|
aged.load(arr) |
t.equal(aged.get("a"), undefined) |
t.equal(aged.get("b"), "B") |
t.equal(aged.get("c"), "C") |
|
simple.load(arr) |
t.equal(simple.get("a"), undefined) |
t.equal(simple.get("b"), "B") |
t.equal(simple.get("c"), "C") |
}, 60) |
|
setTimeout(function () { |
t.equal(cache.get("a"), undefined) |
t.equal(cache.get("b"), undefined) |
t.equal(cache.get("c"), "C") |
|
aged.load(arr) |
t.equal(aged.get("a"), undefined) |
t.equal(aged.get("b"), undefined) |
t.equal(aged.get("c"), "C") |
|
simple.load(arr) |
t.equal(simple.get("a"), undefined) |
t.equal(simple.get("b"), undefined) |
t.equal(simple.get("c"), "C") |
}, 80) |
|
setTimeout(function () { |
t.equal(cache.get("a"), undefined) |
t.equal(cache.get("b"), undefined) |
t.equal(cache.get("c"), undefined) |
|
aged.load(arr) |
t.equal(aged.get("a"), undefined) |
t.equal(aged.get("b"), undefined) |
t.equal(aged.get("c"), undefined) |
|
simple.load(arr) |
t.equal(simple.get("a"), undefined) |
t.equal(simple.get("b"), undefined) |
t.equal(simple.get("c"), undefined) |
t.end() |
}, 100) |
|
}) |