From 13da6b0d4b0d750525e0b3bbef24f650af3bb42b Mon Sep 17 00:00:00 2001 From: Lukas Siemon Date: Mon, 5 Dec 2022 11:49:44 -0800 Subject: [PATCH 1/5] feat: auto clearing caches --- .structignore | 1 + README.md | 7 +++ package.json | 1 + src/modules/cache-voider.js | 62 +++++++++++++++++++++++++ src/util/desc.js | 13 ++++++ test/util/cache-voider-disabled.spec.js | 19 ++++++++ test/util/desc.spec.js | 18 +++++++ yarn.lock | 12 +++++ 8 files changed, 133 insertions(+) create mode 100644 .structignore create mode 100644 src/modules/cache-voider.js create mode 100644 test/util/cache-voider-disabled.spec.js diff --git a/.structignore b/.structignore new file mode 100644 index 00000000..5840856d --- /dev/null +++ b/.structignore @@ -0,0 +1 @@ +test/util/cache-voider-disabled.spec.js diff --git a/README.md b/README.md index 22577e16..be3b2781 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,13 @@ loaded from `envVarsFile` (if allowed). To allow overwriting of environment variables, prefix the name of the environment variable with `^`. +#### voidCache + +Type: `boolean`
+Default: `true` + +Known, accessed caches will be cleared after test has executed when set to `true`. + #### timestamp Type: `number|string`
diff --git a/package.json b/package.json index 90c35f7a..bd991b40 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "joi-strict": "2.0.1", "lodash.clonedeep": "4.5.0", "lodash.get": "4.4.2", + "lru-cache-ext": "3.0.2", "minimist": "1.2.6", "nock": "13.2.4", "object-scan": "18.0.1", diff --git a/src/modules/cache-voider.js b/src/modules/cache-voider.js new file mode 100644 index 00000000..d54f3abd --- /dev/null +++ b/src/modules/cache-voider.js @@ -0,0 +1,62 @@ +import assert from 'assert'; +import LRU from 'lru-cache-ext'; + +const getMocks = (obj) => { + const result = []; + const keys = []; + let o = obj; + while (o instanceof Object) { + keys.push(...Object.getOwnPropertyNames(o)); + o = Object.getPrototypeOf(o); + } + for (let i = 0; i < keys.length; i += 1) { + const k = keys[i]; + const v = LRU.prototype[k]; + if (typeof v !== 'function') { + // eslint-disable-next-line no-continue + continue; + } + result.push({ + obj, + key: k, + value: v + }); + } + return result; +}; + +export default () => { + let injected = false; + const mocks = [ + ...getMocks(LRU.prototype) + ]; + const caches = []; + + return { + inject: () => { + assert(injected === false); + mocks.forEach(({ obj, key, value }) => { + try { + // eslint-disable-next-line no-param-reassign,func-names + obj[key] = function (...args) { + caches.push(this); + return value.call(this, ...args); + }; + } catch (e) { /* ignored */ } + }); + injected = true; + }, + release: () => { + assert(injected === true); + mocks.forEach(({ obj, key, value }) => { + try { + // eslint-disable-next-line no-param-reassign + obj[key] = value; + } catch (e) { /* ignored */ } + }); + caches.splice(0).forEach((c) => c.clear()); + injected = false; + }, + isInjected: () => injected + }; +}; diff --git a/src/util/desc.js b/src/util/desc.js index f6899d44..e788bc83 100644 --- a/src/util/desc.js +++ b/src/util/desc.js @@ -12,6 +12,7 @@ import EnvManager from '../modules/env-manager.js'; import TimeKeeper from '../modules/time-keeper.js'; import LogRecorder from '../modules/log-recorder.js'; import RandomSeeder from '../modules/random-seeder.js'; +import CacheVoider from '../modules/cache-voider.js'; import { getParents, genCassetteName } from './mocha-test.js'; const mocha = { @@ -53,6 +54,7 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { fixtureFolder: Joi.string().optional(), envVarsFile: Joi.string().optional(), envVars: Joi.object().optional().unknown(true).pattern(Joi.string(), Joi.string()), + voidCache: Joi.boolean().optional(), timestamp: Joi.alternatives( Joi.number().integer().min(0), Joi.date().iso() @@ -75,6 +77,7 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { const fixtureFolder = resolve(get(opts, 'fixtureFolder', '$FILENAME__fixtures')); const envVarsFile = resolve(get(opts, 'envVarsFile', '$FILENAME.env.yml')); const envVars = get(opts, 'envVars', null); + const voidCache = get(opts, 'voidCache', true); const timestamp = get(opts, 'timestamp', null); const record = get(opts, 'record', false); const cryptoSeed = get(opts, 'cryptoSeed', null); @@ -84,6 +87,7 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { let dir = null; let requestRecorder = null; + let cacheVoider = null; let envManagerFile = null; let envManagerDesc = null; let timeKeeper = null; @@ -130,6 +134,9 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { // eslint-disable-next-line func-names mocha.before(function () { return (async () => { + if (voidCache !== false) { + cacheVoider = CacheVoider(); + } if (getParents(this.test).length === 3 && fs.existsSync(envVarsFile)) { envManagerFile = EnvManager({ envVars: fs.smartRead(envVarsFile), allowOverwrite: false }); envManagerFile.apply(); @@ -190,6 +197,9 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { // eslint-disable-next-line func-names mocha.beforeEach(function () { return (async () => { + if (cacheVoider !== null) { + cacheVoider.inject(); + } if (useTmpDir === true) { tmp.setGracefulCleanup(); dir = tmp.dirSync({ keep: false, unsafeCleanup: true }).name; @@ -222,6 +232,9 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { if (dir !== null) { dir = null; } + if (cacheVoider !== null) { + cacheVoider.release(); + } })(); }); diff --git a/test/util/cache-voider-disabled.spec.js b/test/util/cache-voider-disabled.spec.js new file mode 100644 index 00000000..46cdfee9 --- /dev/null +++ b/test/util/cache-voider-disabled.spec.js @@ -0,0 +1,19 @@ +import LRU from 'lru-cache-ext'; +import { expect } from 'chai'; +import describe from '../../src/util/desc.js'; + +describe('Testing Cache Reset Disabled', { voidCache: false }, () => { + let cache; + before(() => { + cache = new LRU({ ttl: 100, max: 100 }); + }); + + it('First', () => { + expect(cache.has('a')).to.equal(false); + cache.set('a', 1); + }); + + it('Second', () => { + expect(cache.has('a')).to.equal(true); + }); +}); diff --git a/test/util/desc.spec.js b/test/util/desc.spec.js index 230b685a..07b9f07d 100644 --- a/test/util/desc.spec.js +++ b/test/util/desc.spec.js @@ -5,6 +5,7 @@ import path from 'path'; import axios from 'axios'; import fancyLog from 'fancy-log'; import { expect } from 'chai'; +import LRU from 'lru-cache-ext'; import describe from '../../src/util/desc.js'; const dirPrefix = path.join(os.tmpdir(), 'tmp-'); @@ -261,4 +262,21 @@ describe('Testing { describe }', () => { state.push('testTwo'); }); }); + + describe('Testing Cache Reset', () => { + let cache; + before(() => { + cache = new LRU({ ttl: 100, max: 100 }); + }); + + it('First', () => { + expect(cache.has('a')).to.equal(false); + cache.set('a', 1); + }); + + it('Second', () => { + expect(cache.has('a')).to.equal(false); + cache.set('a', 1); + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 190fc7df..b677790e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2734,6 +2734,18 @@ lowercase-keys@^1.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== +lru-cache-ext@3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/lru-cache-ext/-/lru-cache-ext-3.0.2.tgz#5dc1fb94bc22431c8a8fe602226155838d940b52" + integrity sha512-PQ0kInomO2I3HZuiagNTkaNyiDQkcIyeEahHRWSBVsEaxPqXb4FTPU4ajl9znX+C5antzQ0UWcfWrxy8kAhUrw== + dependencies: + lru-cache "7.8.1" + +lru-cache@7.8.1: + version "7.8.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.8.1.tgz#68ee3f4807a57d2ba185b7fd90827d5c21ce82bb" + integrity sha512-E1v547OCgJvbvevfjgK9sNKIVXO96NnsTsFPBlg4ZxjhsJSODoH9lk8Bm0OxvHNm6Vm5Yqkl/1fErDxhYL8Skg== + lru-cache@^4.0.0, lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" From 43df2327d72b193202a4065be45f821e5f7e1490 Mon Sep 17 00:00:00 2001 From: Lukas Siemon Date: Mon, 5 Dec 2022 11:52:16 -0800 Subject: [PATCH 2/5] amend: minor --- src/modules/cache-voider.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/cache-voider.js b/src/modules/cache-voider.js index d54f3abd..82d75992 100644 --- a/src/modules/cache-voider.js +++ b/src/modules/cache-voider.js @@ -56,7 +56,6 @@ export default () => { }); caches.splice(0).forEach((c) => c.clear()); injected = false; - }, - isInjected: () => injected + } }; }; From 63ab05d83979b0f9ffb0b9ea52d4fcecaa95c6a6 Mon Sep 17 00:00:00 2001 From: Lukas Siemon Date: Mon, 5 Dec 2022 13:32:07 -0800 Subject: [PATCH 3/5] amend: rename --- .structignore | 2 +- README.md | 2 +- .../{cache-voider.js => cache-clearer.js} | 0 src/util/desc.js | 20 +++++++++---------- ...spec.js => cache-clearer-disabled.spec.js} | 2 +- test/util/desc.spec.js | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) rename src/modules/{cache-voider.js => cache-clearer.js} (100%) rename test/util/{cache-voider-disabled.spec.js => cache-clearer-disabled.spec.js} (83%) diff --git a/.structignore b/.structignore index 5840856d..f820d242 100644 --- a/.structignore +++ b/.structignore @@ -1 +1 @@ -test/util/cache-voider-disabled.spec.js +test/util/cache-clearer-disabled.spec.js diff --git a/README.md b/README.md index be3b2781..37d47749 100644 --- a/README.md +++ b/README.md @@ -176,7 +176,7 @@ loaded from `envVarsFile` (if allowed). To allow overwriting of environment variables, prefix the name of the environment variable with `^`. -#### voidCache +#### clearCache Type: `boolean`
Default: `true` diff --git a/src/modules/cache-voider.js b/src/modules/cache-clearer.js similarity index 100% rename from src/modules/cache-voider.js rename to src/modules/cache-clearer.js diff --git a/src/util/desc.js b/src/util/desc.js index e788bc83..e3ee3d19 100644 --- a/src/util/desc.js +++ b/src/util/desc.js @@ -12,7 +12,7 @@ import EnvManager from '../modules/env-manager.js'; import TimeKeeper from '../modules/time-keeper.js'; import LogRecorder from '../modules/log-recorder.js'; import RandomSeeder from '../modules/random-seeder.js'; -import CacheVoider from '../modules/cache-voider.js'; +import CacheClearer from '../modules/cache-clearer.js'; import { getParents, genCassetteName } from './mocha-test.js'; const mocha = { @@ -54,7 +54,7 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { fixtureFolder: Joi.string().optional(), envVarsFile: Joi.string().optional(), envVars: Joi.object().optional().unknown(true).pattern(Joi.string(), Joi.string()), - voidCache: Joi.boolean().optional(), + clearCache: Joi.boolean().optional(), timestamp: Joi.alternatives( Joi.number().integer().min(0), Joi.date().iso() @@ -77,7 +77,7 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { const fixtureFolder = resolve(get(opts, 'fixtureFolder', '$FILENAME__fixtures')); const envVarsFile = resolve(get(opts, 'envVarsFile', '$FILENAME.env.yml')); const envVars = get(opts, 'envVars', null); - const voidCache = get(opts, 'voidCache', true); + const clearCache = get(opts, 'clearCache', true); const timestamp = get(opts, 'timestamp', null); const record = get(opts, 'record', false); const cryptoSeed = get(opts, 'cryptoSeed', null); @@ -87,7 +87,7 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { let dir = null; let requestRecorder = null; - let cacheVoider = null; + let cacheClearer = null; let envManagerFile = null; let envManagerDesc = null; let timeKeeper = null; @@ -134,8 +134,8 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { // eslint-disable-next-line func-names mocha.before(function () { return (async () => { - if (voidCache !== false) { - cacheVoider = CacheVoider(); + if (clearCache !== false) { + cacheClearer = CacheClearer(); } if (getParents(this.test).length === 3 && fs.existsSync(envVarsFile)) { envManagerFile = EnvManager({ envVars: fs.smartRead(envVarsFile), allowOverwrite: false }); @@ -197,8 +197,8 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { // eslint-disable-next-line func-names mocha.beforeEach(function () { return (async () => { - if (cacheVoider !== null) { - cacheVoider.inject(); + if (cacheClearer !== null) { + cacheClearer.inject(); } if (useTmpDir === true) { tmp.setGracefulCleanup(); @@ -232,8 +232,8 @@ const desc = (suiteName, optsOrTests, testsOrNull = null) => { if (dir !== null) { dir = null; } - if (cacheVoider !== null) { - cacheVoider.release(); + if (cacheClearer !== null) { + cacheClearer.release(); } })(); }); diff --git a/test/util/cache-voider-disabled.spec.js b/test/util/cache-clearer-disabled.spec.js similarity index 83% rename from test/util/cache-voider-disabled.spec.js rename to test/util/cache-clearer-disabled.spec.js index 46cdfee9..ab8d9a53 100644 --- a/test/util/cache-voider-disabled.spec.js +++ b/test/util/cache-clearer-disabled.spec.js @@ -2,7 +2,7 @@ import LRU from 'lru-cache-ext'; import { expect } from 'chai'; import describe from '../../src/util/desc.js'; -describe('Testing Cache Reset Disabled', { voidCache: false }, () => { +describe('Testing Clear Cache Disabled', { clearCache: false }, () => { let cache; before(() => { cache = new LRU({ ttl: 100, max: 100 }); diff --git a/test/util/desc.spec.js b/test/util/desc.spec.js index 07b9f07d..60be80f1 100644 --- a/test/util/desc.spec.js +++ b/test/util/desc.spec.js @@ -263,7 +263,7 @@ describe('Testing { describe }', () => { }); }); - describe('Testing Cache Reset', () => { + describe('Testing Clear Cache', () => { let cache; before(() => { cache = new LRU({ ttl: 100, max: 100 }); From 22e22eeb077645915e738401a8382986b4ebb86d Mon Sep 17 00:00:00 2001 From: Lukas Siemon Date: Mon, 5 Dec 2022 13:35:27 -0800 Subject: [PATCH 4/5] amend: refactor --- src/modules/cache-clearer.js | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/modules/cache-clearer.js b/src/modules/cache-clearer.js index 82d75992..79e52d0a 100644 --- a/src/modules/cache-clearer.js +++ b/src/modules/cache-clearer.js @@ -1,41 +1,37 @@ import assert from 'assert'; import LRU from 'lru-cache-ext'; -const getMocks = (obj) => { +const getFns = (obj) => { const result = []; - const keys = []; + const properties = []; let o = obj; while (o instanceof Object) { - keys.push(...Object.getOwnPropertyNames(o)); + properties.push(...Object.getOwnPropertyNames(o)); o = Object.getPrototypeOf(o); } - for (let i = 0; i < keys.length; i += 1) { - const k = keys[i]; - const v = LRU.prototype[k]; - if (typeof v !== 'function') { + for (let i = 0; i < properties.length; i += 1) { + const key = properties[i]; + const value = LRU.prototype[key]; + if (typeof value !== 'function') { // eslint-disable-next-line no-continue continue; } - result.push({ - obj, - key: k, - value: v - }); + result.push({ obj, key, value }); } return result; }; export default () => { let injected = false; - const mocks = [ - ...getMocks(LRU.prototype) + const fns = [ + ...getFns(LRU.prototype) ]; const caches = []; return { inject: () => { assert(injected === false); - mocks.forEach(({ obj, key, value }) => { + fns.forEach(({ obj, key, value }) => { try { // eslint-disable-next-line no-param-reassign,func-names obj[key] = function (...args) { @@ -48,7 +44,7 @@ export default () => { }, release: () => { assert(injected === true); - mocks.forEach(({ obj, key, value }) => { + fns.forEach(({ obj, key, value }) => { try { // eslint-disable-next-line no-param-reassign obj[key] = value; From e3aa49551e1faef6a8c39a36b989a9b4210be181 Mon Sep 17 00:00:00 2001 From: Lukas Siemon Date: Mon, 5 Dec 2022 13:41:58 -0800 Subject: [PATCH 5/5] Update README.md Co-authored-by: Kodi Ackerman --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 37d47749..70b2f319 100644 --- a/README.md +++ b/README.md @@ -181,7 +181,7 @@ To allow overwriting of environment variables, prefix the name of the environmen Type: `boolean`
Default: `true` -Known, accessed caches will be cleared after test has executed when set to `true`. +Known accessed caches will be cleared after test has executed when set to `true`. #### timestamp