Skip to content

Commit 8253f1c

Browse files
committed
test: add test for QUIC handshake against test client/server
1 parent 10df38a commit 8253f1c

File tree

5 files changed

+128
-8
lines changed

5 files changed

+128
-8
lines changed

test/common/quic/test-client.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ export default class QuicTestClient {
3333
const args = [
3434
address,
3535
port,
36-
uri ?? '',
3736
];
37+
if (uri !== undefined) args.push(uri);
3838
this.#runningProcess = spawn(this.#pathToClient, args, options);
3939
this.#runningProcess.on('error', (err) => {
4040
this.#runningProcess = undefined;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Flags: --experimental-quic
2+
import { hasQuic, isAIX, isWindows, skip, getPort } from '../common/index.mjs';
3+
import { partialDeepStrictEqual } from 'node:assert';
4+
import { setTimeout } from 'node:timers/promises';
5+
6+
if (!hasQuic) {
7+
skip('QUIC support is not enabled');
8+
}
9+
if (isAIX) {
10+
// AIX does not support some of the networking features used in the ngtcp2
11+
// example server and client.
12+
skip('QUIC third-party tests are disabled on AIX');
13+
}
14+
if (isWindows) {
15+
// Windows does not support the [Li/U]nix specific headers and system calls
16+
// required by the ngtcp2 example server/client.
17+
skip('QUIC third-party tests are disabled on Windows');
18+
}
19+
20+
// Test that our QUIC client can successfully handshake with the ngtcp2
21+
// test server (not our implementation).
22+
23+
const { default: QuicTestServer } = await import('../common/quic/test-server.mjs');
24+
const { connect } = await import('node:quic');
25+
const fixtures = await import('../common/fixtures.mjs');
26+
const kPort = getPort();
27+
28+
const server = new QuicTestServer();
29+
const fixturesPath = fixtures.path();
30+
31+
// If this completes without throwing, the test passes.
32+
await server.help({ stdio: 'ignore' });
33+
34+
server.run('localhost', kPort,
35+
`${fixturesPath}/keys/agent1-key.pem`,
36+
`${fixturesPath}/keys/agent1-cert.pem`,
37+
{ stdio: 'ignore' });
38+
39+
const client = await connect({
40+
host: 'localhost',
41+
port: kPort
42+
});
43+
44+
const check = {
45+
servername: 'localhost',
46+
protocol: 'h3',
47+
cipher: 'TLS_AES_128_GCM_SHA256',
48+
cipherVersion: 'TLSv1.3',
49+
};
50+
51+
// If the handshake completes without throwing the opened promise
52+
// will be resolved with the basic handshake info.
53+
const info = await client.opened;
54+
55+
partialDeepStrictEqual(info, check);
56+
57+
client.close();
58+
59+
await setTimeout(100);
60+
server.stop();
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Flags: --experimental-quic
2+
import { hasQuic, isAIX, isWindows, skip } from '../common/index.mjs';
3+
import { partialDeepStrictEqual, ok } from 'node:assert';
4+
import { setTimeout } from 'node:timers/promises';
5+
6+
if (!hasQuic) {
7+
skip('QUIC support is not enabled');
8+
}
9+
if (isAIX) {
10+
// AIX does not support some of the networking features used in the ngtcp2
11+
// example server and client.
12+
skip('QUIC third-party tests are disabled on AIX');
13+
}
14+
if (isWindows) {
15+
// Windows does not support the [Li/U]nix specific headers and system calls
16+
// required by the ngtcp2 example server/client.
17+
skip('QUIC third-party tests are disabled on Windows');
18+
}
19+
20+
// Import after the hasQuic check
21+
const { default: QuicTestClient } = await import('../common/quic/test-client.mjs');
22+
const { listen } = await import('node:quic');
23+
const { readKey } = await import('../common/fixtures.mjs');
24+
const { createPrivateKey } = await import('node:crypto');
25+
26+
const keys = createPrivateKey(readKey('agent1-key.pem'));
27+
const certs = readKey('agent1-cert.pem');
28+
29+
const check = {
30+
// The SNI value
31+
servername: 'localhost',
32+
// The selected ALPN protocol
33+
protocol: 'h3',
34+
// The negotiated cipher suite
35+
cipher: 'TLS_AES_128_GCM_SHA256',
36+
cipherVersion: 'TLSv1.3',
37+
};
38+
39+
const serverOpened = Promise.withResolvers();
40+
41+
const server = await listen(async (session) => {
42+
// Wrapping in a mustCall is not necessary here since if this
43+
// function is not called the test will time out and fail.
44+
const info = await session.opened;
45+
partialDeepStrictEqual(info, check);
46+
serverOpened.resolve();
47+
session.destroy();
48+
}, { keys, certs });
49+
50+
// The server must have an address to connect to after listen resolves.
51+
const address = server.address;
52+
ok(address !== undefined);
53+
54+
const client = new QuicTestClient();
55+
client.run(address.address, address.port, undefined, {
56+
stdio: 'ignore',
57+
});
58+
59+
await serverOpened.promise;
60+
61+
await setTimeout(100);
62+
client.stop();
63+
await server.close();

test/parallel/test-quic-test-client.mjs renamed to test/sequential/test-quic-test-client.mjs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Flags: --experimental-quic
2-
import { hasQuic, isAIX, isWindows, skip } from '../common/index.mjs';
3-
import { rejects } from 'node:assert';
2+
import { hasQuic, isAIX, isWindows, skip, getPort } from '../common/index.mjs';
43

54
if (!hasQuic) {
65
skip('QUIC support is not enabled');
@@ -27,6 +26,4 @@ setTimeout(() => {
2726
client.stop();
2827
}, 100);
2928

30-
// We expect this to fail since there's no server running.
31-
await rejects(client.run('localhost', '12345', undefined, { stdio: 'ignore' }),
32-
{ message: /Process exited with code 1 and signal null/ });
29+
await client.run('localhost', getPort(), undefined, { stdio: 'ignore' });

test/parallel/test-quic-test-server.mjs renamed to test/sequential/test-quic-test-server.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Flags: --experimental-quic
2-
import { hasQuic, isAIX, isWindows, skip } from '../common/index.mjs';
2+
import { hasQuic, isAIX, isWindows, skip, getPort } from '../common/index.mjs';
33

44
if (!hasQuic) {
55
skip('QUIC support is not enabled');
@@ -28,7 +28,7 @@ setTimeout(() => {
2828
server.stop();
2929
}, 100);
3030

31-
await server.run('localhost', '12345',
31+
await server.run('localhost', getPort(),
3232
`${fixturesPath}/keys/agent1-key.pem`,
3333
`${fixturesPath}/keys/agent1-cert.pem`,
3434
{ stdio: 'inherit' });

0 commit comments

Comments
 (0)