From 6105ea718fd63efac2a3dbc1d20f544b2962442f Mon Sep 17 00:00:00 2001 From: isaacs Date: Fri, 10 Nov 2023 18:43:34 -0800 Subject: [PATCH] update tests to pass on node <20 --- .gitignore | 1 + .prettierignore | 14 ++++---- CHANGELOG.md | 2 +- README.md | 4 +-- scripts/max-size-test.js | 75 --------------------------------------- test/avoid-memory-leak.ts | 4 +-- test/move-to-tail.ts | 4 +-- test/warn-missing-ac.ts | 71 ++++++++++++++++++++++++------------ 8 files changed, 63 insertions(+), 112 deletions(-) delete mode 100755 scripts/max-size-test.js diff --git a/.gitignore b/.gitignore index 8db06982..0c658015 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.tap /node_modules /dist +/docs diff --git a/.prettierignore b/.prettierignore index 4edd771b..e6e7150c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,10 +1,10 @@ /node_modules -/tap-snapshots -/coverage -/.nyc_output -/benchmark -/.github -/scripts -/CHANGELOG.md /docs +/.tap +/*.json +/example +/.github /dist +/tap-snapshots +/benchmark +/.tshy diff --git a/CHANGELOG.md b/CHANGELOG.md index 93ac2085..aa2cde3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ ## 9.0.0 - Use named export only, no default export. -- Bring back minimal polyfill. If this polyfill ends up being +- Bring back minimal polyfill. If this polyfill ends up being used, then a warning is printed, as it is not safe for use outside of LRUCache. diff --git a/README.md b/README.md index c3d0f204..a12c0cc7 100644 --- a/README.md +++ b/README.md @@ -278,10 +278,10 @@ For example: ```ts const cache = new LRUCache({ ttl: 100, - fetchMethod: async (url, oldValue, { signal }) => { + fetchMethod: async (url, oldValue, { signal }) => { const res = await fetch(url, { signal }) return await res.json() - } + }, }) cache.set('https://example.com/', { some: 'data' }) // 100ms go by... diff --git a/scripts/max-size-test.js b/scripts/max-size-test.js deleted file mode 100755 index 3f6c58e6..00000000 --- a/scripts/max-size-test.js +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env node --max_old_space_size=400 --expose_gc - -// https://github.com/isaacs/node-lru-cache/issues/227 - -if (typeof gc !== 'function') { - throw new Error('run with --expose-gc') -} - -let heapdump -try { - heapdump = require('heapdump') -} catch (e) { - const {spawnSync} = require('child_process') - spawnSync('npm', ['install'], { cwd: __dirname, stdio: 'inherit' }) - heapdump = require('heapdump') -} - -const LRU = require('../') -const maxSize = 1_000_000 -const itemSize = 1_000 -const expectItemCount = Math.floor(maxSize / itemSize) -const profEvery = 100_000 -const n = 10_000_000 - -const sizeCalculation = s => s.length || 1 -const max = expectItemCount + 1 -const keyRange = expectItemCount * 2 -const makeItem = () => Buffer.alloc(itemSize) - -const v8 = require('v8') -const prof = async (i, cache, name) => { - // run gc so that we know if we're actually leaking memory, or just - // that the gc is being lazy and not responding until there's memory - // pressure. - gc() - const file = `${__dirname}/heapdump-${name}-${i}.heapsnapshot` - await new Promise((res, rej) => - heapdump.writeSnapshot(file, er => er ? rej(er) : res())) - if (!cache || i === 0) { - console.log(i, v8.getHeapStatistics(), file) - } - if (cache && i === 0) { - console.log(max, cache.valList.length, cache.free.length) - } -} - -const test = async (name, cache) => { - console.log(name) - for (let i = 0; i < n; i++) { - if ((i % profEvery) === 0) { - await prof(i, cache, name) - } - - // add items within a range of 2x the expected item count, - // so we get evictions happening - const item = makeItem() - cache.set(i % keyRange, item) - - // get some random item, too, to keep the list a bit shuffled. - // often these will be missing, of course, but expectItemCount/keyRange - // times they'll be a hit, once the cache is full. - const j = Math.floor(Math.random() * keyRange) - cache.get(j) - } - cache = null - prof(n, null, name) -} - -const main = async () => { - await test('max-no-maxSize', new LRU({ max })) - await test('max-maxSize', new LRU({ max, maxSize, sizeCalculation })) - await test('no-max-maxSize', new LRU({ maxSize, sizeCalculation })) -} - -main() diff --git a/test/avoid-memory-leak.ts b/test/avoid-memory-leak.ts index d916e94e..7b7dc307 100644 --- a/test/avoid-memory-leak.ts +++ b/test/avoid-memory-leak.ts @@ -2,7 +2,7 @@ // https://github.com/isaacs/node-lru-cache/issues/227 -import t, {Test} from 'tap' +import t, { Test } from 'tap' import { expose } from './fixtures/expose.js' const maxSize = 100_000 @@ -28,7 +28,7 @@ const tryReq = (mod: string) => { const v8 = tryReq('v8') import { LRUCache } from '../dist/esm/index.js' -import {createRequire} from 'module' +import { createRequire } from 'module' const expectItemCount = Math.ceil(maxSize / itemSize) const max = expectItemCount + 1 const keyRange = expectItemCount * 2 diff --git a/test/move-to-tail.ts b/test/move-to-tail.ts index f1611df2..08b3ccc7 100644 --- a/test/move-to-tail.ts +++ b/test/move-to-tail.ts @@ -30,10 +30,10 @@ t.test('list integrity', { bail: true }, t => { t.test(msg, { bail: false }, t => { for (let i = 0; i < c.max; i++) { if (i !== exp.head) { - t.equal(exp.next[(exp.prev[i] as number)], i, 'n[p[i]] === i') + t.equal(exp.next[exp.prev[i] as number], i, 'n[p[i]] === i') } if (i !== exp.tail) { - t.equal(exp.prev[(exp.next[i] as number)], i, 'p[n[i]] === i') + t.equal(exp.prev[exp.next[i] as number], i, 'p[n[i]] === i') } } t.end() diff --git a/test/warn-missing-ac.ts b/test/warn-missing-ac.ts index 79ed06a2..c0d1cd6f 100644 --- a/test/warn-missing-ac.ts +++ b/test/warn-missing-ac.ts @@ -1,6 +1,6 @@ -import {fileURLToPath} from 'url' +import { createRequire } from 'module' +import { fileURLToPath } from 'url' -export {} const __filename = fileURLToPath(import.meta.url) const main = async () => { const { default: t } = await import('tap') @@ -9,32 +9,46 @@ const main = async () => { // need to run both tests in parallel so we don't miss the close event t.jobs = 3 - const warn = spawn(process.execPath, [ - ...process.execArgv, - __filename, - 'child', - ]) + const argv = process.execArgv.filter( + a => !a.startsWith('--no-warnings') + ) + const warn = spawn( + process.execPath, + [...argv, __filename, 'child'], + { + env: { + ...process.env, + NODE_OPTIONS: '', + }, + } + ) const warnErr: Buffer[] = [] warn.stderr.on('data', c => warnErr.push(c)) const noWarn = spawn( process.execPath, - [...process.execArgv, __filename, 'child'], + [...argv, __filename, 'child'], { env: { ...process.env, LRU_CACHE_IGNORE_AC_WARNING: '1', + NODE_OPTIONS: '', }, } ) const noWarnErr: Buffer[] = [] noWarn.stderr.on('data', c => noWarnErr.push(c)) - const noFetch = spawn(process.execPath, [ - ...process.execArgv, - __filename, - 'child-no-fetch', - ]) + const noFetch = spawn( + process.execPath, + [...argv, __filename, 'child-no-fetch'], + { + env: { + ...process.env, + NODE_OPTIONS: '', + }, + } + ) const noFetchErr: Buffer[] = [] noFetch.stderr.on('data', c => noFetchErr.push(c)) @@ -46,7 +60,10 @@ const main = async () => { r() }) ) - t.equal(Buffer.concat(noWarnErr).toString().trim(), '') + t.notMatch( + Buffer.concat(noWarnErr).toString().trim(), + 'NO_ABORT_CONTROLLER' + ) }) t.test('no warning (because no fetch)', async t => { @@ -57,7 +74,10 @@ const main = async () => { r() }) ) - t.equal(Buffer.concat(noFetchErr).toString().trim(), '') + t.notMatch( + Buffer.concat(noWarnErr).toString().trim(), + 'NO_ABORT_CONTROLLER' + ) }) t.test('warning', async t => { @@ -68,24 +88,29 @@ const main = async () => { r() }) ) - t.not(Buffer.concat(warnErr).toString().trim(), '') + t.match( + Buffer.concat(warnErr).toString().trim(), + /NO_ABORT_CONTROLLER/ + ) }) } switch (process.argv[2]) { case 'child': - //@ts-ignore + //@ts-expect-error + process.emitWarning = null + //@ts-expect-error globalThis.AbortController = undefined - //@ts-ignore + //@ts-expect-error globalThis.AbortSignal = undefined - import('../dist/esm/index.js').then(({ LRUCache }) => { - new LRUCache({ max: 1, fetchMethod: async () => 1 }).fetch(1) - }) + const req = createRequire(import.meta.url) + const { LRUCache } = req('../dist/commonjs/index.js') + new LRUCache({ max: 1, fetchMethod: async () => 1 }).fetch(1) break case 'child-no-fetch': - //@ts-ignore + //@ts-expect-error globalThis.AbortController = undefined - //@ts-ignore + //@ts-expect-error globalThis.AbortSignal = undefined import('../dist/esm/index.js') break