Browse Source

Merge branch 'release/0.16.0'

feature/specify-what-to-cache 0.16.0
Bryan Donovan 10 years ago
parent
commit
8a014ee185
  1. 19
      .jscs.json
  2. 4
      History.md
  3. 40
      examples/example.js
  4. 18
      examples/redis_example/example.js
  5. 30
      examples/redis_example/redis_store.js
  6. 10
      lib/caching.js
  7. 29
      lib/multi_caching.js
  8. 18
      lib/stores/memory.js
  9. 4
      package.json
  10. 278
      test/caching.unit.js
  11. 310
      test/multi_caching.unit.js
  12. 12
      test/run.js
  13. 6
      test/stores/memory.unit.js
  14. 30
      test/support.js

19
.jscs.json

@ -24,6 +24,7 @@
"requireParenthesesAroundIIFE": true, "requireParenthesesAroundIIFE": true,
"requireSpaceBeforeBlockStatements": true, "requireSpaceBeforeBlockStatements": true,
"disallowNewlineBeforeBlockStatements": true,
"requireSpacesInConditionalExpression": true, "requireSpacesInConditionalExpression": true,
@ -31,6 +32,18 @@
"beforeOpeningCurlyBrace": true "beforeOpeningCurlyBrace": true
}, },
"disallowSpacesInAnonymousFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionDeclaration": {
"beforeOpeningRoundBrace": true
},
"disallowSpacesInFunctionExpression": {
"beforeOpeningRoundBrace": true
},
"requireSpaceBeforeBinaryOperators": [ "requireSpaceBeforeBinaryOperators": [
"+", "+",
"-", "-",
@ -62,6 +75,12 @@
"safeContextKeyword": "self", "safeContextKeyword": "self",
"maximumLineLength": {
"value": 120,
"allowUrlComments": true,
"allowRegex": true
},
"validateIndentation": 4, "validateIndentation": 4,
"validateParameterSeparator": ", ", "validateParameterSeparator": ", ",

4
History.md

@ -1,3 +1,7 @@
- 0.16.0 2015-01-07
Get and pass up feature to update higher caches. (#19) - raadad
Minor style tweaks/jscs update.
- 0.15.0 2014-12-18 - 0.15.0 2014-12-18
Moved cache queue before the store get function (up to 2x performance boost). (#18) - aletorrado Moved cache queue before the store get function (up to 2x performance boost). (#18) - aletorrado
Added domain support to make sure the wrap callback function is always called - aletorrado Added domain support to make sure the wrap callback function is always called - aletorrado

40
examples/example.js

@ -8,13 +8,13 @@ var ttl; //Can't use a different ttl per set() call with memory cache
// //
// Basic usage // Basic usage
// //
memory_cache.set('foo', 'bar', ttl, function (err) { memory_cache.set('foo', 'bar', ttl, function(err) {
if (err) { throw err; } if (err) { throw err; }
memory_cache.get('foo', function (err, result) { memory_cache.get('foo', function(err, result) {
console.log(result); console.log(result);
// >> 'bar' // >> 'bar'
memory_cache.del('foo', function (err) { memory_cache.del('foo', function(err) {
if (err) { if (err) {
console.log(err); console.log(err);
} }
@ -23,7 +23,7 @@ memory_cache.set('foo', 'bar', ttl, function (err) {
}); });
function get_user(id, cb) { function get_user(id, cb) {
setTimeout(function () { setTimeout(function() {
console.log("Fetching user from slow database."); console.log("Fetching user from slow database.");
cb(null, {id: id, name: 'Bob'}); cb(null, {id: id, name: 'Bob'});
}, 100); }, 100);
@ -38,14 +38,14 @@ var key = 'user_' + user_id;
// Instead of manually managing the cache like this: // Instead of manually managing the cache like this:
function get_cached_user_manually(id, cb) { function get_cached_user_manually(id, cb) {
memory_cache.get(id, function (err, result) { memory_cache.get(id, function(err, result) {
if (err) { return cb(err); } if (err) { return cb(err); }
if (result) { if (result) {
return cb(null, result); return cb(null, result);
} }
get_user(id, function (err, result) { get_user(id, function(err, result) {
if (err) { return cb(err); } if (err) { return cb(err); }
memory_cache.set(id, result); memory_cache.set(id, result);
cb(null, result); cb(null, result);
@ -55,16 +55,16 @@ function get_cached_user_manually(id, cb) {
// ... you can instead use the `wrap` function: // ... you can instead use the `wrap` function:
function get_cached_user(id, cb) { function get_cached_user(id, cb) {
memory_cache.wrap(id, function (cache_callback) { memory_cache.wrap(id, function(cache_callback) {
get_user(id, cache_callback); get_user(id, cache_callback);
}, cb); }, cb);
} }
get_cached_user(user_id, function (err, user) { get_cached_user(user_id, function(err, user) {
// First time fetches the user from the (fake) database: // First time fetches the user from the (fake) database:
console.log(user); console.log(user);
get_cached_user(user_id, function (err, user) { get_cached_user(user_id, function(err, user) {
// Second time fetches from cache. // Second time fetches from cache.
console.log(user); console.log(user);
}); });
@ -76,15 +76,15 @@ get_cached_user(user_id, function (err, user) {
// { id: 123, name: 'Bob' } // { id: 123, name: 'Bob' }
// Same as above, but written differently: // Same as above, but written differently:
memory_cache.wrap(key, function (cb) { memory_cache.wrap(key, function(cb) {
get_user(user_id, cb); get_user(user_id, cb);
}, function (err, user) { }, function(err, user) {
console.log(user); console.log(user);
// Second time fetches user from memory_cache // Second time fetches user from memory_cache
memory_cache.wrap(key, function (cb) { memory_cache.wrap(key, function(cb) {
get_user(user_id, cb); get_user(user_id, cb);
}, function (err, user) { }, function(err, user) {
console.log(user); console.log(user);
}); });
}); });
@ -97,31 +97,31 @@ var user_id2 = 456;
var key2 = 'user_' + user_id; var key2 = 'user_' + user_id;
var ttl2; //Can't use a different ttl per set() call with memory cache var ttl2; //Can't use a different ttl per set() call with memory cache
multi_cache.wrap(key2, function (cb) { multi_cache.wrap(key2, function(cb) {
get_user(user_id2, cb); get_user(user_id2, cb);
}, function (err, user) { }, function(err, user) {
console.log(user); console.log(user);
// Second time fetches user from memory_cache, since it's highest priority. // Second time fetches user from memory_cache, since it's highest priority.
// If the data expires in the memory cache, the next fetch would pull it from // If the data expires in the memory cache, the next fetch would pull it from
// the Redis cache, and set the data in memory again. // the Redis cache, and set the data in memory again.
multi_cache.wrap(key2, function (cb) { multi_cache.wrap(key2, function(cb) {
get_user(user_id2, cb); get_user(user_id2, cb);
}, function (err, user) { }, function(err, user) {
console.log(user); console.log(user);
}); });
// Sets in all caches. // Sets in all caches.
multi_cache.set('foo2', 'bar2', ttl2, function (err) { multi_cache.set('foo2', 'bar2', ttl2, function(err) {
if (err) { throw err; } if (err) { throw err; }
// Fetches from highest priority cache that has the key. // Fetches from highest priority cache that has the key.
multi_cache.get('foo2', function (err, result) { multi_cache.get('foo2', function(err, result) {
console.log(result); console.log(result);
// >> 'bar2' // >> 'bar2'
// Delete from all caches // Delete from all caches
multi_cache.del('foo2', function (err) { multi_cache.del('foo2', function(err) {
if (err) { if (err) {
console.log(err); console.log(err);
} }

18
examples/redis_example/example.js

@ -10,14 +10,14 @@ var redis_cache = cache_manager.caching({store: redis_store, db: 0, ttl: 100});
var ttl = 60; var ttl = 60;
console.log("set/get/del example:"); console.log("set/get/del example:");
redis_cache.set('foo', 'bar', ttl, function (err) { redis_cache.set('foo', 'bar', ttl, function(err) {
if (err) { throw err; } if (err) { throw err; }
redis_cache.get('foo', function (err, result) { redis_cache.get('foo', function(err, result) {
if (err) { throw err; } if (err) { throw err; }
console.log("result fetched from cache: " + result); console.log("result fetched from cache: " + result);
// >> 'bar' // >> 'bar'
redis_cache.del('foo', function (err) { redis_cache.del('foo', function(err) {
if (err) { throw err; } if (err) { throw err; }
}); });
}); });
@ -30,7 +30,7 @@ function create_key(id) {
} }
function get_user(id, cb) { function get_user(id, cb) {
setTimeout(function () { setTimeout(function() {
console.log("\n\nReturning user from slow database."); console.log("\n\nReturning user from slow database.");
cb(null, {id: id, name: 'Bob'}); cb(null, {id: id, name: 'Bob'});
}, 100); }, 100);
@ -38,24 +38,24 @@ function get_user(id, cb) {
function get_user_from_cache(id, cb) { function get_user_from_cache(id, cb) {
var key = create_key(id); var key = create_key(id);
redis_cache.wrap(key, function (cache_cb) { redis_cache.wrap(key, function(cache_cb) {
get_user(user_id, cache_cb); get_user(user_id, cache_cb);
}, ttl, cb); }, ttl, cb);
} }
get_user_from_cache(user_id, function (err, user) { get_user_from_cache(user_id, function(err, user) {
console.log(user); console.log(user);
// Second time fetches user from redis_cache // Second time fetches user from redis_cache
get_user_from_cache(user_id, function (err, user) { get_user_from_cache(user_id, function(err, user) {
console.log("user from second cache request:"); console.log("user from second cache request:");
console.log(user); console.log(user);
redis_cache.keys(function (err, keys) { redis_cache.keys(function(err, keys) {
console.log("keys: " + util.inspect(keys)); console.log("keys: " + util.inspect(keys));
var key = create_key(user_id); var key = create_key(user_id);
redis_cache.del(key, function (err) { redis_cache.del(key, function(err) {
if (err) { throw err; } if (err) { throw err; }
process.exit(); process.exit();
}); });

30
examples/redis_example/redis_store.js

@ -20,7 +20,7 @@ function redis_store(args) {
var pool = new RedisPool(redis_options); var pool = new RedisPool(redis_options);
function connect(cb) { function connect(cb) {
pool.acquire(function (err, conn) { pool.acquire(function(err, conn) {
if (err) { if (err) {
pool.release(conn); pool.release(conn);
return cb(err); return cb(err);
@ -34,11 +34,11 @@ function redis_store(args) {
}); });
} }
self.get = function (key, cb) { self.get = function(key, cb) {
connect(function (err, conn) { connect(function(err, conn) {
if (err) { return cb(err); } if (err) { return cb(err); }
conn.get(key, function (err, result) { conn.get(key, function(err, result) {
pool.release(conn); pool.release(conn);
if (err) { return cb(err); } if (err) { return cb(err); }
cb(null, JSON.parse(result)); cb(null, JSON.parse(result));
@ -46,18 +46,18 @@ function redis_store(args) {
}); });
}; };
self.set = function (key, value, ttl, cb) { self.set = function(key, value, ttl, cb) {
var ttlToUse = ttl || ttlDefault; var ttlToUse = ttl || ttlDefault;
connect(function (err, conn) { connect(function(err, conn) {
if (err) { return cb(err); } if (err) { return cb(err); }
if (ttlToUse) { if (ttlToUse) {
conn.setex(key, ttlToUse, JSON.stringify(value), function (err, result) { conn.setex(key, ttlToUse, JSON.stringify(value), function(err, result) {
pool.release(conn); pool.release(conn);
cb(err, result); cb(err, result);
}); });
} else { } else {
conn.set(key, JSON.stringify(value), function (err, result) { conn.set(key, JSON.stringify(value), function(err, result) {
pool.release(conn); pool.release(conn);
cb(err, result); cb(err, result);
}); });
@ -65,27 +65,27 @@ function redis_store(args) {
}); });
}; };
self.del = function (key, cb) { self.del = function(key, cb) {
connect(function (err, conn) { connect(function(err, conn) {
if (err) { return cb(err); } if (err) { return cb(err); }
conn.del(key, function (err, result) { conn.del(key, function(err, result) {
pool.release(conn); pool.release(conn);
cb(err, result); cb(err, result);
}); });
}); });
}; };
self.keys = function (pattern, cb) { self.keys = function(pattern, cb) {
if (typeof pattern === 'function') { if (typeof pattern === 'function') {
cb = pattern; cb = pattern;
pattern = '*'; pattern = '*';
} }
connect(function (err, conn) { connect(function(err, conn) {
if (err) { return cb(err); } if (err) { return cb(err); }
conn.keys(pattern, function (err, result) { conn.keys(pattern, function(err, result) {
pool.release(conn); pool.release(conn);
cb(err, result); cb(err, result);
}); });
@ -96,7 +96,7 @@ function redis_store(args) {
} }
module.exports = { module.exports = {
create: function (args) { create: function(args) {
return redis_store(args); return redis_store(args);
} }
}; };

10
lib/caching.js

@ -1,7 +1,7 @@
/*jshint maxcomplexity:15*/ /*jshint maxcomplexity:15*/
var domain = require('domain'); var domain = require('domain');
var caching = function (args) { var caching = function(args) {
args = args || {}; args = args || {};
var self = {}; var self = {};
if (typeof args.store === 'object') { if (typeof args.store === 'object') {
@ -36,7 +36,7 @@ var caching = function (args) {
* console.log(user); * console.log(user);
* }); * });
*/ */
self.wrap = function (key, work, ttl, cb) { self.wrap = function(key, work, ttl, cb) {
if (typeof ttl === 'function') { if (typeof ttl === 'function') {
cb = ttl; cb = ttl;
ttl = undefined; ttl = undefined;
@ -57,7 +57,7 @@ var caching = function (args) {
delete self.queues[key]; delete self.queues[key];
} }
self.store.get(key, function (err, result) { self.store.get(key, function(err, result) {
if (err && (!self.ignoreCacheErrors)) { if (err && (!self.ignoreCacheErrors)) {
fillCallbacks(err); fillCallbacks(err);
} else if (result) { } else if (result) {
@ -68,12 +68,12 @@ var caching = function (args) {
.on('error', function(err) { .on('error', function(err) {
fillCallbacks(err); fillCallbacks(err);
}) })
.bind(work)(function (err, data) { .bind(work)(function(err, data) {
if (err) { if (err) {
fillCallbacks(err); fillCallbacks(err);
return; return;
} }
self.store.set(key, data, ttl, function (err) { self.store.set(key, data, ttl, function(err) {
if (err && (!self.ignoreCacheErrors)) { if (err && (!self.ignoreCacheErrors)) {
fillCallbacks(err); fillCallbacks(err);
} else { } else {

29
lib/multi_caching.js

@ -4,7 +4,7 @@ var domain = require('domain');
/** /**
* Module that lets you specify a hierarchy of caches. * Module that lets you specify a hierarchy of caches.
*/ */
var multi_caching = function (caches) { var multi_caching = function(caches) {
var self = {}; var self = {};
if (!Array.isArray(caches)) { throw new Error('multi_caching requires an array of caches'); } if (!Array.isArray(caches)) { throw new Error('multi_caching requires an array of caches'); }
@ -12,8 +12,8 @@ var multi_caching = function (caches) {
function get_from_highest_priority_cache(key, cb) { function get_from_highest_priority_cache(key, cb) {
var i = 0; var i = 0;
async.forEachSeries(caches, function (cache, async_cb) { async.forEachSeries(caches, function(cache, async_cb) {
cache.store.get(key, function (err, result) { cache.store.get(key, function(err, result) {
if (err) { return cb(err); } if (err) { return cb(err); }
if (result) { if (result) {
// break out of async loop. // break out of async loop.
@ -27,17 +27,16 @@ var multi_caching = function (caches) {
} }
function set_in_multiple_caches(caches, opts, cb) { function set_in_multiple_caches(caches, opts, cb) {
async.forEach(caches, function (cache, async_cb) { async.forEach(caches, function(cache, async_cb) {
cache.store.set(opts.key, opts.value, opts.ttl, async_cb); cache.store.set(opts.key, opts.value, opts.ttl, async_cb);
}, cb); }, cb);
} }
/** /**
* Looks for an item in cache tiers. * Looks for an item in cache tiers.
* *
* When a key is found in a lower cache, all higher levels are updated * When a key is found in a lower cache, all higher levels are updated
*/ */
self.get_and_pass_up = function(key, cb) { self.get_and_pass_up = function(key, cb) {
get_from_highest_priority_cache(key, function(err, result, index) { get_from_highest_priority_cache(key, function(err, result, index) {
if (err) { if (err) {
@ -65,7 +64,7 @@ var multi_caching = function (caches) {
* If a key doesn't exist in a higher-priority cache but exists in a lower-priority * If a key doesn't exist in a higher-priority cache but exists in a lower-priority
* cache, it gets set in all higher-priority caches. * cache, it gets set in all higher-priority caches.
*/ */
self.wrap = function (key, work, ttl, cb) { self.wrap = function(key, work, ttl, cb) {
if (typeof ttl === 'function') { if (typeof ttl === 'function') {
cb = ttl; cb = ttl;
ttl = undefined; ttl = undefined;
@ -86,7 +85,7 @@ var multi_caching = function (caches) {
delete self.queues[key]; delete self.queues[key];
} }
get_from_highest_priority_cache(key, function (err, result, index) { get_from_highest_priority_cache(key, function(err, result, index) {
if (err) { if (err) {
return fillCallbacks(err); return fillCallbacks(err);
} else if (result) { } else if (result) {
@ -96,7 +95,7 @@ var multi_caching = function (caches) {
value: result, value: result,
ttl: ttl ttl: ttl
}; };
set_in_multiple_caches(caches_to_update, opts, function (err) { set_in_multiple_caches(caches_to_update, opts, function(err) {
fillCallbacks(err, result); fillCallbacks(err, result);
}); });
} else { } else {
@ -105,7 +104,7 @@ var multi_caching = function (caches) {
.on('error', function(err) { .on('error', function(err) {
fillCallbacks(err); fillCallbacks(err);
}) })
.bind(work)(function (err, data) { .bind(work)(function(err, data) {
if (err) { if (err) {
fillCallbacks(err); fillCallbacks(err);
return; return;
@ -115,7 +114,7 @@ var multi_caching = function (caches) {
value: data, value: data,
ttl: ttl ttl: ttl
}; };
set_in_multiple_caches(caches, opts, function (err) { set_in_multiple_caches(caches, opts, function(err) {
if (err) { if (err) {
fillCallbacks(err); fillCallbacks(err);
} else { } else {
@ -127,7 +126,7 @@ var multi_caching = function (caches) {
}); });
}; };
self.set = function (key, value, ttl, cb) { self.set = function(key, value, ttl, cb) {
var opts = { var opts = {
key: key, key: key,
value: value, value: value,
@ -136,12 +135,12 @@ var multi_caching = function (caches) {
set_in_multiple_caches(caches, opts, cb); set_in_multiple_caches(caches, opts, cb);
}; };
self.get = function (key, cb) { self.get = function(key, cb) {
get_from_highest_priority_cache(key, cb); get_from_highest_priority_cache(key, cb);
}; };
self.del = function (key, cb) { self.del = function(key, cb) {
async.forEach(caches, function (cache, async_cb) { async.forEach(caches, function(cache, async_cb) {
cache.store.del(key, async_cb); cache.store.del(key, async_cb);
}, cb); }, cb);
}; };

18
lib/stores/memory.js

@ -1,6 +1,6 @@
var Lru = require("lru-cache"); var Lru = require("lru-cache");
var memory_store = function (args) { var memory_store = function(args) {
args = args || {}; args = args || {};
var self = {}; var self = {};
self.name = 'memory'; self.name = 'memory';
@ -12,17 +12,17 @@ var memory_store = function (args) {
var lru_cache = new Lru(lru_opts); var lru_cache = new Lru(lru_opts);
self.set = function (key, value, ttl, cb) { self.set = function(key, value, ttl, cb) {
lru_cache.set(key, value); lru_cache.set(key, value);
if (cb) { if (cb) {
process.nextTick(cb); process.nextTick(cb);
} }
}; };
self.get = function (key, cb) { self.get = function(key, cb) {
var value = lru_cache.get(key); var value = lru_cache.get(key);
if (cb) { if (cb) {
process.nextTick(function () { process.nextTick(function() {
cb(null, value); cb(null, value);
}); });
} else { } else {
@ -30,24 +30,24 @@ var memory_store = function (args) {
} }
}; };
self.del = function (key, cb) { self.del = function(key, cb) {
lru_cache.del(key); lru_cache.del(key);
if (cb) { if (cb) {
process.nextTick(cb); process.nextTick(cb);
} }
}; };
self.reset = function (cb) { self.reset = function(cb) {
lru_cache.reset(); lru_cache.reset();
if (cb) { if (cb) {
process.nextTick(cb); process.nextTick(cb);
} }
}; };
self.keys = function (cb) { self.keys = function(cb) {
var keys = lru_cache.keys(); var keys = lru_cache.keys();
if (cb) { if (cb) {
process.nextTick(function () { process.nextTick(function() {
cb(null, keys); cb(null, keys);
}); });
} else { } else {
@ -59,7 +59,7 @@ var memory_store = function (args) {
}; };
var methods = { var methods = {
create: function (args) { create: function(args) {
return memory_store(args); return memory_store(args);
} }
}; };

4
package.json

@ -1,6 +1,6 @@
{ {
"name": "cache-manager", "name": "cache-manager",
"version": "0.15.0", "version": "0.16.0",
"description": "Cache module for Node.js", "description": "Cache module for Node.js",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@ -26,7 +26,7 @@
"devDependencies": { "devDependencies": {
"coveralls": "^2.3.0", "coveralls": "^2.3.0",
"istanbul": "^0.2.11", "istanbul": "^0.2.11",
"jscs": "^1.7.1", "jscs": "^1.9.0",
"jshint": "^2.5.4", "jshint": "^2.5.4",
"mocha": "^1.20.1", "mocha": "^1.20.1",
"optimist": "^0.6.1", "optimist": "^0.6.1",

278
test/caching.unit.js

@ -9,49 +9,49 @@ var caching = require('../index').caching;
var memory_store = require('../lib/stores/memory'); var memory_store = require('../lib/stores/memory');
var methods = { var methods = {
get_widget: function (name, cb) { get_widget: function(name, cb) {
cb(null, {name: name}); cb(null, {name: name});
} }
}; };
describe("caching", function () { describe("caching", function() {
var cache; var cache;
var key; var key;
var ttl = 1; var ttl = 1;
var name; var name;
var value; var value;
describe("get() and set()", function () { describe("get() and set()", function() {
['memory'].forEach(function (store) { ['memory'].forEach(function(store) {
context("using " + store + " store", function () { context("using " + store + " store", function() {
beforeEach(function () { beforeEach(function() {
cache = caching({store: store}); cache = caching({store: store});
key = support.random.string(20); key = support.random.string(20);
value = support.random.string(); value = support.random.string();
}); });
it("lets us set and get data in cache", function (done) { it("lets us set and get data in cache", function(done) {
cache.set(key, value, ttl, function (err) { cache.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
done(); done();
}); });
}); });
}); });
it("lets us set and get data without a callback", function (done) { it("lets us set and get data without a callback", function(done) {
cache.set(key, value, ttl); cache.set(key, value, ttl);
setTimeout(function () { setTimeout(function() {
var result = cache.get(key); var result = cache.get(key);
assert.equal(result, value); assert.equal(result, value);
done(); done();
}, 20); }, 20);
}); });
it("lets us set and get data without a ttl or callback", function (done) { it("lets us set and get data without a ttl or callback", function(done) {
cache.set(key, value); cache.set(key, value);
setTimeout(function () { setTimeout(function() {
var result = cache.get(key); var result = cache.get(key);
assert.equal(result, value); assert.equal(result, value);
done(); done();
@ -61,27 +61,27 @@ describe("caching", function () {
}); });
}); });
describe("del()", function () { describe("del()", function() {
['memory'].forEach(function (store) { ['memory'].forEach(function(store) {
context("using " + store + " store", function () { context("using " + store + " store", function() {
beforeEach(function (done) { beforeEach(function(done) {
cache = caching({store: store}); cache = caching({store: store});
key = support.random.string(20); key = support.random.string(20);
value = support.random.string(); value = support.random.string();
cache.set(key, value, ttl, function (err) { cache.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
done(); done();
}); });
}); });
it("deletes data from cache", function (done) { it("deletes data from cache", function(done) {
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
cache.del(key, function (err) { cache.del(key, function(err) {
check_err(err); check_err(err);
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.ok(!result); assert.ok(!result);
done(); done();
}); });
@ -89,14 +89,14 @@ describe("caching", function () {
}); });
}); });
it("lets us delete data without a callback", function (done) { it("lets us delete data without a callback", function(done) {
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
cache.del(key); cache.del(key);
setTimeout(function () { setTimeout(function() {
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.ok(!result); assert.ok(!result);
done(); done();
}); });
@ -107,15 +107,15 @@ describe("caching", function () {
}); });
}); });
describe("reset()", function () { describe("reset()", function() {
var key2; var key2;
var value2; var value2;
beforeEach(function (done) { beforeEach(function(done) {
cache = caching({store: 'memory'}); cache = caching({store: 'memory'});
key = support.random.string(20); key = support.random.string(20);
value = support.random.string(); value = support.random.string();
cache.set(key, value, ttl, function (err) { cache.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
key2 = support.random.string(20); key2 = support.random.string(20);
@ -125,14 +125,14 @@ describe("caching", function () {
}); });
}); });
it("clears the cache", function (done) { it("clears the cache", function(done) {
cache.reset(function (err) { cache.reset(function(err) {
check_err(err); check_err(err);
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.ok(!result); assert.ok(!result);
cache.get(key2, function (err, result) { cache.get(key2, function(err, result) {
assert.ok(!result); assert.ok(!result);
done(); done();
}); });
@ -140,13 +140,13 @@ describe("caching", function () {
}); });
}); });
it("lets us clear the cache without a callback (memory store only)", function (done) { it("lets us clear the cache without a callback (memory store only)", function(done) {
cache.reset(); cache.reset();
setTimeout(function () { setTimeout(function() {
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.ok(!result); assert.ok(!result);
cache.get(key2, function (err, result) { cache.get(key2, function(err, result) {
assert.ok(!result); assert.ok(!result);
done(); done();
}); });
@ -154,33 +154,33 @@ describe("caching", function () {
}, 10); }, 10);
}); });
context("when store has no del() method", function () { context("when store has no del() method", function() {
var fake_store; var fake_store;
beforeEach(function () { beforeEach(function() {
fake_store = { fake_store = {
get: function () {}, get: function() {},
set: function () {}, set: function() {},
}; };
}); });
it("it doesn't throw an error", function () { it("it doesn't throw an error", function() {
assert.doesNotThrow(function () { assert.doesNotThrow(function() {
caching({store: fake_store}); caching({store: fake_store});
}); });
}); });
}); });
}); });
describe("setex()", function () { describe("setex()", function() {
var fake_store; var fake_store;
beforeEach(function () { beforeEach(function() {
fake_store = { fake_store = {
get: function () {}, get: function() {},
set: function () {}, set: function() {},
del: function () {}, del: function() {},
setex: function () {} setex: function() {}
}; };
sinon.stub(fake_store, 'setex'); sinon.stub(fake_store, 'setex');
@ -188,17 +188,17 @@ describe("caching", function () {
cache = caching({store: fake_store}); cache = caching({store: fake_store});
}); });
it("passes the params to the underlying store's setex() method", function () { it("passes the params to the underlying store's setex() method", function() {
cache.setex('foo', 'bar', 'blah'); cache.setex('foo', 'bar', 'blah');
assert.ok(fake_store.setex.calledWith('foo', 'bar', 'blah')); assert.ok(fake_store.setex.calledWith('foo', 'bar', 'blah'));
}); });
}); });
describe("keys()", function () { describe("keys()", function() {
var key_count; var key_count;
var saved_keys = []; var saved_keys = [];
beforeEach(function (done) { beforeEach(function(done) {
key_count = 10; key_count = 10;
var processed = 0; var processed = 0;
@ -208,7 +208,7 @@ describe("caching", function () {
return processed === key_count; return processed === key_count;
} }
async.until(is_done, function (cb) { async.until(is_done, function(cb) {
processed += 1; processed += 1;
key = support.random.string(20); key = support.random.string(20);
saved_keys.push(key); saved_keys.push(key);
@ -217,25 +217,25 @@ describe("caching", function () {
}, done); }, done);
}); });
it("calls back with all keys in cache", function (done) { it("calls back with all keys in cache", function(done) {
cache.keys(function (err, keys) { cache.keys(function(err, keys) {
check_err(err); check_err(err);
assert.deepEqual(keys.sort, saved_keys.sort); assert.deepEqual(keys.sort, saved_keys.sort);
done(); done();
}); });
}); });
it("lets us get the keys without a callback (memory store only)", function () { it("lets us get the keys without a callback (memory store only)", function() {
var keys = cache.keys(); var keys = cache.keys();
assert.deepEqual(keys.sort, saved_keys.sort); assert.deepEqual(keys.sort, saved_keys.sort);
}); });
}); });
describe("wrap()", function () { describe("wrap()", function() {
describe("using memory (lru-cache) store", function () { describe("using memory (lru-cache) store", function() {
var memory_store_stub; var memory_store_stub;
beforeEach(function () { beforeEach(function() {
ttl = 0.1; ttl = 0.1;
memory_store_stub = memory_store.create({ttl: ttl}); memory_store_stub = memory_store.create({ttl: ttl});
@ -246,23 +246,23 @@ describe("caching", function () {
name = support.random.string(); name = support.random.string();
}); });
afterEach(function () { afterEach(function() {
memory_store.create.restore(); memory_store.create.restore();
}); });
context("calls back with the result of the wrapped function", function () { context("calls back with the result of the wrapped function", function() {
beforeEach(function () { beforeEach(function() {
sinon.spy(memory_store_stub, 'set'); sinon.spy(memory_store_stub, 'set');
}); });
afterEach(function () { afterEach(function() {
memory_store_stub.set.restore(); memory_store_stub.set.restore();
}); });
it("when a ttl is passed in", function (done) { it("when a ttl is passed in", function(done) {
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, ttl, function (err, widget) { }, ttl, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_store_stub.set, key, {name: name}, ttl); sinon.assert.calledWith(memory_store_stub.set, key, {name: name}, ttl);
@ -270,10 +270,10 @@ describe("caching", function () {
}); });
}); });
it("when a ttl is not passed in", function (done) { it("when a ttl is not passed in", function(done) {
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_store_stub.set, key, {name: name}, undefined); sinon.assert.calledWith(memory_store_stub.set, key, {name: name}, undefined);
@ -282,19 +282,19 @@ describe("caching", function () {
}); });
}); });
context("when result is already cached", function () { context("when result is already cached", function() {
function get_cached_widget(name, cb) { function get_cached_widget(name, cb) {
cache.wrap(key, function (cache_cb) { cache.wrap(key, function(cache_cb) {
methods.get_widget(name, cache_cb); methods.get_widget(name, cache_cb);
}, ttl, cb); }, ttl, cb);
} }
beforeEach(function (done) { beforeEach(function(done) {
get_cached_widget(name, function (err, widget) { get_cached_widget(name, function(err, widget) {
check_err(err); check_err(err);
assert.ok(widget); assert.ok(widget);
memory_store_stub.get(key, function (err, result) { memory_store_stub.get(key, function(err, result) {
check_err(err); check_err(err);
assert.ok(result); assert.ok(result);
@ -305,19 +305,19 @@ describe("caching", function () {
}); });
}); });
afterEach(function () { afterEach(function() {
memory_store_stub.get.restore(); memory_store_stub.get.restore();
}); });
it("retrieves data from cache", function (done) { it("retrieves data from cache", function(done) {
var func_called = false; var func_called = false;
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, function (err, result) { methods.get_widget(name, function(err, result) {
func_called = true; func_called = true;
cb(err, result); cb(err, result);
}); });
}, ttl, function (err, widget) { }, ttl, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
assert.ok(memory_store_stub.get.calledWith(key)); assert.ok(memory_store_stub.get.calledWith(key));
@ -327,26 +327,26 @@ describe("caching", function () {
}); });
}); });
it("expires cached result after ttl seconds", function (done) { it("expires cached result after ttl seconds", function(done) {
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, ttl, function (err, widget) { }, ttl, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
memory_store_stub.get(key, function (err, result) { memory_store_stub.get(key, function(err, result) {
check_err(err); check_err(err);
assert.ok(result); assert.ok(result);
var func_called = false; var func_called = false;
setTimeout(function () { setTimeout(function() {
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, function (err, result) { methods.get_widget(name, function(err, result) {
func_called = true; func_called = true;
cb(err, result); cb(err, result);
}); });
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.ok(func_called); assert.ok(func_called);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
@ -357,35 +357,35 @@ describe("caching", function () {
}); });
}); });
context("when an error is thrown in the work function", function () { context("when an error is thrown in the work function", function() {
var fake_error; var fake_error;
beforeEach(function() { beforeEach(function() {
fake_error = new Error(support.random.string()); fake_error = new Error(support.random.string());
}); });
it("bubbles up that error", function (done) { it("bubbles up that error", function(done) {
cache.wrap(key, function () { cache.wrap(key, function() {
throw fake_error; throw fake_error;
}, ttl, function (err) { }, ttl, function(err) {
assert.equal(err, fake_error); assert.equal(err, fake_error);
done(); done();
}); });
}); });
}); });
context("when store.get() calls back with an error", function () { context("when store.get() calls back with an error", function() {
context("and ignoreCacheErrors is not set (default is false)", function () { context("and ignoreCacheErrors is not set (default is false)", function() {
it("bubbles up that error", function (done) { it("bubbles up that error", function(done) {
var fake_error = new Error(support.random.string()); var fake_error = new Error(support.random.string());
sinon.stub(memory_store_stub, 'get', function (key, cb) { sinon.stub(memory_store_stub, 'get', function(key, cb) {
cb(fake_error); cb(fake_error);
}); });
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, ttl, function (err) { }, ttl, function(err) {
assert.equal(err, fake_error); assert.equal(err, fake_error);
memory_store_stub.get.restore(); memory_store_stub.get.restore();
done(); done();
@ -393,19 +393,19 @@ describe("caching", function () {
}); });
}); });
context("and ignoreCacheErrors is set to true", function () { context("and ignoreCacheErrors is set to true", function() {
it("does not bubble up that error", function (done) { it("does not bubble up that error", function(done) {
cache = caching({store: 'memory', ttl: ttl, ignoreCacheErrors: true}); cache = caching({store: 'memory', ttl: ttl, ignoreCacheErrors: true});
var fake_error = new Error(support.random.string()); var fake_error = new Error(support.random.string());
sinon.stub(memory_store_stub, 'get', function (key, cb) { sinon.stub(memory_store_stub, 'get', function(key, cb) {
cb(fake_error); cb(fake_error);
}); });
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, ttl, function (err) { }, ttl, function(err) {
assert.equal(err, null); assert.equal(err, null);
memory_store_stub.get.restore(); memory_store_stub.get.restore();
done(); done();
@ -414,18 +414,18 @@ describe("caching", function () {
}); });
}); });
context("when store.set() calls back with an error", function () { context("when store.set() calls back with an error", function() {
context("and ignoreCacheErrors is not set", function () { context("and ignoreCacheErrors is not set", function() {
it("bubbles up that error", function (done) { it("bubbles up that error", function(done) {
var fake_error = new Error(support.random.string()); var fake_error = new Error(support.random.string());
sinon.stub(memory_store_stub, 'set', function (key, val, ttl, cb) { sinon.stub(memory_store_stub, 'set', function(key, val, ttl, cb) {
cb(fake_error); cb(fake_error);
}); });
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, ttl, function (err) { }, ttl, function(err) {
assert.equal(err, fake_error); assert.equal(err, fake_error);
memory_store_stub.set.restore(); memory_store_stub.set.restore();
done(); done();
@ -433,18 +433,18 @@ describe("caching", function () {
}); });
}); });
context("and ignoreCacheErrors is set to true", function () { context("and ignoreCacheErrors is set to true", function() {
it("does not bubbles up that error", function (done) { it("does not bubbles up that error", function(done) {
cache = caching({store: 'memory', ttl: ttl, ignoreCacheErrors: true}); cache = caching({store: 'memory', ttl: ttl, ignoreCacheErrors: true});
var fake_error = new Error(support.random.string()); var fake_error = new Error(support.random.string());
sinon.stub(memory_store_stub, 'set', function (key, val, ttl, cb) { sinon.stub(memory_store_stub, 'set', function(key, val, ttl, cb) {
cb(fake_error); cb(fake_error);
}); });
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, ttl, function (err) { }, ttl, function(err) {
assert.equal(err, null); assert.equal(err, null);
memory_store_stub.set.restore(); memory_store_stub.set.restore();
done(); done();
@ -453,16 +453,16 @@ describe("caching", function () {
}); });
}); });
context("when wrapped function calls back with an error", function () { context("when wrapped function calls back with an error", function() {
it("calls back with that error", function (done) { it("calls back with that error", function(done) {
var fake_error = new Error(support.random.string()); var fake_error = new Error(support.random.string());
sinon.stub(methods, 'get_widget', function (name, cb) { sinon.stub(methods, 'get_widget', function(name, cb) {
cb(fake_error, {name: name}); cb(fake_error, {name: name});
}); });
cache.wrap(key, function (cb) { cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, ttl, function (err, widget) { }, ttl, function(err, widget) {
methods.get_widget.restore(); methods.get_widget.restore();
assert.equal(err, fake_error); assert.equal(err, fake_error);
assert.ok(!widget); assert.ok(!widget);
@ -472,38 +472,38 @@ describe("caching", function () {
}); });
}); });
describe("when called multiple times in parallel with same key", function () { describe("when called multiple times in parallel with same key", function() {
var construct; var construct;
beforeEach(function () { beforeEach(function() {
cache = caching({ cache = caching({
store: 'memory', store: 'memory',
max: 50, max: 50,
ttl: 5 * 60 ttl: 5 * 60
}); });
construct = sinon.spy(function (val, cb) { construct = sinon.spy(function(val, cb) {
var timeout = support.random.number(100); var timeout = support.random.number(100);
setTimeout(function () { setTimeout(function() {
cb(null, 'value'); cb(null, 'value');
}, timeout); }, timeout);
}); });
}); });
it("calls the wrapped function once", function (done) { it("calls the wrapped function once", function(done) {
var values = []; var values = [];
for (var i = 0; i < 2; i++) { for (var i = 0; i < 2; i++) {
values.push(i); values.push(i);
} }
async.each(values, function (val, async_cb) { async.each(values, function(val, async_cb) {
cache.wrap('key', function (cb) { cache.wrap('key', function(cb) {
construct(val, cb); construct(val, cb);
}, ttl, function (err, result) { }, ttl, function(err, result) {
assert.equal(result, 'value'); assert.equal(result, 'value');
async_cb(err); async_cb(err);
}); });
}, function (err) { }, function(err) {
check_err(err); check_err(err);
assert.equal(construct.callCount, 1); assert.equal(construct.callCount, 1);
done(); done();
@ -512,44 +512,44 @@ describe("caching", function () {
}); });
}); });
describe("instantiating with no store passed in", function () { describe("instantiating with no store passed in", function() {
it("defaults to 'memory' store", function () { it("defaults to 'memory' store", function() {
var cache = caching(); var cache = caching();
assert.equal(cache.store.name, 'memory'); assert.equal(cache.store.name, 'memory');
}); });
}); });
describe("instantiating with custom store", function () { describe("instantiating with custom store", function() {
it("allows us to pass in our own store object", function (done) { it("allows us to pass in our own store object", function(done) {
var store = memory_store.create({ttl: ttl}); var store = memory_store.create({ttl: ttl});
cache = caching({store: store}); cache = caching({store: store});
cache.set(key, value, ttl, function (err) { cache.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
done(); done();
}); });
}); });
}); });
it("allows us to pass in a path to our own store", function (done) { it("allows us to pass in a path to our own store", function(done) {
var store_path = '../lib/stores/memory'; var store_path = '../lib/stores/memory';
cache = caching({store: store_path}); cache = caching({store: store_path});
cache.set(key, value, ttl, function (err) { cache.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
done(); done();
}); });
}); });
}); });
it("allows us to pass in a module (uninstantiated)", function (done) { it("allows us to pass in a module (uninstantiated)", function(done) {
var store = memory_store; var store = memory_store;
cache = caching({store: store}); cache = caching({store: store});
cache.set(key, value, ttl, function (err) { cache.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
done(); done();
}); });

310
test/multi_caching.unit.js

@ -8,12 +8,12 @@ var multi_caching = require('../index').multi_caching;
var memory_store = require('../lib/stores/memory'); var memory_store = require('../lib/stores/memory');
var methods = { var methods = {
get_widget: function (name, cb) { get_widget: function(name, cb) {
cb(null, {name: name}); cb(null, {name: name});
} }
}; };
describe("multi_caching", function () { describe("multi_caching", function() {
var memory_cache; var memory_cache;
var memory_cache2; var memory_cache2;
var memory_cache3; var memory_cache3;
@ -23,7 +23,7 @@ describe("multi_caching", function () {
var name; var name;
var ttl = 5; var ttl = 5;
beforeEach(function () { beforeEach(function() {
memory_ttl = 0.1; memory_ttl = 0.1;
memory_cache = caching({store: 'memory', ttl: memory_ttl}); memory_cache = caching({store: 'memory', ttl: memory_ttl});
@ -34,27 +34,27 @@ describe("multi_caching", function () {
name = support.random.string(); name = support.random.string();
}); });
describe("get(), set(), del()", function () { describe("get(), set(), del()", function() {
var value; var value;
beforeEach(function () { beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache2, memory_cache3]); multi_cache = multi_caching([memory_cache, memory_cache2, memory_cache3]);
key = support.random.string(20); key = support.random.string(20);
value = support.random.string(); value = support.random.string();
}); });
describe("set()", function () { describe("set()", function() {
it("lets us set data in all caches", function (done) { it("lets us set data in all caches", function(done) {
multi_cache.set(key, value, ttl, function (err) { multi_cache.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
memory_cache2.get(key, function (err, result) { memory_cache2.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, value); assert.equal(result, value);
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, value); assert.equal(result, value);
done(); done();
@ -64,19 +64,19 @@ describe("multi_caching", function () {
}); });
}); });
it("lets us set data without a callback", function (done) { it("lets us set data without a callback", function(done) {
multi_cache.set(key, value, ttl); multi_cache.set(key, value, ttl);
setTimeout(function () { setTimeout(function() {
multi_cache.get(key, function (err, result) { multi_cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
memory_cache2.get(key, function (err, result) { memory_cache2.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, value); assert.equal(result, value);
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, value); assert.equal(result, value);
done(); done();
@ -87,19 +87,19 @@ describe("multi_caching", function () {
}, 20); }, 20);
}); });
it("lets us set data without a ttl or callback", function (done) { it("lets us set data without a ttl or callback", function(done) {
multi_cache.set(key, value); multi_cache.set(key, value);
setTimeout(function () { setTimeout(function() {
multi_cache.get(key, function (err, result) { multi_cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
memory_cache2.get(key, function (err, result) { memory_cache2.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, value); assert.equal(result, value);
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, value); assert.equal(result, value);
done(); done();
@ -111,12 +111,12 @@ describe("multi_caching", function () {
}); });
}); });
describe("get()", function () { describe("get()", function() {
it("gets data from first cache that has it", function (done) { it("gets data from first cache that has it", function(done) {
memory_cache3.set(key, value, ttl, function (err) { memory_cache3.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.get(key, function (err, result) { multi_cache.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, value); assert.equal(result, value);
done(); done();
@ -125,22 +125,22 @@ describe("multi_caching", function () {
}); });
}); });
describe("del()", function () { describe("del()", function() {
it("lets us delete data in all caches", function (done) { it("lets us delete data in all caches", function(done) {
multi_cache.set(key, value, ttl, function (err) { multi_cache.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.del(key, function (err) { multi_cache.del(key, function(err) {
check_err(err); check_err(err);
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
assert.ok(!result); assert.ok(!result);
memory_cache2.get(key, function (err, result) { memory_cache2.get(key, function(err, result) {
check_err(err); check_err(err);
assert.ok(!result); assert.ok(!result);
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.ok(!result); assert.ok(!result);
done(); done();
@ -151,21 +151,21 @@ describe("multi_caching", function () {
}); });
}); });
it("lets us delete data without a callback", function (done) { it("lets us delete data without a callback", function(done) {
multi_cache.set(key, value, ttl, function (err) { multi_cache.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.del(key); multi_cache.del(key);
setTimeout(function () { setTimeout(function() {
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
assert.ok(!result); assert.ok(!result);
memory_cache2.get(key, function (err, result) { memory_cache2.get(key, function(err, result) {
check_err(err); check_err(err);
assert.ok(!result); assert.ok(!result);
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.ok(!result); assert.ok(!result);
done(); done();
@ -178,22 +178,22 @@ describe("multi_caching", function () {
}); });
}); });
describe("get_and_pass_up()", function () { describe("get_and_pass_up()", function() {
var value; var value;
var key; var key;
describe("using a single cache store", function () { describe("using a single cache store", function() {
beforeEach(function () { beforeEach(function() {
multi_cache = multi_caching([memory_cache3]); multi_cache = multi_caching([memory_cache3]);
key = support.random.string(20); key = support.random.string(20);
value = support.random.string(); value = support.random.string();
}); });
it("gets data from first cache that has it", function (done) { it("gets data from first cache that has it", function(done) {
memory_cache3.set(key, value, ttl, function (err) { memory_cache3.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.get_and_pass_up(key, function (err, result) { multi_cache.get_and_pass_up(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, value); assert.equal(result, value);
done(); done();
@ -211,7 +211,7 @@ describe("multi_caching", function () {
sinon.spy(memory_cache2, 'set'); sinon.spy(memory_cache2, 'set');
sinon.spy(memory_cache3, 'set'); sinon.spy(memory_cache3, 'set');
multi_cache.get_and_pass_up(key, function (err, result) { multi_cache.get_and_pass_up(key, function(err, result) {
check_err(err); check_err(err);
response = result; response = result;
done(); done();
@ -229,7 +229,7 @@ describe("multi_caching", function () {
}); });
it("does not set anything in caches", function(done) { it("does not set anything in caches", function(done) {
process.nextTick(function () { process.nextTick(function() {
assert.ok(memory_cache.set.notCalled); assert.ok(memory_cache.set.notCalled);
assert.ok(memory_cache2.set.notCalled); assert.ok(memory_cache2.set.notCalled);
assert.ok(memory_cache3.set.notCalled); assert.ok(memory_cache3.set.notCalled);
@ -238,23 +238,23 @@ describe("multi_caching", function () {
}); });
}); });
describe("using multi cache store", function () { describe("using multi cache store", function() {
beforeEach(function () { beforeEach(function() {
multi_cache = multi_caching([memory_cache,memory_cache2,memory_cache3]); multi_cache = multi_caching([memory_cache, memory_cache2, memory_cache3]);
key = support.random.string(20); key = support.random.string(20);
value = support.random.string(); value = support.random.string();
}); });
it("checks to see if higher levels have item", function (done) { it("checks to see if higher levels have item", function(done) {
memory_cache3.set(key, value, ttl, function (err) { memory_cache3.set(key, value, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.get_and_pass_up(key, function (err, result) { multi_cache.get_and_pass_up(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, value); assert.equal(result, value);
process.nextTick(function() { process.nextTick(function() {
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
assert.equal(result, value); assert.equal(result, value);
check_err(err); check_err(err);
done(); done();
@ -266,25 +266,25 @@ describe("multi_caching", function () {
}); });
}); });
describe("wrap()", function () { describe("wrap()", function() {
describe("using a single cache store", function () { describe("using a single cache store", function() {
beforeEach(function () { beforeEach(function() {
multi_cache = multi_caching([memory_cache3]); multi_cache = multi_caching([memory_cache3]);
}); });
context("calls back with the result of a function", function () { context("calls back with the result of a function", function() {
beforeEach(function () { beforeEach(function() {
sinon.spy(memory_cache3.store, 'set'); sinon.spy(memory_cache3.store, 'set');
}); });
afterEach(function () { afterEach(function() {
memory_cache3.store.set.restore(); memory_cache3.store.set.restore();
}); });
it('when a ttl is passed in', function (done) { it('when a ttl is passed in', function(done) {
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, ttl, function (err, widget) { }, ttl, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_cache3.store.set, key, {name: name}, ttl); sinon.assert.calledWith(memory_cache3.store.set, key, {name: name}, ttl);
@ -292,10 +292,10 @@ describe("multi_caching", function () {
}); });
}); });
it('when a ttl is not passed in', function (done) { it('when a ttl is not passed in', function(done) {
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
sinon.assert.calledWith(memory_cache3.store.set, key, {name: name}); sinon.assert.calledWith(memory_cache3.store.set, key, {name: name});
@ -304,16 +304,16 @@ describe("multi_caching", function () {
}); });
}); });
context("when wrapped function calls back with an error", function () { context("when wrapped function calls back with an error", function() {
it("calls back with that error", function (done) { it("calls back with that error", function(done) {
var fake_error = new Error(support.random.string()); var fake_error = new Error(support.random.string());
sinon.stub(methods, 'get_widget', function (name, cb) { sinon.stub(methods, 'get_widget', function(name, cb) {
cb(fake_error, {name: name}); cb(fake_error, {name: name});
}); });
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
methods.get_widget.restore(); methods.get_widget.restore();
assert.equal(err, fake_error); assert.equal(err, fake_error);
assert.ok(!widget); assert.ok(!widget);
@ -323,33 +323,33 @@ describe("multi_caching", function () {
}); });
}); });
describe("using two cache stores", function () { describe("using two cache stores", function() {
beforeEach(function () { beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache3]); multi_cache = multi_caching([memory_cache, memory_cache3]);
}); });
it("calls back with the result of a function", function (done) { it("calls back with the result of a function", function(done) {
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
done(); done();
}); });
}); });
it("sets value in all caches", function (done) { it("sets value in all caches", function(done) {
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
check_err(err); check_err(err);
assert.deepEqual(result, {name: name}); assert.deepEqual(result, {name: name});
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.deepEqual(result, {name: name}); assert.deepEqual(result, {name: name});
done(); done();
@ -358,18 +358,18 @@ describe("multi_caching", function () {
}); });
}); });
context("when value exists in first store but not second", function () { context("when value exists in first store but not second", function() {
it("returns value from first store, does not set it in second", function (done) { it("returns value from first store, does not set it in second", function(done) {
memory_cache.set(key, {name: name}, ttl, function (err) { memory_cache.set(key, {name: name}, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, null); assert.equal(result, null);
done(); done();
@ -379,18 +379,18 @@ describe("multi_caching", function () {
}); });
}); });
context("when value exists in second store but not first", function () { context("when value exists in second store but not first", function() {
it("returns value from second store, sets it in first store", function (done) { it("returns value from second store, sets it in first store", function(done) {
memory_cache3.set(key, {name: name}, ttl, function (err) { memory_cache3.set(key, {name: name}, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
check_err(err); check_err(err);
assert.deepEqual(result, {name: name}); assert.deepEqual(result, {name: name});
done(); done();
@ -401,37 +401,37 @@ describe("multi_caching", function () {
}); });
}); });
describe("using three cache stores", function () { describe("using three cache stores", function() {
beforeEach(function () { beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache3, memory_cache2]); multi_cache = multi_caching([memory_cache, memory_cache3, memory_cache2]);
}); });
it("calls back with the result of a function", function (done) { it("calls back with the result of a function", function(done) {
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
done(); done();
}); });
}); });
it("sets value in all caches", function (done) { it("sets value in all caches", function(done) {
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
check_err(err); check_err(err);
assert.deepEqual(result, {name: name}); assert.deepEqual(result, {name: name});
memory_cache2.get(key, function (err, result) { memory_cache2.get(key, function(err, result) {
check_err(err); check_err(err);
assert.deepEqual(result, {name: name}); assert.deepEqual(result, {name: name});
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.deepEqual(result, {name: name}); assert.deepEqual(result, {name: name});
done(); done();
@ -441,22 +441,22 @@ describe("multi_caching", function () {
}); });
}); });
context("when value exists in first store only", function () { context("when value exists in first store only", function() {
it("returns value from first store, does not set it in second or third", function (done) { it("returns value from first store, does not set it in second or third", function(done) {
memory_cache.set(key, {name: name}, ttl, function (err) { memory_cache.set(key, {name: name}, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
memory_cache2.get(key, function (err, result) { memory_cache2.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, null); assert.equal(result, null);
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, null); assert.equal(result, null);
done(); done();
@ -467,22 +467,22 @@ describe("multi_caching", function () {
}); });
}); });
context("when value exists in second store only", function () { context("when value exists in second store only", function() {
it("returns value from second store, sets it in first store, does not set third store", function (done) { it("returns value from second store, sets it in first store, does not set third store", function(done) {
memory_cache3.set(key, {name: name}, ttl, function (err) { memory_cache3.set(key, {name: name}, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
check_err(err); check_err(err);
assert.deepEqual(result, {name: name}); assert.deepEqual(result, {name: name});
memory_cache2.get(key, function (err, result) { memory_cache2.get(key, function(err, result) {
check_err(err); check_err(err);
assert.equal(result, null); assert.equal(result, null);
done(); done();
@ -493,22 +493,22 @@ describe("multi_caching", function () {
}); });
}); });
context("when value exists in third store only", function () { context("when value exists in third store only", function() {
it("returns value from third store, sets it in first and second stores", function (done) { it("returns value from third store, sets it in first and second stores", function(done) {
memory_cache2.set(key, {name: name}, ttl, function (err) { memory_cache2.set(key, {name: name}, ttl, function(err) {
check_err(err); check_err(err);
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err, widget) { }, function(err, widget) {
check_err(err); check_err(err);
assert.deepEqual(widget, {name: name}); assert.deepEqual(widget, {name: name});
memory_cache3.get(key, function (err, result) { memory_cache3.get(key, function(err, result) {
check_err(err); check_err(err);
assert.deepEqual(result, {name: name}); assert.deepEqual(result, {name: name});
memory_cache.get(key, function (err, result) { memory_cache.get(key, function(err, result) {
check_err(err); check_err(err);
assert.deepEqual(result, {name: name}); assert.deepEqual(result, {name: name});
@ -521,11 +521,11 @@ describe("multi_caching", function () {
}); });
}); });
context("error handling", function () { context("error handling", function() {
var memory_store_stub; var memory_store_stub;
var ttl; var ttl;
beforeEach(function () { beforeEach(function() {
ttl = 0.1; ttl = 0.1;
memory_store_stub = memory_store.create({ttl: ttl}); memory_store_stub = memory_store.create({ttl: ttl});
sinon.stub(memory_store, 'create').returns(memory_store_stub); sinon.stub(memory_store, 'create').returns(memory_store_stub);
@ -533,38 +533,38 @@ describe("multi_caching", function () {
multi_cache = multi_caching([memory_cache]); multi_cache = multi_caching([memory_cache]);
}); });
afterEach(function () { afterEach(function() {
memory_store.create.restore(); memory_store.create.restore();
}); });
context("when an error is thrown in the work function", function () { context("when an error is thrown in the work function", function() {
var fake_error; var fake_error;
beforeEach(function() { beforeEach(function() {
fake_error = new Error(support.random.string()); fake_error = new Error(support.random.string());
}); });
it("bubbles up that error", function (done) { it("bubbles up that error", function(done) {
multi_cache.wrap(key, function () { multi_cache.wrap(key, function() {
throw fake_error; throw fake_error;
}, ttl, function (err) { }, ttl, function(err) {
assert.equal(err, fake_error); assert.equal(err, fake_error);
done(); done();
}); });
}); });
}); });
context("when store.get() calls back with an error", function () { context("when store.get() calls back with an error", function() {
it("bubbles up that error", function (done) { it("bubbles up that error", function(done) {
var fake_error = new Error(support.random.string()); var fake_error = new Error(support.random.string());
sinon.stub(memory_store_stub, 'get', function (key, cb) { sinon.stub(memory_store_stub, 'get', function(key, cb) {
cb(fake_error); cb(fake_error);
}); });
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err) { }, function(err) {
assert.equal(err, fake_error); assert.equal(err, fake_error);
memory_store_stub.get.restore(); memory_store_stub.get.restore();
done(); done();
@ -572,17 +572,17 @@ describe("multi_caching", function () {
}); });
}); });
context("when store.set() calls back with an error", function () { context("when store.set() calls back with an error", function() {
it("bubbles up that error", function (done) { it("bubbles up that error", function(done) {
var fake_error = new Error(support.random.string()); var fake_error = new Error(support.random.string());
sinon.stub(memory_store_stub, 'set', function (key, val, ttl, cb) { sinon.stub(memory_store_stub, 'set', function(key, val, ttl, cb) {
cb(fake_error); cb(fake_error);
}); });
multi_cache.wrap(key, function (cb) { multi_cache.wrap(key, function(cb) {
methods.get_widget(name, cb); methods.get_widget(name, cb);
}, function (err) { }, function(err) {
assert.equal(err, fake_error); assert.equal(err, fake_error);
memory_store_stub.set.restore(); memory_store_stub.set.restore();
done(); done();
@ -591,34 +591,34 @@ describe("multi_caching", function () {
}); });
}); });
describe("when called multiple times in parallel with same key", function () { describe("when called multiple times in parallel with same key", function() {
var construct; var construct;
beforeEach(function () { beforeEach(function() {
multi_cache = multi_caching([memory_cache, memory_cache3]); multi_cache = multi_caching([memory_cache, memory_cache3]);
construct = sinon.spy(function (val, cb) { construct = sinon.spy(function(val, cb) {
var timeout = support.random.number(100); var timeout = support.random.number(100);
setTimeout(function () { setTimeout(function() {
cb(null, 'value'); cb(null, 'value');
}, timeout); }, timeout);
}); });
}); });
it("calls the wrapped function once", function (done) { it("calls the wrapped function once", function(done) {
var values = []; var values = [];
for (var i = 0; i < 5; i++) { for (var i = 0; i < 5; i++) {
values.push(i); values.push(i);
} }
async.each(values, function (val, async_cb) { async.each(values, function(val, async_cb) {
multi_cache.wrap('key', function (cb) { multi_cache.wrap('key', function(cb) {
construct(val, cb); construct(val, cb);
}, function (err, result) { }, function(err, result) {
assert.equal(result, 'value'); assert.equal(result, 'value');
async_cb(err); async_cb(err);
}); });
}, function (err) { }, function(err) {
check_err(err); check_err(err);
assert.equal(construct.callCount, 1); assert.equal(construct.callCount, 1);
done(); done();
@ -627,9 +627,9 @@ describe("multi_caching", function () {
}); });
}); });
context("when instantiated with a non-Array 'caches' arg", function () { context("when instantiated with a non-Array 'caches' arg", function() {
it("throws an error", function () { it("throws an error", function() {
assert.throws(function () { assert.throws(function() {
multi_caching({foo: 'bar'}); multi_caching({foo: 'bar'});
}, /multi_caching requires an array/); }, /multi_caching requires an array/);
}); });

12
test/run.js

@ -25,7 +25,7 @@ var valid_test_types = ['unit', 'functional', 'acceptance', 'integration'];
var requested_types = argv.types.split(','); var requested_types = argv.types.split(',');
var types_to_use = []; var types_to_use = [];
valid_test_types.forEach(function (valid_test_type) { valid_test_types.forEach(function(valid_test_type) {
if (requested_types.indexOf(valid_test_type) !== -1) { if (requested_types.indexOf(valid_test_type) !== -1) {
types_to_use.push(valid_test_type); types_to_use.push(valid_test_type);
} }
@ -36,7 +36,7 @@ if (argv.help || types_to_use.length === 0) {
process.exit(); process.exit();
} }
var is_valid_file = function (file) { var is_valid_file = function(file) {
if (file.match(/buster/)) { if (file.match(/buster/)) {
return false; return false;
} }
@ -54,10 +54,10 @@ var is_valid_file = function (file) {
}; };
function run(cb) { function run(cb) {
walk_dir('test', is_valid_file, function (err, files) { walk_dir('test', is_valid_file, function(err, files) {
if (err) { return cb(err); } if (err) { return cb(err); }
files.forEach(function (file) { files.forEach(function(file) {
mocha.addFile(file); mocha.addFile(file);
}); });
@ -65,9 +65,9 @@ function run(cb) {
}); });
} }
run(function (err) { run(function(err) {
if (err) { throw err; } if (err) { throw err; }
mocha.run(function (failures) { mocha.run(function(failures) {
process.exit(failures); process.exit(failures);
}); });
}); });

6
test/stores/memory.unit.js

@ -1,9 +1,9 @@
var support = require('../support'); var support = require('../support');
var memory_store = require('../../lib/stores/memory'); var memory_store = require('../../lib/stores/memory');
describe("memory store", function () { describe("memory store", function() {
describe("instantiating", function () { describe("instantiating", function() {
it("lets us pass in no args", function (done) { it("lets us pass in no args", function(done) {
var memory_cache = memory_store.create(); var memory_cache = memory_store.create();
support.test_set_get_del(memory_cache, done); support.test_set_get_del(memory_cache, done);
}); });

30
test/support.js

@ -4,7 +4,7 @@ var assert = require('assert');
var support = { var support = {
random: { random: {
string: function (str_len) { string: function(str_len) {
str_len = str_len || 8; str_len = str_len || 8;
var chars = "abcdefghiklmnopqrstuvwxyz"; var chars = "abcdefghiklmnopqrstuvwxyz";
var random_str = ''; var random_str = '';
@ -15,13 +15,13 @@ var support = {
return random_str; return random_str;
}, },
number: function (max) { number: function(max) {
max = max || 1000; max = max || 1000;
return Math.floor((Math.random() * max)); return Math.floor((Math.random() * max));
} }
}, },
check_err: function (err) { check_err: function(err) {
if (err) { if (err) {
var msg; var msg;
@ -38,36 +38,36 @@ var support = {
} }
}, },
assert_between: function (actual, lower, upper) { assert_between: function(actual, lower, upper) {
assert.ok(actual >= lower, "Expected " + actual + " to be >= " + lower); assert.ok(actual >= lower, "Expected " + actual + " to be >= " + lower);
assert.ok(actual <= upper, "Expected " + actual + " to be <= " + upper); assert.ok(actual <= upper, "Expected " + actual + " to be <= " + upper);
}, },
assert_within: function (actual, expected, delta) { assert_within: function(actual, expected, delta) {
var lower = expected - delta; var lower = expected - delta;
var upper = expected + delta; var upper = expected + delta;
this.assert_between(actual, lower, upper); this.assert_between(actual, lower, upper);
}, },
walk_dir: function (dir, validation_function, cb) { walk_dir: function(dir, validation_function, cb) {
if (arguments.length === 2) { if (arguments.length === 2) {
cb = validation_function; cb = validation_function;
validation_function = null; validation_function = null;
} }
var results = []; var results = [];
fs.readdir(dir, function (err, list) { fs.readdir(dir, function(err, list) {
if (err) { return cb(err); } if (err) { return cb(err); }
var pending = list.length; var pending = list.length;
if (!pending) { return cb(null, results); } if (!pending) { return cb(null, results); }
list.forEach(function (file) { list.forEach(function(file) {
file = dir + '/' + file; file = dir + '/' + file;
fs.stat(file, function (err, stat) { fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) { if (stat && stat.isDirectory()) {
support.walk_dir(file, validation_function, function (err, res) { support.walk_dir(file, validation_function, function(err, res) {
results = results.concat(res); results = results.concat(res);
if (!--pending) { cb(null, results); } if (!--pending) { cb(null, results); }
}); });
@ -87,22 +87,22 @@ var support = {
}); });
}, },
test_set_get_del: function (cache, cb) { test_set_get_del: function(cache, cb) {
var key = 'TEST' + support.random.string(); var key = 'TEST' + support.random.string();
var val = support.random.string(); var val = support.random.string();
var ttl; var ttl;
cache.set(key, val, ttl, function (err) { cache.set(key, val, ttl, function(err) {
if (err) { return cb(err); } if (err) { return cb(err); }
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
if (err) { return cb(err); } if (err) { return cb(err); }
assert.equal(result, val); assert.equal(result, val);
cache.del(key, function (err) { cache.del(key, function(err) {
if (err) { return cb(err); } if (err) { return cb(err); }
cache.get(key, function (err, result) { cache.get(key, function(err, result) {
if (err) { return cb(err); } if (err) { return cb(err); }
assert.ok(!result); assert.ok(!result);
cb(); cb();

Loading…
Cancel
Save