Skip to content

Commit b1f7e9e

Browse files
committed
quic: add test
1 parent 63c637c commit b1f7e9e

1 file changed

Lines changed: 112 additions & 0 deletions

File tree

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// Flags: --experimental-quic --no-warnings
2+
3+
// CONNECTION_CLOSE reason strings are truncated to 256 UTF-8 bytes.
4+
5+
import { hasQuic, skip, mustCall } from '../common/index.mjs';
6+
import assert from 'node:assert';
7+
import { setTimeout } from 'node:timers/promises';
8+
9+
if (!hasQuic) {
10+
skip('QUIC is not enabled');
11+
}
12+
13+
const { listen, connect } = await import('../common/quic.mjs');
14+
15+
const kMaxReasonLength = 256;
16+
17+
// Client close with an ASCII reason longer than the wire limit.
18+
{
19+
const reason = 'a'.repeat(kMaxReasonLength + 1);
20+
const expectedReason = reason.slice(0, kMaxReasonLength);
21+
const serverDone = Promise.withResolvers();
22+
23+
const serverEndpoint = await listen(mustCall(async (serverSession) => {
24+
serverSession.onerror = mustCall((error) => {
25+
assert.strictEqual(error.reason, expectedReason);
26+
});
27+
await assert.rejects(serverSession.closed, {
28+
code: 'ERR_QUIC_APPLICATION_ERROR',
29+
reason: expectedReason,
30+
});
31+
serverDone.resolve();
32+
}));
33+
34+
const clientSession = await connect(serverEndpoint.address, {
35+
reuseEndpoint: false,
36+
});
37+
await clientSession.opened;
38+
await setTimeout(100);
39+
await clientSession.close({
40+
code: 1n,
41+
type: 'application',
42+
reason,
43+
});
44+
45+
await serverDone.promise;
46+
await serverEndpoint.close();
47+
}
48+
49+
// Client close where truncating at the byte limit would split a UTF-8 sequence.
50+
{
51+
const prefix = 'a'.repeat(kMaxReasonLength - 1);
52+
const reason = `${prefix}€`;
53+
const serverDone = Promise.withResolvers();
54+
55+
const serverEndpoint = await listen(mustCall(async (serverSession) => {
56+
serverSession.onerror = mustCall((error) => {
57+
assert.strictEqual(error.reason, prefix);
58+
});
59+
await assert.rejects(serverSession.closed, {
60+
code: 'ERR_QUIC_APPLICATION_ERROR',
61+
reason: prefix,
62+
});
63+
serverDone.resolve();
64+
}));
65+
66+
const clientSession = await connect(serverEndpoint.address, {
67+
reuseEndpoint: false,
68+
});
69+
await clientSession.opened;
70+
await setTimeout(100);
71+
await clientSession.close({
72+
code: 2n,
73+
type: 'application',
74+
reason,
75+
});
76+
77+
await serverDone.promise;
78+
await serverEndpoint.close();
79+
}
80+
81+
// Server close exercises the server-specific CONNECTION_CLOSE packet path.
82+
{
83+
const reason = 's'.repeat(kMaxReasonLength + 1);
84+
const expectedReason = reason.slice(0, kMaxReasonLength);
85+
const serverDone = Promise.withResolvers();
86+
87+
const serverEndpoint = await listen(mustCall(async (serverSession) => {
88+
await serverSession.opened;
89+
await setTimeout(100);
90+
await serverSession.close({
91+
code: 3n,
92+
type: 'application',
93+
reason,
94+
});
95+
serverDone.resolve();
96+
}));
97+
98+
const clientSession = await connect(serverEndpoint.address, {
99+
reuseEndpoint: false,
100+
onerror: mustCall((error) => {
101+
assert.strictEqual(error.reason, expectedReason);
102+
}),
103+
});
104+
await clientSession.opened;
105+
await assert.rejects(clientSession.closed, {
106+
code: 'ERR_QUIC_APPLICATION_ERROR',
107+
reason: expectedReason,
108+
});
109+
110+
await serverDone.promise;
111+
await serverEndpoint.close();
112+
}

0 commit comments

Comments
 (0)