diff --git a/.structignore b/.structignore
new file mode 100644
index 00000000..f820d242
--- /dev/null
+++ b/.structignore
@@ -0,0 +1 @@
+test/util/cache-clearer-disabled.spec.js
diff --git a/README.md b/README.md
index 22577e16..70b2f319 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 `^`.
+#### clearCache
+
+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-clearer.js b/src/modules/cache-clearer.js
new file mode 100644
index 00000000..79e52d0a
--- /dev/null
+++ b/src/modules/cache-clearer.js
@@ -0,0 +1,57 @@
+import assert from 'assert';
+import LRU from 'lru-cache-ext';
+
+const getFns = (obj) => {
+ const result = [];
+ const properties = [];
+ let o = obj;
+ while (o instanceof Object) {
+ properties.push(...Object.getOwnPropertyNames(o));
+ o = Object.getPrototypeOf(o);
+ }
+ 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, value });
+ }
+ return result;
+};
+
+export default () => {
+ let injected = false;
+ const fns = [
+ ...getFns(LRU.prototype)
+ ];
+ const caches = [];
+
+ return {
+ inject: () => {
+ assert(injected === false);
+ fns.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);
+ fns.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;
+ }
+ };
+};
diff --git a/src/util/desc.js b/src/util/desc.js
index f6899d44..e3ee3d19 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 CacheClearer from '../modules/cache-clearer.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()),
+ clearCache: 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 clearCache = get(opts, 'clearCache', 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 cacheClearer = 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 (clearCache !== false) {
+ cacheClearer = CacheClearer();
+ }
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 (cacheClearer !== null) {
+ cacheClearer.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 (cacheClearer !== null) {
+ cacheClearer.release();
+ }
})();
});
diff --git a/test/util/cache-clearer-disabled.spec.js b/test/util/cache-clearer-disabled.spec.js
new file mode 100644
index 00000000..ab8d9a53
--- /dev/null
+++ b/test/util/cache-clearer-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 Clear Cache Disabled', { clearCache: 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..60be80f1 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 Clear Cache', () => {
+ 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"