diff --git a/test/common/quic/test-client.mjs b/test/common/quic/test-client.mjs index 1e450e99ed673f..5e837ef5a3af30 100644 --- a/test/common/quic/test-client.mjs +++ b/test/common/quic/test-client.mjs @@ -33,8 +33,8 @@ export default class QuicTestClient { const args = [ address, port, - uri ?? '', ]; + if (uri !== undefined) args.push(uri); this.#runningProcess = spawn(this.#pathToClient, args, options); this.#runningProcess.on('error', (err) => { this.#runningProcess = undefined; diff --git a/test/sequential/test-quic-client-handshake-with-test-server.mjs b/test/sequential/test-quic-client-handshake-with-test-server.mjs new file mode 100644 index 00000000000000..3a484c1f0a7a16 --- /dev/null +++ b/test/sequential/test-quic-client-handshake-with-test-server.mjs @@ -0,0 +1,60 @@ +// Flags: --experimental-quic +import { hasQuic, isAIX, isWindows, skip, getPort } from '../common/index.mjs'; +import { partialDeepStrictEqual } from 'node:assert'; +import { setTimeout } from 'node:timers/promises'; + +if (!hasQuic) { + skip('QUIC support is not enabled'); +} +if (isAIX) { + // AIX does not support some of the networking features used in the ngtcp2 + // example server and client. + skip('QUIC third-party tests are disabled on AIX'); +} +if (isWindows) { + // Windows does not support the [Li/U]nix specific headers and system calls + // required by the ngtcp2 example server/client. + skip('QUIC third-party tests are disabled on Windows'); +} + +// Test that our QUIC client can successfully handshake with the ngtcp2 +// test server (not our implementation). + +const { default: QuicTestServer } = await import('../common/quic/test-server.mjs'); +const { connect } = await import('node:quic'); +const fixtures = await import('../common/fixtures.mjs'); +const kPort = getPort(); + +const server = new QuicTestServer(); +const fixturesPath = fixtures.path(); + +// If this completes without throwing, the test passes. +await server.help({ stdio: 'ignore' }); + +server.run('localhost', kPort, + `${fixturesPath}/keys/agent1-key.pem`, + `${fixturesPath}/keys/agent1-cert.pem`, + { stdio: 'ignore' }); + +const client = await connect({ + host: 'localhost', + port: kPort +}); + +const check = { + servername: 'localhost', + protocol: 'h3', + cipher: 'TLS_AES_128_GCM_SHA256', + cipherVersion: 'TLSv1.3', +}; + +// If the handshake completes without throwing the opened promise +// will be resolved with the basic handshake info. +const info = await client.opened; + +partialDeepStrictEqual(info, check); + +client.close(); + +await setTimeout(100); +server.stop(); diff --git a/test/sequential/test-quic-server-handshake-with-test-client.mjs b/test/sequential/test-quic-server-handshake-with-test-client.mjs new file mode 100644 index 00000000000000..c3e1eb49676ad1 --- /dev/null +++ b/test/sequential/test-quic-server-handshake-with-test-client.mjs @@ -0,0 +1,63 @@ +// Flags: --experimental-quic +import { hasQuic, isAIX, isWindows, skip } from '../common/index.mjs'; +import { partialDeepStrictEqual, ok } from 'node:assert'; +import { setTimeout } from 'node:timers/promises'; + +if (!hasQuic) { + skip('QUIC support is not enabled'); +} +if (isAIX) { + // AIX does not support some of the networking features used in the ngtcp2 + // example server and client. + skip('QUIC third-party tests are disabled on AIX'); +} +if (isWindows) { + // Windows does not support the [Li/U]nix specific headers and system calls + // required by the ngtcp2 example server/client. + skip('QUIC third-party tests are disabled on Windows'); +} + +// Import after the hasQuic check +const { default: QuicTestClient } = await import('../common/quic/test-client.mjs'); +const { listen } = await import('node:quic'); +const { readKey } = await import('../common/fixtures.mjs'); +const { createPrivateKey } = await import('node:crypto'); + +const keys = createPrivateKey(readKey('agent1-key.pem')); +const certs = readKey('agent1-cert.pem'); + +const check = { + // The SNI value + servername: 'localhost', + // The selected ALPN protocol + protocol: 'h3', + // The negotiated cipher suite + cipher: 'TLS_AES_128_GCM_SHA256', + cipherVersion: 'TLSv1.3', +}; + +const serverOpened = Promise.withResolvers(); + +const server = await listen(async (session) => { + // Wrapping in a mustCall is not necessary here since if this + // function is not called the test will time out and fail. + const info = await session.opened; + partialDeepStrictEqual(info, check); + serverOpened.resolve(); + session.destroy(); +}, { keys, certs }); + +// The server must have an address to connect to after listen resolves. +const address = server.address; +ok(address !== undefined); + +const client = new QuicTestClient(); +client.run(address.address, address.port, undefined, { + stdio: 'ignore', +}); + +await serverOpened.promise; + +await setTimeout(100); +client.stop(); +await server.close(); diff --git a/test/parallel/test-quic-test-client.mjs b/test/sequential/test-quic-test-client.mjs similarity index 69% rename from test/parallel/test-quic-test-client.mjs rename to test/sequential/test-quic-test-client.mjs index 921001e84ddc10..ada7037e91ce34 100644 --- a/test/parallel/test-quic-test-client.mjs +++ b/test/sequential/test-quic-test-client.mjs @@ -1,6 +1,5 @@ // Flags: --experimental-quic -import { hasQuic, isAIX, isWindows, skip } from '../common/index.mjs'; -import { rejects } from 'node:assert'; +import { hasQuic, isAIX, isWindows, skip, getPort } from '../common/index.mjs'; if (!hasQuic) { skip('QUIC support is not enabled'); @@ -27,6 +26,4 @@ setTimeout(() => { client.stop(); }, 100); -// We expect this to fail since there's no server running. -await rejects(client.run('localhost', '12345', undefined, { stdio: 'ignore' }), - { message: /Process exited with code 1 and signal null/ }); +await client.run('localhost', getPort(), undefined, { stdio: 'ignore' }); diff --git a/test/parallel/test-quic-test-server.mjs b/test/sequential/test-quic-test-server.mjs similarity index 89% rename from test/parallel/test-quic-test-server.mjs rename to test/sequential/test-quic-test-server.mjs index 0951984b2a708a..4fb56789b14201 100644 --- a/test/parallel/test-quic-test-server.mjs +++ b/test/sequential/test-quic-test-server.mjs @@ -1,5 +1,5 @@ // Flags: --experimental-quic -import { hasQuic, isAIX, isWindows, skip } from '../common/index.mjs'; +import { hasQuic, isAIX, isWindows, skip, getPort } from '../common/index.mjs'; if (!hasQuic) { skip('QUIC support is not enabled'); @@ -28,7 +28,7 @@ setTimeout(() => { server.stop(); }, 100); -await server.run('localhost', '12345', +await server.run('localhost', getPort(), `${fixturesPath}/keys/agent1-key.pem`, `${fixturesPath}/keys/agent1-cert.pem`, { stdio: 'inherit' });