Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 38 additions & 27 deletions test/connect-timeout.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use strict'

const { tspl } = require('@matteo.collina/tspl')
const { test, describe } = require('node:test')
const { Client, Pool, errors } = require('..')
const net = require('node:net')
Expand All @@ -10,21 +9,25 @@ const skip = !!process.env.CITGM

// Using describe instead of test to avoid the timeout
describe('prioritize socket errors over timeouts', { skip }, async () => {
const t = tspl({ ...assert, after: () => {} }, { plan: 2 })
const client = new Pool('http://foorbar.invalid:1234', { connectTimeout: 1 })
const { promise, resolve } = Promise.withResolvers()

client.request({ method: 'GET', path: '/foobar' })
.then(() => t.fail())
.then(() => {
assert.fail('should have errored')
resolve()
})
.catch((err) => {
t.strictEqual(err.code, 'ENOTFOUND')
t.strictEqual(err.code !== 'UND_ERR_CONNECT_TIMEOUT', true)
assert.strictEqual(err.code, 'ENOTFOUND')
assert.strictEqual(err.code !== 'UND_ERR_CONNECT_TIMEOUT', true)
resolve()
})

// block for 1s which is enough for the dns lookup to complete and the
// Timeout to fire
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, Number(1000))

await t.completed
await promise
})

// mock net.connect to avoid the dns lookup
Expand All @@ -33,7 +36,7 @@ net.connect = function (options) {
}

async function assertConnectTimeout (dispatcher, t) {
const tt = tspl(t, { plan: 3 })
t.plan(3)

await new Promise((resolve, reject) => {
// Connection timeouts use FastTimers, which have a deliberately low
Expand All @@ -48,9 +51,9 @@ async function assertConnectTimeout (dispatcher, t) {
method: 'GET'
}, (err) => {
try {
tt.ok(err instanceof errors.ConnectTimeoutError)
tt.strictEqual(err.code, 'UND_ERR_CONNECT_TIMEOUT')
tt.strictEqual(err.message, 'Connect Timeout Error (attempted address: localhost:9000, timeout: 1000ms)')
t.assert.ok(err instanceof errors.ConnectTimeoutError)
t.assert.strictEqual(err.code, 'UND_ERR_CONNECT_TIMEOUT')
t.assert.strictEqual(err.message, 'Connect Timeout Error (attempted address: localhost:9000, timeout: 1000ms)')
resolve()
} catch (error) {
reject(error)
Expand All @@ -59,8 +62,6 @@ async function assertConnectTimeout (dispatcher, t) {
}
})
})

await tt.completed
}

test('connect-timeout (Client)', { skip }, async t => {
Expand All @@ -82,8 +83,7 @@ test('connect-timeout (Pool)', { skip }, async t => {
})

test('autoSelectFamily AggregateError with ETIMEDOUT is normalized to ConnectTimeoutError', { skip }, async t => {
const _t = t
t = tspl(t, { plan: 5 })
t.plan(5)

const aggregate = new AggregateError([
Object.assign(new Error('connect ETIMEDOUT 127.0.0.1:9000'), { code: 'ETIMEDOUT' }),
Expand All @@ -103,18 +103,29 @@ test('autoSelectFamily AggregateError with ETIMEDOUT is normalized to ConnectTim
const client = new Client('http://localhost:9000', {
connectTimeout: 1e3
})
_t.after(() => client.close().catch(() => {}))

client.request({
path: '/',
method: 'GET'
}, (err) => {
t.ok(err instanceof errors.ConnectTimeoutError)
t.strictEqual(err.code, 'UND_ERR_CONNECT_TIMEOUT')
t.strictEqual(err.message, 'Connect Timeout Error (attempted addresses: 127.0.0.1:9000, ::1:9000, timeout: 1000ms)')
t.ok(err.cause instanceof AggregateError)
t.strictEqual(err.cause, aggregate)
})
t.after(() => client.close().catch(() => {}))

await new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('timeout waiting for callback'))
}, 5e3)

await t.completed
client.request({
path: '/',
method: 'GET'
}, (err) => {
try {
t.assert.ok(err instanceof errors.ConnectTimeoutError)
t.assert.strictEqual(err.code, 'UND_ERR_CONNECT_TIMEOUT')
t.assert.strictEqual(err.message, 'Connect Timeout Error (attempted addresses: 127.0.0.1:9000, ::1:9000, timeout: 1000ms)')
t.assert.ok(err.cause instanceof AggregateError)
t.assert.strictEqual(err.cause, aggregate)
resolve()
} catch (error) {
reject(error)
} finally {
clearTimeout(timeout)
}
})
})
})
Loading