Skip to content

Commit

Permalink
fix: Do not use WeakRef on mocks. (nodejs#1290)
Browse files Browse the repository at this point in the history
* fix: Do not use WeakRef on mocks.

* fix: Linting errors.

* fix: Fixed test on older versions of Node.
  • Loading branch information
ShogunPanda authored and KhafraDev committed Jun 23, 2022
1 parent 686c381 commit 0999402
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
13 changes: 11 additions & 2 deletions lib/mock/mock-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
54 changes: 54 additions & 0 deletions test/mock-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -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))
})

0 comments on commit 0999402

Please sign in to comment.