UNPKG

30.3 kBJavaScriptView Raw
1let redis = require("redis");
2let client = redis.createClient();
3let cache = require('../classes/controller-cache');
4let Controller = require('../classes/controller');
5const assert = require('assert');
6Promise = require('bluebird').Promise;
7
8const dbsize = () => new Promise((resolve, reject) =>
9 client.dbsize((err, result) => {
10 if (err) return reject(err);
11 resolve(result);
12 }));
13
14const tick = (time) => new Promise((resolve) => setTimeout(resolve, time || 2));
15const promise = (func) => new Promise(resolve => func(resolve));
16
17beforeEach(done => client.flushdb(done));
18afterEach(done => client.flushdb(done));
19before(done => client.flushdb(done));
20after(done => client.flushdb(done));
21
22describe('ControllerCache Handling various data types', function () {
23
24 it('should take a string', () => {
25 let lru = new cache(client, 'someController', 'Get', {max: 10});
26 return lru.cache.set('/some', 'string content')
27 .then(result => assert.equal(result, 'string content'))
28 .then(() => lru.cache.get('/some'))
29 .then(result => assert.equal(result, 'string content'))
30 })
31
32 it('should take an object', () => {
33 let lru = new cache(client, 'someController', 'Get', {max: 10});
34 return lru.cache.set('/my/url?foo=true', {foo: 'bar'})
35 .then(result => assert.deepEqual(result, {foo: 'bar'}))
36 });
37
38 it('should take an array', () => {
39 let lru = new cache(client, 'someController', 'Get', {max: 10});
40 return lru.cache.set('/my/url', [{foo: 'bar'}])
41 .then(result => assert.deepEqual(result, [{foo: 'bar'}]))
42 .then(() => lru.cache.get('/my/url'))
43 .then(result => assert.deepEqual(result, [{foo: 'bar'}]))
44 })
45
46 it('should take a number (integer)', () => {
47 let lru = new cache(client, 'someController', 'Get', {max: 10});
48 return lru.cache.set('/how-many/things', 4e8)
49 .then(result => assert.equal(result, 4e8))
50 .then(() => lru.cache.get('/how-many/things'))
51 .then(result => assert.equal(result, 4e8))
52 })
53
54 it('should take a number (negative integer)', () => {
55 let lru = new cache(client, 'someController', 'Get', {max: 10});
56 return lru.cache.set('/how-many/things', -49637)
57 .then(result => assert.equal(result, -49637))
58 .then(() => lru.cache.get('/how-many/things'))
59 .then(result => assert.equal(result, -49637))
60 })
61
62 it('should take a number (float)', () => {
63 let lru = new cache(client, 'someController', 'Get', {max: 10});
64 return lru.cache.set('/how-many/things', 4.3427)
65 .then(result => assert.equal(result, 4.3427))
66 .then(() => lru.cache.get('/how-many/things'))
67 .then(result => assert.equal(result, 4.3427))
68 })
69
70 it('should take a number (negative float)', () => {
71 let lru = new cache(client, 'someController', 'Get', {max: 10});
72 return lru.cache.set('/how-many/things', -49637.342787368763587653876538763)
73 .then(result => assert.equal(result, -49637.342787368763587653876538763))
74 .then(() => lru.cache.get('/how-many/things'))
75 .then(result => assert.equal(result, -49637.342787368763587653876538763))
76 })
77
78 it('should take a boolean (true)', () => {
79 let lru = new cache(client, 'someController', 'Get', {max: 10});
80 return lru.cache.set('/lengthy-analysis/result', true)
81 .then(result => assert.equal(result, true))
82 .then(() => lru.cache.get('/lengthy-analysis/result'))
83 .then(result => assert.equal(result, true))
84 })
85
86 it('should take a boolean (false)', () => {
87 let lru = new cache(client, 'someController', 'Get', {max: 10});
88 return lru.cache.set('/lengthy-analysis/result', false)
89 .then(result => assert.equal(result, false))
90 .then(() => lru.cache.get('/lengthy-analysis/result'))
91 .then(result => assert.equal(result, false))
92 })
93
94 it('should take a buffer', () => {
95 let lru = new cache(client, 'someController', 'Get', {max: 10});
96 let bigArray = [];
97 let i = 0;
98
99 for (i; i < 3518; i += 1) {
100 bigArray.push((Math.random() * 10) < 5 ? 0 : 1);
101 }
102
103 let buffer = new Buffer(bigArray);
104 return lru.cache.set('/lengthy-analysis/result', buffer)
105 .then(() => lru.cache.get('/lengthy-analysis/result'))
106 .then(result => assert.deepEqual(buffer, new Buffer(result)))
107 })
108
109});
110
111
112describe('ControllerCache Set and Get methods', () => {
113 it('should save an item in the cache and allow to get it back', () => {
114 const lru = new cache(client, 'UserController').cache;
115
116 return lru.set('key', 'hello')
117 .then((result) => assert.equal(result, 'hello'))
118 .then(() => lru.set('key2', {message: 'goodbye'}))
119 .then(() => Promise.all([lru.get('key'), lru.get('key2')]))
120 .then((results) => {
121 assert.equal(results[0], 'hello');
122 assert.deepEqual(results[1], {message: 'goodbye'});
123 });
124 });
125
126 it('should return null if a key is not found in the cache', () => {
127 const lru = new cache(client, 'UserController').cache;
128
129 return lru.get('key1')
130 .then((result) => assert.equal(result, null));
131 });
132
133 it('should save up to opts.max items in the cache', () => {
134 const lru = new cache(client, 'UserController').cache;
135
136 return Promise.all([
137 lru.set('k1', 'v1'), lru.set('k2', 'v2'), lru.set('k3', 'v3')
138 ])
139 .then(() => lru.get('k1'))
140 .then((r) => assert.equal(r, 'v1'))
141 .then(tick)
142 .then(() => lru.get('k2'))
143 .then((r) => assert.equal(r, 'v2'))
144 .then(tick)
145 .then(() => lru.get('k3'))
146 .then((r) => assert.equal(r, 'v3'))
147 .then(dbsize)
148 .then((r) => assert.equal(r, 4)) // DB size is #items + 1 for the index
149 .then(() => lru.set('k4', 'v4'))
150 .then(() => lru.get('k1'))
151 .then((r) => assert.equal(r, null, 'k1 should have been evicted from the cache'))
152 .then(() => lru.get('k2'))
153 .then((r) => assert.equal(r, 'v2'))
154 .then(() => lru.get('k3')) // set k4, get k1, k2 => k3 out of the cache
155 .then((r) => assert.equal(r, 'v3'))
156 .then(() => lru.get('k4'))
157 .then((r) => assert.equal(r, 'v4'))
158 .then(dbsize)
159 .then((r) => assert.equal(r, 4, 'db size should not have grown'));
160 });
161
162 it('should keep different items in different namespaces', () => {
163 const lru1 = new cache(client, 'first').cache;
164 const lru2 = new cache(client, 'second').cache;
165
166 return lru1.set('k1', 'first cache')
167 .then(() => lru2.set('k1', 'second cache'))
168 .then(() => Promise.all([lru1.get('k1'), lru2.get('k1')]))
169 .then((results) => {
170 assert.equal(results[0], 'first cache');
171 assert.equal(results[1], 'second cache');
172 });
173 });
174
175 it('should keep the last accessed items first', () => {
176 const lru = new cache(client, 'UserController').cache;
177
178 return lru.set('k1', 'v1')
179 .then(() => lru.set('k2', 'v2'))
180 .then(() => lru.set('k3', 'v3'))
181 .then(() => lru.get('k2')) // k2 last
182 .then(tick)
183 .then(() => lru.get('k3')) // k3 second
184 .then(tick)
185 .then(() => lru.get('k1')) // k1 first
186 .then(tick)
187 .then(() => lru.set('k4', 'v4')) // should evict oldest => k2 out
188 .then(() => lru.get('k2'))
189 .then((result) => {
190 assert.equal(result, null);
191 });
192 });
193
194 it('should update value and last accessed score when setting a key again', () => {
195 const lru = new cache(client, 'UserController').cache;
196
197 return lru.set('k1', 'v1')
198 .then(() => lru.set('k2', 'v2'))
199 .then(() => lru.set('k3', 'v3'))
200 .then(() => lru.get('k2'))
201 .then(tick)
202 .then(() => lru.get('k3'))
203 .then(tick)
204 .then(() => lru.get('k1'))
205 .then(tick)
206 .then(() => lru.set('k2', 'v2')) // k2 back to front, k3 is oldest
207 .then(tick)
208 .then(() => lru.set('k4', 'v4')) // k3 out
209 .then(() => lru.get('k3'))
210 .then((result) => {
211 assert.equal(result, null);
212 });
213 });
214
215 it('should not update last accessed score on a different namespace', () => {
216 let lru1 = new cache(client, 'c1', 'get', {max : 2});
217 let lru2 = new cache(client, 'c2', 'get', {max: 2});
218
219 return lru1.cache.set('k1', 'v1')
220 .then(() => lru1.cache.set('k2', 'v2'))
221 .then(() => lru2.cache.set('k1', 'v1'))
222 .then(tick)
223 .then(() => lru2.cache.set('k2', 'v2'))
224 .then(tick)
225 .then(() => lru1.cache.get('k1')) // bumps k1 in first cache
226 .then(tick)
227 .then(() => lru2.cache.set('k3', 'v3')) // should evict k1 in second cache
228 .then(() => lru2.cache.get('k1'))
229 .then((result) => {
230 assert.equal(result, null);
231 });
232 });
233});
234
235describe("ControllerCache LRU set options during runtime (Single Prop)", function () {
236
237 it('should update the max options', function () {
238 let myCache = new cache(client, 'UserController');
239 myCache.setOptions({max: 1}, true);
240 return myCache.cache.set('k1', 'v1')
241 .then(() => myCache.cache.set('k2', 'v2'))
242 .then(() => myCache.cache.get('k1'))
243 .then(tick)
244 .then(() => myCache.cache.get('k1'))
245 .then(result => {
246 assert.equal(result, null);
247 }).then(() => myCache.cache.reset());
248 });
249
250});
251
252describe("ControllerCache LRU set options during runtime (Multiple Props)", function () {
253 it('should update the strategy', function () {
254 let myCache = new cache(client, 'UserController');
255 myCache.setOptions({max: 2, strategy: 'LFU'}, true);
256 return myCache.cache.set('beatles', 'john, paul, george, ringo')
257 .then(() => myCache.cache.get('beatles')) // accessed twice
258 .then(() => myCache.cache.set('zeppelin', 'jimmy, robert, john, bonzo'))
259 .then(() => myCache.cache.set('floyd', 'david, roger, syd, richard, nick')) // cache full, remove least frequently accessed
260 .then(() => myCache.cache.get('zeppelin'))
261 .then(result => {
262 assert.equal(result, null);
263 })
264 });
265
266 it('should update the namespace', function () {
267 let myCache = new cache(client, 'UserController');
268 myCache.setOptions({max: 2, strategy: 'LFU', namespace: 'fooze'}, true);
269 return myCache.cache.set('beatles', 'john, paul, george, ringo')
270 .then(() => myCache.cache.get('beatles')) // accessed twice
271 .then(() => myCache.cache.set('zeppelin', 'jimmy, robert, john, bonzo'))
272 .then(() => myCache.cache.set('floyd', 'david, roger, syd, richard, nick')) // cache full, remove least frequently accessed
273 .then(() => myCache.cache.get('zeppelin'))
274 .then(result => {
275 assert.equal(result, null);
276 assert.equal(myCache.namespace, 'UserController#UNDEFINED-ACTION-fooze');
277 })
278 });
279
280});
281
282describe('ControllerCache getOrSet method', () => {
283 it('should get the value from cache and NOT call the function', () => {
284 const lru = new cache(client, 'someController')
285
286 function fn () {
287 throw Error('should not call');
288 }
289
290 return lru.cache.set('key', 'hello')
291 .then(() => lru.cache.getOrSet('key', fn))
292 .then((result) => assert.equal(result, 'hello'));
293 });
294
295 it('should set key to the return value of the function', () => {
296 const lru = new cache(client, 'someController').cache
297
298 function fn () {
299 return 5;
300 }
301
302 return lru.getOrSet('key', fn)
303 .then((result) => assert.equal(result, 5))
304 .then(() => lru.get('key'))
305 .then((result) => assert.equal(result, 5));
306 });
307
308 it('should set key to the resolved value of the promise returned by the function', () => {
309 const lru = new cache(client, 'someController').cache
310
311 function fn () {
312 return Promise.resolve(5);
313 }
314
315 return lru.getOrSet('key', fn)
316 .then((result) => assert.equal(result, 5))
317 .then(() => lru.get('key'))
318 .then((result) => assert.equal(result, 5));
319 });
320
321 it('should reject if function rejects', () => {
322 const lru = new cache(client, 'someController').cache
323
324 function fn () {
325 return Promise.reject(Error('something went wrong'));
326 }
327
328 return lru.getOrSet('key', fn)
329 .then(() => { throw Error('should not resolve'); })
330 .catch((err) => assert.equal(err.message, 'something went wrong'));
331 });
332
333 it('should reject if function throws', () => {
334 const lru = new cache(client, 'someController').cache
335
336 function fn () {
337 throw Error('something went wrong');
338 }
339
340 return lru.getOrSet('key', fn)
341 .then(() => { throw Error('should not resolve'); })
342 .catch((err) => assert.equal(err.message, 'something went wrong'));
343 });
344
345 it('should update recent-ness when getOrSet a saved value', () => {
346 const lru = new cache(client, 'someController', 'FindOne').cache
347
348 return lru.set('k1', 'v1')
349 .then(() => lru.set('k2', 'v2'))
350 .then(() => lru.set('k3', 'v3'))
351 .then(() => lru.getOrSet('k2')) // k2 last
352 .then(tick)
353 .then(() => lru.getOrSet('k3')) // k3 second
354 .then(tick)
355 .then(() => lru.getOrSet('k1')) // k1 first
356 .then(tick)
357 .then(() => lru.set('k4', 'v4')) // should evict oldest => k2 out
358 .then(() => lru.get('k2'))
359 .then((result) => {
360 assert.equal(result, null);
361 });
362 });
363
364 it('should update recent-ness when getOrSet a missing value', () => {
365 const lru = new cache(client, 'someController').cache
366
367 return lru.getOrSet('k2', () => 2) // k2 last
368 .then(tick)
369 .then(() => lru.getOrSet('k3', () => 3)) // k3 second
370 .then(tick)
371 .then(() => lru.getOrSet('k1', () => 1)) // k1 first
372 .then(tick)
373 .then(() => lru.set('k4', 'v4')) // should evict oldest => k2 out
374 .then(() => lru.get('k2'))
375 .then((result) => {
376 assert.equal(result, null);
377 });
378 });
379});
380
381describe('ControllerCache peek method', () => {
382 it('should return the value without changing the recent-ness score', () => {
383 let lrucache = new cache(client, 'someController', 'Get', {max: 2});
384 const lru = lrucache.cache;
385
386 return lru.set('k1', 'v1')
387 .then(tick)
388 .then(() => lru.set('k2', 'v2'))
389 .then(() => lru.peek('k1'))
390 .then((r) => {
391 assert.equal(r, 'v1');
392 return lru.set('k3', 'v3'); // should evict k1 since last peek doesnt update recentness
393 })
394 .then(() => lru.get('k1'))
395 .then((r) => assert.equal(r, null));
396 });
397});
398
399describe('ControllerCache del method', () => {
400 it('should remove the key from the cache and preserve the rest', () => {
401 let lrucache = new cache(client, 'someController', 'Get', {max: 2});
402 const lru = lrucache.cache;
403
404 return lru.set('k1', 'v1')
405 .then(() => lru.set('k2', 'v2'))
406 .then(() => lru.del('k1'))
407 .then(() => lru.get('k1'))
408 .then((r) => assert.equal(r, null))
409 .then(() => lru.get('k2'))
410 .then((r) => assert.equal(r, 'v2'));
411 });
412
413 it('should not remove from other namespaces', () => {
414 let lrucache = new cache(client, 'someController', 'Foo', {max: 2});
415 const lru = lrucache.cache;
416
417 let cache2 = new cache(client, 'c2');
418 cache2.setOptions({max: 2});
419 const lru2 = cache2.cache;
420
421 return lru.set('k1', 'v1')
422 .then(() => lru2.set('k1', 'v1'))
423 .then(() => lru.del('k1'))
424 .then(() => lru.get('k1'))
425 .then((r) => assert.equal(r, null))
426 .then(() => lru2.get('k1'))
427 .then((r) => assert.equal(r, 'v1'));
428 });
429});
430
431describe('ControllerCache reset method', () => {
432 it('should remove all keys from the cache', () => {
433 let lrucache = new cache(client, 'someController', 'foo', {max: 2});
434 const lru = lrucache.cache;
435
436 return lru.set('k1', 'v1')
437 .then(() => lru.set('k2', 'v2'))
438 .then(() => lru.reset())
439 .then(() => lru.get('k1'))
440 .then((r) => assert.equal(r, null))
441 .then(() => lru.get('k2'))
442 .then((r) => assert.equal(r, null));
443 });
444
445 it('should not empty other namespaces', () => {
446 let lrucache = new cache(client, 'someController', 'getSomeList', {max: 2});
447 const lru = lrucache.cache;
448
449 let cache2 = new cache(client, 'c2');
450 cache2.setOptions({max: 2}, true);
451 const lru2 = cache2.cache;
452
453 return lru.set('k1', 'v1')
454 .then(() => lru2.set('k1', 'v1'))
455 .then(() => lru.reset())
456 .then(() => lru.get('k1'))
457 .then((r) => assert.equal(r, null))
458 .then(() => lru2.get('k1'))
459 .then((r) => assert.equal(r, 'v1'));
460 });
461});
462
463describe('ControllerCache has method', () => {
464 it('should return true if the item is in the cache without affecting the recent-ness', () => {
465 let lrucache = new cache(client, 'someController');
466 lrucache.setOptions({max: 2}, true);
467 const lru = lrucache.cache;
468
469 return lru.set('k1', 'v1')
470 .then(tick)
471 .then(() => lru.set('k2', 'v2'))
472 .then(() => lru.has('k1'))
473 .then((r) => {
474 assert.equal(r, true);
475 return lru.set('k3', 'v3'); // should evict k1 since last peek doesnt update recentness
476 })
477 .then(() => lru.get('k1'))
478 .then((r) => assert.equal(r, null));
479 });
480
481 it('should return false if the item is not in the cache', () => {
482 let lrucache = new cache(client);
483 lrucache.setOptions({max: 2}, true);
484 const lru = lrucache.cache;
485
486 return lru.set('k1', 'v1')
487 .then(() => lru.set('k2', 'v2'))
488 .then(() => lru.has('k3'))
489 .then((r) => assert.equal(r, false));
490 });
491});
492
493describe('ControllerCache keys method', () => {
494 it('should return all keys inside the cache', () => {
495 let lrucache = new cache(client, 'someController');
496 lrucache.setOptions({max: 2}, true);
497 const lru = lrucache.cache;
498
499 return lru.set('k1', 'v1')
500 .then(tick)
501 .then(() => lru.set('k2', 'v2'))
502 .then(() => lru.keys())
503 .then((r) => assert.deepEqual(r, ['k2', 'k1']));
504 });
505
506 it('should not return more keys if size exceeded before', () => {
507 let lrucache = new cache(client, '22', 'aa');
508 lrucache.setOptions({max: 2}, true);
509 const lru = lrucache.cache;
510
511 return lru.set('k1', 'v1')
512 .then(tick)
513 .then(() => lru.set('k2', 'v2'))
514 .then(tick)
515 .then(() => lru.set('k3', 'v3'))
516 .then(() => lru.keys())
517 .then((r) => assert.deepEqual(r, ['k3', 'k2']));
518 });
519});
520
521describe('ControllerCache values method', () => {
522 it('should return all values inside the cache', () => {
523 let lrucache = new cache(client, 'someController');
524 lrucache.setOptions({max: 2}, true);
525 const lru = lrucache.cache;
526
527 return lru.set('k1', 'v1')
528 .then(tick)
529 .then(() => lru.set('k2', 'v2'))
530 .then(() => lru.values())
531 .then((r) => assert.deepEqual(r, ['v2', 'v1']));
532 });
533
534 it('should not return more values if size exceeded before', () => {
535 let lrucache = new cache(client, 'someController');
536 lrucache.setOptions({max: 2}, true);
537 const lru = lrucache.cache;
538
539 return lru.set('k1', 'v1')
540 .then(tick)
541 .then(() => lru.set('k2', 'v2'))
542 .then(tick)
543 .then(() => lru.set('k3', 'v3'))
544 .then(() => lru.values())
545 .then((r) => assert.deepEqual(r, ['v3', 'v2']));
546 });
547});
548
549describe('ControllerCache count method', () => {
550 it('should return zero if no items in the cache', () => {
551 let lrucache = new cache(client, 'someController');
552 lrucache.setOptions({max: 2}, true);
553 const lru = lrucache.cache;
554
555 return lru.count()
556 .then((r) => assert.equal(r, 0));
557 });
558
559 it('should return the amount of items in the cache', () => {
560 let lrucache = new cache(client, 'someController');
561 lrucache.setOptions({max: 2}, true);
562 const lru = lrucache.cache;
563
564 return lru.set('k1', 'v1')
565 .then(tick)
566 .then(() => lru.set('k2', 'v2'))
567 .then(() => lru.count())
568 .then((r) => assert.equal(r, 2));
569 });
570
571 it('should return the max size if cache size exceeded before', () => {
572 let lrucache = new cache(client, 'someController');
573 lrucache.setOptions({max: 2}, true);
574 const lru = lrucache.cache;
575
576 return lru.set('k1', 'v1')
577 .then(tick)
578 .then(() => lru.set('k2', 'v2'))
579 .then(tick)
580 .then(() => lru.set('k3', 'v3'))
581 .then(() => lru.count())
582 .then((r) => assert.equal(r, 2));
583 });
584});
585
586describe('ControllerCache maxAge option', () => {
587 it('should return null after global maxAge has passed', () => {
588 let lrucache = new cache(client, 'someController');
589 lrucache.setOptions({max: 2, maxAge: 10}, true);
590 const lru = lrucache.cache;
591
592 return lru.set('k1', 'v1')
593 .then(() => lru.get('k1'))
594 .then((result) => assert.equal(result, 'v1'))
595 .then(() => tick(11))
596 .then(() => lru.get('k1'))
597 .then((result) => assert.equal(result, null));
598 });
599
600 it('should return null after key maxAge has passed', () => {
601 let lrucache = new cache(client, 'someController');
602 lrucache.setOptions({max: 2}, true);
603 const lru = lrucache.cache;
604
605 return lru.set('k1', 'v1', 10)
606 .then(() => lru.get('k1'))
607 .then((result) => assert.equal(result, 'v1'))
608 .then(() => tick(11))
609 .then(() => lru.get('k1'))
610 .then((result) => assert.equal(result, null));
611 });
612
613 it('should reduce dbsize after key expiration', () => {
614 let lrucache = new cache(client, 'someController');
615 lrucache.setOptions({max: 2, maxAge: 10}, true);
616 const lru = lrucache.cache;
617
618 return lru.set('k1', 'v1')
619 .then(dbsize)
620 .then((size) => assert.equal(size, 2))
621 .then(() => tick(11))
622 .then(() => lru.get('k1'))
623 .then((result) => assert.equal(result, null))
624 .then(dbsize)
625 .then((size) => assert.equal(size, 0)); // zset doesnt count if empty
626 });
627
628 it('should remove expired key from index next time is getted', () => {
629 let lrucache = new cache(client, 'someController');
630 lrucache.setOptions({max: 2}, true);
631 const lru = lrucache.cache;
632
633 return lru.set('k1', 'v1')
634 .then(() => lru.set('k2', 'v2', 10))
635 .then(() => tick(11))
636 .then(() => lru.get('k2'))
637 .then((result) => assert.equal(result, null))
638 .then(() => lru.count())
639 .then((count) => assert.equal(count, 1))
640 .then(() => lru.keys())
641 .then((keys) => assert.deepEqual(keys, ['k1']));
642 });
643
644 it('should remove expired key from index next time is peeked', () => {
645 let lrucache = new cache(client, 'someController');
646 lrucache.setOptions({max: 2}, true);
647 const lru = lrucache.cache;
648
649 return lru.set('k1', 'v1')
650 .then(() => lru.set('k2', 'v2', 10))
651 .then(() => tick(11))
652 .then(() => lru.peek('k2'))
653 .then((result) => assert.equal(result, null))
654 .then(() => lru.count())
655 .then((count) => assert.equal(count, 1))
656 .then(() => lru.keys())
657 .then((keys) => assert.deepEqual(keys, ['k1']));
658 });
659
660 it('should not let key maxAge affect other keys', () => {
661 let lrucache = new cache(client, 'someController');
662 lrucache.setOptions({max: 2, maxAge: 30}, true);
663 const lru = lrucache.cache;
664
665 return lru.set('k1', 'v1', 10)
666 .then(() => lru.set('k2', 'v2'))
667 .then(() => lru.get('k1'))
668 .then((result) => assert.equal(result, 'v1'))
669 .then(() => lru.get('k2'))
670 .then((result) => assert.equal(result, 'v2'))
671 .then(() => tick(11))
672 .then(() => lru.get('k1'))
673 .then((result) => assert.equal(result, null))
674 .then(() => lru.get('k2'))
675 .then((result) => assert.equal(result, 'v2'))
676 .then(() => tick(20))
677 .then(() => lru.get('k2'))
678 .then((result) => assert.equal(result, null));
679 });
680
681 it('should return false when calling has on an expired item', () => {
682 let lrucache = new cache(client, 'someController');
683 lrucache.setOptions({max: 2, maxAge: 10}, true);
684 const lru = lrucache.cache;
685
686 return lru.set('k1', 'v1')
687 .then(() => lru.has('k1'))
688 .then((result) => assert.equal(result, true))
689 .then(() => tick(11))
690 .then(() => lru.has('k1'))
691 .then((result) => assert.equal(result, false));
692 });
693});
694
695describe('ControllerCache custom score/increment options', () => {
696 it('should allow building a LFU cache with a custom score and increment', () => {
697 let lrucache = new cache(client, 'someController', 'Get', {max: 3, strategy: 'LFU'});
698 const lfu = lrucache.cache;
699
700 return lfu.set('k1', 'v1')
701 .then(() => lfu.get('k1'))
702 .then(() => lfu.get('k1')) // k1 used three times
703 .then(() => lfu.set('k2', 'v2'))
704 .then(() => lfu.set('k2', 'v22')) // k2 used 2 times
705 .then(() => lfu.set('k3', 'v3'))
706 .then(() => lfu.set('k4', 'v4')) // k3 should be removed
707 .then(() => lfu.get('k3'))
708 .then((result) => assert.equal(result, null))
709 .then(() => lfu.keys())
710 .then((keys) => assert.deepEqual(keys, ['k1', 'k2', 'k4']));
711 });
712});
713
714describe('ControllerCache Use a URL as a key', function () {
715 it('should store a url as a key', function () {
716 let lru = new cache(client, 'someController');
717 return lru.cache.set('/bands/led-zeppelin', 'v1')
718 .then(() => lru.cache.get('/bands/led-zeppelin'))
719 .then(result => assert.equal(result,'v1'))
720 });
721
722 it('should store a url & querystring as a key', function () {
723 let lru = new cache(client, 'someController');
724 return lru.cache.set('/bands/led-zeppelin?foo=bar&zap=123&weird=[1,2,3,4]&why={"key": "val"}', 'v1')
725 .then(() => lru.cache.get('/bands/led-zeppelin?foo=bar&zap=123&weird=[1,2,3,4]&why={"key": "val"}'))
726 .then(result => assert.equal(result,'v1'))
727 });
728});
729
730describe('ControllerCache cachedVersion', function () {
731 it('should return the cached version when it is available', function () {
732 let lru = new cache(client, 'someController', 'Get');
733 let req = {
734 controller : 'someController',
735 action : 'Get',
736 url : '/bands/led-zeppelin'
737 };
738 lru.cache.set('/bands/led-zeppelin', { name : 'Led Zeppelin' });
739
740 return lru.cachedVersion(req).then(result => {
741 assert.equal(result.name, 'Led Zeppelin')
742 });
743 });
744
745 it('should return false when it is not available', function () {
746 let lru = new cache(client, 'someController', 'Get');
747 let req = {
748 controller : 'someController',
749 action : 'Get',
750 url : '/bands/led-zeppelin'
751 };
752
753 return lru.cachedVersion(req).then(result => {
754 assert.equal(result, false);
755 });
756 });
757});
758
759describe('ControllerCache Controller Methods should work', function () {
760
761 class testController extends Controller {
762
763 Get () {
764 return promise( res => {
765 this.cache({ max: 100, strategy: 'LFU' }, cache => {
766 let doc = [{ name: 'doc1' }];
767 this.res.status(200).json(doc);
768 cache(doc).then(res);
769 });
770 });
771 }
772
773 FindOne () {
774 return promise( res => {
775 let doc = { name: 'doc1' };
776 this.cache({ max: 100, strategy: 'LRU' })
777 .miss(cache => {
778 this.res.status(200).json(doc);
779 cache(doc);
780 })
781 .hit(data => this.res.status(200).json(data))
782 .exec().then(res);
783 });
784 }
785
786 Post () {
787 return promise( res => {
788 this.actionCache('Get').reset().then(res);
789 });
790 }
791
792 Put () {
793 return promise( res => {
794 this.actionCache('Get').reset().then(res);
795 })
796 }
797
798 Delete () {
799 return promise( res => {
800 this.res.status(200).json({result: 'Ya, its gone forever'});
801 this.actionCache('Get').reset().then( () => {
802 this.actionCache('FindOne').del('/widgets/12').then(res);
803 });
804 })
805 }
806
807 lookup (val) {
808 return this.cache.get(val);
809 }
810
811 callbackWithResponseType () {
812 let doc = { name: 'doc1' };
813 return promise( res => {
814 let doc = { name: 'doc1' };
815 this.cache({ max: 100, strategy: 'LRU', responseMethod: 'send' }, cache => {
816 res(this.res.send(doc));
817 cache(doc);
818 })
819 });
820 }
821
822 promisable () {
823 let doc = { name: 'doc14' };
824 return promise( res => {
825 let doc = { name: 'doc1' };
826 this.cache({ max: 2, strategy: 'LFU' })
827 .then(() => User.find().limit(15))
828 .then(users => this.res.json(users).cache(users))
829 .catch(err => this.error(err))
830 .finally(res)
831 });
832 }
833
834 }
835
836 let res = {
837 status () {
838 return { json () { return 'json' } }
839 },
840 json () { return 'json' },
841 send () { return 'send'}
842 }
843
844 it('should cache on a request to a cacheable method (GET)', function () {
845 let myController = new testController({controller: 'myController', action: 'Get', url: '/widgets'}, res, client);
846 return myController.Get()
847 .then(() => myController.cacheStore.get('/widgets'))
848 .then(value => assert.deepEqual(value, [{name: 'doc1'}]))
849 })
850
851 it('should cache on a request to a cacheable method (FindOne)', function () {
852 let myController = new testController({controller: 'myController', action: 'FindOne', url: '/widgets'}, res, client);
853 return myController.FindOne()
854 .then(() => myController.cacheStore.get('/widgets'))
855 .then(value => assert.deepEqual(value, { name: 'doc1' }))
856 })
857
858 it('should remove a cached Item (PUT)', function () {
859 let controllerForGet = new testController({controller: 'myController', action: 'Get', url: '/widgets'}, res, client);
860 let controllerForPut = new testController({controller: 'myController', action: 'Put', url: '/widgets/12'}, res, client);
861
862 return controllerForGet.Get()
863 .then(() => controllerForGet.cacheStore.get('/widgets'))
864 .then(value => assert.deepEqual(value, [{name: 'doc1'}]))
865 .then(() => controllerForPut.Put())
866 .then(() => controllerForGet.cacheStore.get('/widgets'))
867 .then(value => assert.equal(value, null))
868 })
869
870
871 it('should remove a cached Item (DELETE)', function () {
872 let controllerForGet = new testController({controller: 'myController', action: 'Get', url: '/widgets'}, res, client);
873 let controllerForFindOne = new testController({controller: 'myController', action: 'FindOne', url: '/widgets/12'}, res, client);
874 let controllerForDelete = new testController({controller: 'myController', action: 'Delete', url: '/widgets/12'}, res, client);
875
876 return controllerForGet.Get()
877 .then(() => controllerForFindOne.FindOne())
878 .then(() => controllerForGet.cacheStore.get('/widgets'))
879 .then(value => assert.deepEqual(value, [{name: 'doc1'}]))
880
881 .then(() => controllerForFindOne.cacheStore.get('/widgets/12'))
882 .then(value => assert.deepEqual(value, {name: 'doc1'}))
883 .then(() => controllerForDelete.Delete())
884 .then(() => controllerForGet.cacheStore.get('/widgets'))
885 .then(value => assert.equal(value, null))
886 })
887
888});
889
890//