From 0999402b415ec0907b3c31dd2917a322b81eeadb Mon Sep 17 00:00:00 2001 From: Paolo Insogna Date: Fri, 18 Mar 2022 12:08:10 +0100 Subject: [PATCH] fix: Do not use WeakRef on mocks. (#1290) * fix: Do not use WeakRef on mocks. * fix: Linting errors. * fix: Fixed test on older versions of Node. --- lib/mock/mock-agent.js | 13 ++++++++-- test/mock-agent.js | 54 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/lib/mock/mock-agent.js b/lib/mock/mock-agent.js index d4f060d8ce7..4ae47f657fe 100644 --- a/lib/mock/mock-agent.js +++ b/lib/mock/mock-agent.js @@ -18,7 +18,16 @@ const MockPool = require('./mock-pool') const { matchValue, buildMockOptions } = require('./mock-utils') const { InvalidArgumentError } = require('../core/errors') const Dispatcher = require('../dispatcher') -const { WeakRef } = require('../compat/dispatcher-weakref')() + +class FakeWeakRef { + constructor (value) { + this.value = value + } + + deref () { + return this.value + } +} class MockAgent extends Dispatcher { constructor (opts) { @@ -86,7 +95,7 @@ class MockAgent extends Dispatcher { } [kMockAgentSet] (origin, dispatcher) { - this[kClients].set(origin, new WeakRef(dispatcher)) + this[kClients].set(origin, new FakeWeakRef(dispatcher)) } [kFactory] (origin) { diff --git a/test/mock-agent.js b/test/mock-agent.js index db0beb52ebd..a0301f208d8 100644 --- a/test/mock-agent.js +++ b/test/mock-agent.js @@ -2349,3 +2349,57 @@ test('MockAgent - headers function interceptor', async (t) => { t.equal(statusCode, 200) } }) + +test('MockAgent - clients are not garbage collected', async (t) => { + const samples = 250 + t.plan(2) + + const server = createServer((req, res) => { + t.fail('should not be called') + t.end() + res.end('should not be called') + }) + t.teardown(server.close.bind(server)) + + await promisify(server.listen.bind(server))(0) + + const baseUrl = `http://localhost:${server.address().port}` + + // Create the dispatcher and isable net connect so we can make sure it matches properly + const dispatcher = new MockAgent() + dispatcher.disableNetConnect() + + // When Node 16 is the minimum supported, this can be replaced by simply requiring setTimeout from timers/promises + function sleep (delay) { + return new Promise(resolve => { + setTimeout(resolve, delay) + }) + } + + // Purposely create the pool inside a function so that the reference is lost + function intercept () { + // Create the pool and add a lot of intercepts + const pool = dispatcher.get(baseUrl) + + for (let i = 0; i < samples; i++) { + pool.intercept({ + path: `/foo/${i}`, + method: 'GET' + }).reply(200, Buffer.alloc(1024 * 1024)) + } + } + + intercept() + + const results = new Set() + for (let i = 0; i < samples; i++) { + // Let's make some time pass to allow garbage collection to happen + await sleep(10) + + const { statusCode } = await request(`${baseUrl}/foo/${i}`, { method: 'GET', dispatcher }) + results.add(statusCode) + } + + t.equal(results.size, 1) + t.ok(results.has(200)) +})