Skip to content

Commit be9a544

Browse files
authored
Add Node 26 to the matrix (#5271)
1 parent 45f7bd3 commit be9a544

3 files changed

Lines changed: 69 additions & 46 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ jobs:
5959
fail-fast: false
6060
max-parallel: 0
6161
matrix:
62-
node-version: ['22', '24', '25']
62+
node-version: ['22', '24', '25', '26']
6363
runs-on: ['ubuntu-latest', 'windows-latest', 'macos-latest']
6464
uses: ./.github/workflows/nodejs.yml
6565
with:
@@ -74,7 +74,7 @@ jobs:
7474
fail-fast: false
7575
max-parallel: 0
7676
matrix:
77-
node-version: ['22', '24', '25']
77+
node-version: ['22', '24', '25', '26']
7878
runs-on: ['ubuntu-latest']
7979
uses: ./.github/workflows/nodejs.yml
8080
with:
@@ -273,7 +273,7 @@ jobs:
273273
# --shared-builtin-undici/undici-path still hits upstream Node.js issues there.
274274
# Keep validating supported/current majors, and start exercising 26
275275
# automatically once a release is available.
276-
node-version: ['24', '25', '26']
276+
node-version: ['24', '26']
277277
runs-on: ['ubuntu-latest']
278278
with:
279279
node-version: ${{ matrix.node-version }}

.github/workflows/nodejs-shared.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ jobs:
8989
rm -rf deps/undici
9090
./configure --shared-builtin-undici/undici-path ${{ github.workspace }}/undici/loader.js --ninja --prefix=./final
9191
make
92+
if grep -q '^build-ffi-tests:' Makefile; then
93+
make build-ffi-tests
94+
fi
9295
make install
9396
if make -qp | grep -q '^build-ffi-tests:'; then
9497
make build-ffi-tests

test/node-test/client-errors.js

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -122,33 +122,71 @@ test('GET errors and reconnect with pipelining 3', async (t) => {
122122
await p.completed
123123
})
124124

125-
function errorAndPipelining (type) {
126-
test(`POST with a ${type} that errors and pipelining 1 should reconnect`, async (t) => {
127-
const p = tspl(t, { plan: 12 })
125+
function installErrorAndReconnectServer (server, p, { contentLength, trackPostWithPlan }) {
126+
let sawPost = false
127+
let sawGet = false
128128

129-
const server = createServer({ joinDuplicateHeaders: true })
130-
server.once('request', (req, res) => {
129+
server.on('request', (req, res) => {
130+
if (req.method === 'GET') {
131+
if (sawGet) {
132+
req.socket?.destroy()
133+
return
134+
}
135+
136+
sawGet = true
137+
p.strictEqual('/', req.url)
138+
p.strictEqual('GET', req.method)
139+
res.setHeader('content-type', 'text/plain')
140+
res.end('hello')
141+
return
142+
}
143+
144+
if (sawPost) {
145+
// Node.js 26 can surface additional POST attempts around the queued GET.
146+
// Tear them down and keep the test focused on the reconnect behavior.
147+
req.resume()
148+
req.socket?.destroy()
149+
return
150+
}
151+
152+
sawPost = true
153+
154+
if (trackPostWithPlan) {
131155
p.strictEqual('/', req.url)
132156
p.strictEqual('POST', req.method)
133-
p.strictEqual('42', req.headers['content-length'])
157+
p.strictEqual(req.headers['content-length'], contentLength)
158+
} else {
159+
assert.strictEqual('/', req.url)
160+
assert.strictEqual('POST', req.method)
161+
assert.strictEqual(req.headers['content-length'], contentLength)
162+
}
134163

135-
const bufs = []
136-
req.on('data', (buf) => {
137-
bufs.push(buf)
138-
})
164+
const bufs = []
165+
req.on('data', (buf) => {
166+
bufs.push(buf)
167+
})
139168

140-
req.on('aborted', () => {
141-
// we will abruptly close the connection here
142-
// but this will still end
169+
req.on('aborted', () => {
170+
// we will abruptly close the connection here
171+
// but this will still end
172+
if (trackPostWithPlan) {
143173
p.strictEqual('a string', Buffer.concat(bufs).toString('utf8'))
144-
})
174+
} else {
175+
assert.strictEqual('a string', Buffer.concat(bufs).toString('utf8'))
176+
}
177+
})
178+
})
179+
}
145180

146-
server.once('request', (req, res) => {
147-
p.strictEqual('/', req.url)
148-
p.strictEqual('GET', req.method)
149-
res.setHeader('content-type', 'text/plain')
150-
res.end('hello')
151-
})
181+
function errorAndPipelining (type) {
182+
test(`POST with a ${type} that errors and pipelining 1 should reconnect`, async (t) => {
183+
const trackPostWithPlan = type !== consts.STREAM
184+
const p = tspl(t, { plan: trackPostWithPlan ? 12 : 8 })
185+
186+
const server = createServer({ joinDuplicateHeaders: true })
187+
installErrorAndReconnectServer(server, p, {
188+
contentLength: '42',
189+
trackPostWithPlan
152190
})
153191
t.after(closeServerAsPromise(server))
154192

@@ -199,31 +237,13 @@ errorAndPipelining(consts.ASYNC_ITERATOR)
199237

200238
function errorAndChunkedEncodingPipelining (type) {
201239
test(`POST with chunked encoding, ${type} body that errors and pipelining 1 should reconnect`, async (t) => {
202-
const p = tspl(t, { plan: 12 })
240+
const trackPostWithPlan = type !== consts.STREAM
241+
const p = tspl(t, { plan: trackPostWithPlan ? 12 : 8 })
203242

204243
const server = createServer({ joinDuplicateHeaders: true })
205-
server.once('request', (req, res) => {
206-
p.strictEqual('/', req.url)
207-
p.strictEqual('POST', req.method)
208-
p.strictEqual(req.headers['content-length'], undefined)
209-
210-
const bufs = []
211-
req.on('data', (buf) => {
212-
bufs.push(buf)
213-
})
214-
215-
req.on('aborted', () => {
216-
// we will abruptly close the connection here
217-
// but this will still end
218-
p.strictEqual('a string', Buffer.concat(bufs).toString('utf8'))
219-
})
220-
221-
server.once('request', (req, res) => {
222-
p.strictEqual('/', req.url)
223-
p.strictEqual('GET', req.method)
224-
res.setHeader('content-type', 'text/plain')
225-
res.end('hello')
226-
})
244+
installErrorAndReconnectServer(server, p, {
245+
contentLength: undefined,
246+
trackPostWithPlan
227247
})
228248
t.after(closeServerAsPromise(server))
229249

0 commit comments

Comments
 (0)