mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
Replaces the `for await (const _ of source) {}` discard idiom with
dump(), which says what it does and does not need an eslint-disable
for the unused loop variable. The eslint-disable directives and
comments that become redundant are removed with it.
Only files that already declare --experimental-stream-iter are
converted, so no test gains an experimental flag it did not already
opt into. Files still using the old idiom are left as they are;
converting them would change what those tests run under and belongs
in a separate discussion.
Loops that break early are left alone: those cancel the source rather
than reading it to completion, which is not what dump() does.
Assisted-by: Claude Opus 5
Signed-off-by: Ethan Arrowood <ethan@arrowood.dev>
PR-URL: https://github.com/nodejs/node/pull/65598
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Tim Perry <pimterry@gmail.com>
112 lines
3.4 KiB
JavaScript
112 lines
3.4 KiB
JavaScript
// Flags: --experimental-quic --experimental-stream-iter --no-warnings
|
|
|
|
// Test: 0-RTT session resumption.
|
|
// First connection receives a session ticket and NEW_TOKEN.
|
|
// Second connection uses both the session ticket and token.
|
|
// The token skips address validation (Retry), the session
|
|
// ticket enables 0-RTT encryption. The client sends data
|
|
// BEFORE the handshake completes (true 0-RTT). The server's
|
|
// onstream fires and the stream's early flag is true.
|
|
|
|
import { hasQuic, skip, mustCall } from '../common/index.mjs';
|
|
import assert from 'node:assert';
|
|
import { dump } from 'node:stream/iter';
|
|
|
|
if (!hasQuic) {
|
|
skip('QUIC is not enabled');
|
|
}
|
|
|
|
const { listen, connect } = await import('../common/quic.mjs');
|
|
const { bytes } = await import('stream/iter');
|
|
|
|
const encoder = new TextEncoder();
|
|
|
|
let savedTicket;
|
|
let savedToken;
|
|
const gotTicket = Promise.withResolvers();
|
|
const gotToken = Promise.withResolvers();
|
|
|
|
let firstStreamEarly;
|
|
let secondStreamEarly;
|
|
const secondStreamDone = Promise.withResolvers();
|
|
|
|
let serverSessionCount = 0;
|
|
const serverEndpoint = await listen(mustCall((serverSession) => {
|
|
const sessionNum = ++serverSessionCount;
|
|
serverSession.onstream = mustCall((stream) =>
|
|
bytes(stream).then((data) => {
|
|
assert.ok(data.byteLength > 0);
|
|
|
|
if (sessionNum === 1) {
|
|
firstStreamEarly = stream.early;
|
|
} else {
|
|
secondStreamEarly = stream.early;
|
|
secondStreamDone.resolve();
|
|
}
|
|
|
|
stream.writer.endSync();
|
|
return stream.closed;
|
|
|
|
}).then(mustCall(() => serverSession.close()))
|
|
);
|
|
}, 2));
|
|
|
|
// --- ZRTT-01: First connection — receive the session ticket and token ---
|
|
const cs1 = await connect(serverEndpoint.address, {
|
|
onsessionticket: mustCall((ticket) => {
|
|
assert.ok(Buffer.isBuffer(ticket));
|
|
assert.ok(ticket.length > 0);
|
|
savedTicket = ticket;
|
|
gotTicket.resolve();
|
|
}, 2),
|
|
onnewtoken: mustCall((token) => {
|
|
assert.ok(Buffer.isBuffer(token));
|
|
assert.ok(token.length > 0);
|
|
savedToken = token;
|
|
gotToken.resolve();
|
|
}),
|
|
});
|
|
|
|
const info1 = await cs1.opened;
|
|
assert.strictEqual(info1.earlyDataAttempted, false);
|
|
assert.strictEqual(info1.earlyDataAccepted, false);
|
|
|
|
await Promise.all([gotTicket.promise, gotToken.promise]);
|
|
|
|
// Send data to verify the connection works.
|
|
const s1 = await cs1.createBidirectionalStream({
|
|
body: encoder.encode('first'),
|
|
});
|
|
await dump(s1);
|
|
await Promise.all([s1.closed, cs1.closed]);
|
|
|
|
// --- ZRTT-02: Second connection — 0-RTT with ticket + token ---
|
|
// The token skips Retry (address validation), the session ticket
|
|
// enables 0-RTT encryption. With the deferred handshake, the
|
|
// stream data is included in the first flight as 0-RTT.
|
|
const cs2 = await connect(serverEndpoint.address, {
|
|
sessionTicket: savedTicket,
|
|
token: savedToken,
|
|
});
|
|
|
|
// Send data BEFORE the handshake completes — true 0-RTT.
|
|
const s2 = await cs2.createBidirectionalStream();
|
|
await s2.writer.write(encoder.encode('early data'));
|
|
|
|
// Now wait for handshake completion.
|
|
const info2 = await cs2.opened;
|
|
assert.strictEqual(info2.earlyDataAttempted, true);
|
|
assert.strictEqual(info2.earlyDataAccepted, true);
|
|
|
|
await s2.writer.end();
|
|
await dump(s2);
|
|
await s2.closed;
|
|
|
|
// Verify the server saw the early data flag.
|
|
await secondStreamDone.promise;
|
|
assert.strictEqual(firstStreamEarly, false);
|
|
assert.strictEqual(secondStreamEarly, true);
|
|
|
|
await cs2.closed;
|
|
await serverEndpoint.close();
|