summaryrefslogtreecommitdiff
path: root/tests/unit/tls_test.ts
diff options
context:
space:
mode:
authorMatt Mastracci <matthew@mastracci.com>2024-04-02 18:36:34 -0600
committerGitHub <noreply@github.com>2024-04-03 00:36:34 +0000
commit57572dafd5218119efb510a5e8a1cc82d4afa92f (patch)
tree69b430d41246ff6c57ff0cda72fa799e078e46f1 /tests/unit/tls_test.ts
parent219a27dde51bf4c04af2d905f71d1cec021ee98e (diff)
chore(tests): rewrite tls_test to avoid any hardcoded ports (#23191)
To avoid the risk of port collisions during tests, we listen on port 0 and use that for both ends of the connections (for any tests we run in this file).
Diffstat (limited to 'tests/unit/tls_test.ts')
-rw-r--r--tests/unit/tls_test.ts218
1 files changed, 92 insertions, 126 deletions
diff --git a/tests/unit/tls_test.ts b/tests/unit/tls_test.ts
index 05fa904b2..84c5e0f30 100644
--- a/tests/unit/tls_test.ts
+++ b/tests/unit/tls_test.ts
@@ -14,14 +14,39 @@ import { TextProtoReader } from "../testdata/run/textproto.ts";
const encoder = new TextEncoder();
const decoder = new TextDecoder();
-const cert = await Deno.readTextFile("tests/testdata/tls/localhost.crt");
-const key = await Deno.readTextFile("tests/testdata/tls/localhost.key");
-const caCerts = [await Deno.readTextFile("tests/testdata/tls/RootCA.pem")];
+const cert = Deno.readTextFileSync("tests/testdata/tls/localhost.crt");
+const key = Deno.readTextFileSync("tests/testdata/tls/localhost.key");
+const caCerts = [Deno.readTextFileSync("tests/testdata/tls/RootCA.pem")];
async function sleep(msec: number) {
await new Promise((res, _rej) => setTimeout(res, msec));
}
+function listenTls(
+ options?: { alpnProtocols?: string[]; reusePort?: boolean },
+): { listener: Deno.TlsListener; port: number; hostname: string } {
+ const tlsOptions = { port: 0, hostname: "localhost", cert, key, ...options };
+ const listener = Deno.listenTls(tlsOptions);
+ return {
+ listener,
+ port: (<Deno.NetAddr> listener.addr).port,
+ hostname: "localhost",
+ };
+}
+
+function listenTcp(): {
+ listener: Deno.Listener;
+ port: number;
+ hostname: string;
+} {
+ const listener = Deno.listen({ port: 0, hostname: "localhost" });
+ return {
+ listener,
+ port: (<Deno.NetAddr> listener.addr).port,
+ hostname: "localhost",
+ };
+}
+
function unreachable(): never {
throw new Error("Unreachable code reached");
}
@@ -59,7 +84,7 @@ Deno.test(
function listenTLSNonExistentCertKeyFiles() {
const options = {
hostname: "localhost",
- port: 3500,
+ port: 0,
certFile: "tests/testdata/tls/localhost.crt",
keyFile: "tests/testdata/tls/localhost.key",
};
@@ -86,7 +111,7 @@ Deno.test(
assertThrows(() => {
Deno.listenTls({
hostname: "localhost",
- port: 3500,
+ port: 0,
certFile: "tests/testdata/tls/localhost.crt",
keyFile: "tests/testdata/tls/localhost.key",
});
@@ -101,7 +126,7 @@ Deno.test(
function listenTLSEmptyKeyFile() {
const options = {
hostname: "localhost",
- port: 3500,
+ port: 0,
certFile: "tests/testdata/tls/localhost.crt",
keyFile: "tests/testdata/tls/localhost.key",
};
@@ -126,7 +151,7 @@ Deno.test(
function listenTLSEmptyCertFile() {
const options = {
hostname: "localhost",
- port: 3500,
+ port: 0,
certFile: "tests/testdata/tls/localhost.crt",
keyFile: "tests/testdata/tls/localhost.key",
};
@@ -149,12 +174,9 @@ Deno.test(
Deno.test(
{ permissions: { net: true } },
async function startTlsWithoutExclusiveAccessToTcpConn() {
- const hostname = "localhost";
- const port = getPort();
-
- const tcpListener = Deno.listen({ hostname, port });
+ const { listener, hostname, port } = listenTcp();
const [serverConn, clientConn] = await Promise.all([
- tcpListener.accept(),
+ listener.accept(),
Deno.connect({ hostname, port }),
]);
@@ -168,7 +190,7 @@ Deno.test(
);
serverConn.close();
- tcpListener.close();
+ listener.close();
await readPromise;
},
);
@@ -177,15 +199,7 @@ Deno.test(
{ permissions: { read: true, net: true } },
async function dialAndListenTLS() {
const { promise, resolve } = Promise.withResolvers<void>();
- const hostname = "localhost";
- const port = 3500;
-
- const listener = Deno.listenTls({
- hostname,
- port,
- cert: await Deno.readTextFile("tests/testdata/tls/localhost.crt"),
- key: await Deno.readTextFile("tests/testdata/tls/localhost.key"),
- });
+ const { listener, port, hostname } = listenTls();
const response = encoder.encode(
"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n",
@@ -232,14 +246,13 @@ Deno.test(
await promise;
},
);
+
Deno.test(
{ permissions: { read: false, net: true } },
async function listenTlsWithCertAndKey() {
const { promise, resolve } = Promise.withResolvers<void>();
- const hostname = "localhost";
- const port = 3500;
- const listener = Deno.listenTls({ hostname, port, cert, key });
+ const { listener, hostname, port } = listenTls();
const response = encoder.encode(
"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n",
@@ -286,23 +299,12 @@ Deno.test(
},
);
-let nextPort = 3501;
-function getPort() {
- return nextPort++;
-}
-
async function tlsPair(): Promise<[Deno.Conn, Deno.Conn]> {
- const port = getPort();
- const listener = Deno.listenTls({
- hostname: "localhost",
- port,
- cert: await Deno.readTextFile("tests/testdata/tls/localhost.crt"),
- key: await Deno.readTextFile("tests/testdata/tls/localhost.key"),
- });
+ const { listener, hostname, port } = listenTls();
const acceptPromise = listener.accept();
const connectPromise = Deno.connectTls({
- hostname: "localhost",
+ hostname,
port,
caCerts: [Deno.readTextFileSync("tests/testdata/tls/RootCA.pem")],
});
@@ -316,12 +318,7 @@ async function tlsPair(): Promise<[Deno.Conn, Deno.Conn]> {
async function tlsAlpn(
useStartTls: boolean,
): Promise<[Deno.TlsConn, Deno.TlsConn]> {
- const port = getPort();
- const listener = Deno.listenTls({
- hostname: "localhost",
- port,
- cert: await Deno.readTextFile("tests/testdata/tls/localhost.crt"),
- key: await Deno.readTextFile("tests/testdata/tls/localhost.key"),
+ const { listener, port } = listenTls({
alpnProtocols: ["deno", "rocks"],
});
@@ -721,33 +718,25 @@ async function tlsWithTcpFailureTestImpl(
failureMode: "corruption" | "shutdown",
reverse: boolean,
) {
- const tlsPort = getPort();
- const tlsListener = Deno.listenTls({
- hostname: "localhost",
- port: tlsPort,
- cert: await Deno.readTextFile("tests/testdata/tls/localhost.crt"),
- key: await Deno.readTextFile("tests/testdata/tls/localhost.key"),
- });
-
- const tcpPort = getPort();
- const tcpListener = Deno.listen({ hostname: "localhost", port: tcpPort });
+ const tls = listenTls();
+ const tcp = listenTcp();
const [tlsServerConn, tcpServerConn] = await Promise.all([
- tlsListener.accept(),
- Deno.connect({ hostname: "localhost", port: tlsPort }),
+ tls.listener.accept(),
+ Deno.connect({ hostname: tls.hostname, port: tls.port }),
]);
const [tcpClientConn, tlsClientConn] = await Promise.all([
- tcpListener.accept(),
+ tcp.listener.accept(),
Deno.connectTls({
- hostname: "localhost",
- port: tcpPort,
+ hostname: tcp.hostname,
+ port: tcp.port,
caCerts: [Deno.readTextFileSync("tests/testdata/tls/RootCA.pem")],
}),
]);
- tlsListener.close();
- tcpListener.close();
+ tls.listener.close();
+ tcp.listener.close();
const {
tlsConn1,
@@ -1013,18 +1002,17 @@ Deno.test(
},
);
-function createHttpsListener(port: number): Deno.Listener {
+function createHttpsListener(): {
+ listener: Deno.TlsListener;
+ hostname: string;
+ port: number;
+} {
// Query format: `curl --insecure https://localhost:8443/z/12345`
// The server returns a response consisting of 12345 times the letter 'z'.
- const listener = Deno.listenTls({
- hostname: "localhost",
- port,
- cert: Deno.readTextFileSync("./tests/testdata/tls/localhost.crt"),
- key: Deno.readTextFileSync("./tests/testdata/tls/localhost.key"),
- });
+ const { listener, hostname, port } = listenTls();
serve(listener);
- return listener;
+ return { listener, hostname, port };
async function serve(listener: Deno.Listener) {
for await (const conn of listener) {
@@ -1085,8 +1073,7 @@ async function curl(url: string): Promise<string> {
Deno.test(
{ permissions: { read: true, net: true, run: true } },
async function curlFakeHttpsServer() {
- const port = getPort();
- const listener = createHttpsListener(port);
+ const { listener, port } = createHttpsListener();
const res1 = await curl(`https://localhost:${port}/d/1`);
assertStrictEquals(res1, "d");
@@ -1166,7 +1153,7 @@ Deno.test(
hostname: "deno.land",
port: 443,
certChain: "bad data",
- privateKey: await Deno.readTextFile(
+ privateKey: Deno.readTextFileSync(
"tests/testdata/tls/localhost.key",
),
});
@@ -1182,7 +1169,7 @@ Deno.test(
hostname: "deno.land",
port: 443,
cert: "bad data",
- key: await Deno.readTextFile(
+ key: Deno.readTextFileSync(
"tests/testdata/tls/localhost.key",
),
});
@@ -1197,7 +1184,7 @@ Deno.test(
await Deno.connectTls({
hostname: "deno.land",
port: 443,
- certChain: await Deno.readTextFile(
+ certChain: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
privateKey: "bad data",
@@ -1213,7 +1200,7 @@ Deno.test(
await Deno.connectTls({
hostname: "deno.land",
port: 443,
- cert: await Deno.readTextFile(
+ cert: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
key: "bad data",
@@ -1229,7 +1216,7 @@ Deno.test(
await Deno.connectTls({
hostname: "deno.land",
port: 443,
- certChain: await Deno.readTextFile(
+ certChain: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
privateKey: "",
@@ -1245,7 +1232,7 @@ Deno.test(
await Deno.connectTls({
hostname: "deno.land",
port: 443,
- cert: await Deno.readTextFile(
+ cert: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
key: "",
@@ -1265,10 +1252,10 @@ Deno.test(
const conn = await Deno.connectTls({
hostname: "localhost",
port: 4552,
- certChain: await Deno.readTextFile(
+ certChain: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
- privateKey: await Deno.readTextFile(
+ privateKey: Deno.readTextFileSync(
"tests/testdata/tls/localhost.key",
),
caCerts: [Deno.readTextFileSync("tests/testdata/tls/RootCA.pem")],
@@ -1290,10 +1277,10 @@ Deno.test(
const conn = await Deno.connectTls({
hostname: "localhost",
port: 4552,
- cert: await Deno.readTextFile(
+ cert: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
- key: await Deno.readTextFile(
+ key: Deno.readTextFileSync(
"tests/testdata/tls/localhost.key",
),
caCerts: [Deno.readTextFileSync("tests/testdata/tls/RootCA.pem")],
@@ -1312,13 +1299,13 @@ Deno.test(
await Deno.connectTls({
hostname: "deno.land",
port: 443,
- cert: await Deno.readTextFile(
+ cert: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
- certChain: await Deno.readTextFile(
+ certChain: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
- key: await Deno.readTextFile(
+ key: Deno.readTextFileSync(
"tests/testdata/tls/localhost.key",
),
});
@@ -1337,13 +1324,13 @@ Deno.test(
await Deno.connectTls({
hostname: "deno.land",
port: 443,
- cert: await Deno.readTextFile(
+ cert: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
- privateKey: await Deno.readTextFile(
+ privateKey: Deno.readTextFileSync(
"tests/testdata/tls/localhost.crt",
),
- key: await Deno.readTextFile(
+ key: Deno.readTextFileSync(
"tests/testdata/tls/localhost.key",
),
});
@@ -1402,15 +1389,8 @@ Deno.test(
Deno.test(
{ permissions: { read: true, net: true } },
async function tlsHandshakeSuccess() {
- const hostname = "localhost";
- const port = getPort();
+ const { listener, hostname, port } = listenTls();
- const listener = Deno.listenTls({
- hostname,
- port,
- cert: await Deno.readTextFile("tests/testdata/tls/localhost.crt"),
- key: await Deno.readTextFile("tests/testdata/tls/localhost.key"),
- });
const acceptPromise = listener.accept();
const connectPromise = Deno.connectTls({
hostname,
@@ -1470,17 +1450,10 @@ Deno.test(
Deno.test(
{ permissions: { read: true, net: true } },
async function tlsHandshakeFailure() {
- const hostname = "localhost";
- const port = getPort();
+ let tls: { listener: Deno.TlsListener; port: number; hostname: string };
async function server() {
- const listener = Deno.listenTls({
- hostname,
- port,
- cert: Deno.readTextFileSync("tests/testdata/tls/localhost.crt"),
- key: Deno.readTextFileSync("tests/testdata/tls/localhost.key"),
- });
- for await (const conn of listener) {
+ for await (const conn of tls.listener) {
for (let i = 0; i < 10; i++) {
// Handshake fails because the client rejects the server certificate.
await assertRejects(
@@ -1495,7 +1468,10 @@ Deno.test(
}
async function connectTlsClient() {
- const conn = await Deno.connectTls({ hostname, port });
+ const conn = await Deno.connectTls({
+ hostname: tls.hostname,
+ port: tls.port,
+ });
// Handshake fails because the server presents a self-signed certificate.
await assertRejects(
() => conn.handshake(),
@@ -1505,10 +1481,14 @@ Deno.test(
conn.close();
}
+ tls = listenTls();
await Promise.all([server(), connectTlsClient()]);
async function startTlsClient() {
- const tcpConn = await Deno.connect({ hostname, port });
+ const tcpConn = await Deno.connect({
+ hostname: tls.hostname,
+ port: tls.port,
+ });
const tlsConn = await Deno.startTls(tcpConn, {
hostname: "foo.land",
caCerts: [Deno.readTextFileSync("tests/testdata/tls/RootCA.pem")],
@@ -1522,6 +1502,7 @@ Deno.test(
tlsConn.close();
}
+ tls = listenTls();
await Promise.all([server(), startTlsClient()]);
},
);
@@ -1530,10 +1511,7 @@ Deno.test(
{ permissions: { net: true } },
async function listenTlsWithReuseAddr() {
const deferred1 = Promise.withResolvers<void>();
- const hostname = "localhost";
- const port = 3500;
-
- const listener1 = Deno.listenTls({ hostname, port, cert, key });
+ const { listener: listener1, port, hostname } = listenTls();
listener1.accept().then((conn) => {
conn.close();
@@ -1564,13 +1542,7 @@ Deno.test({
ignore: Deno.build.os !== "linux",
permissions: { net: true },
}, async function listenTlsReusePort() {
- const hostname = "localhost";
- const port = 4003;
- const listener1 = Deno.listenTls({
- hostname,
- port,
- cert,
- key,
+ const { listener: listener1, port, hostname } = listenTls({
reusePort: true,
});
const listener2 = Deno.listenTls({
@@ -1611,13 +1583,7 @@ Deno.test({
ignore: Deno.build.os === "linux",
permissions: { net: true },
}, function listenTlsReusePortDoesNothing() {
- const hostname = "localhost";
- const port = 4003;
- const listener1 = Deno.listenTls({
- hostname,
- port,
- cert,
- key,
+ const { listener: listener1, hostname, port } = listenTls({
reusePort: true,
});
assertThrows(() => {
@@ -1646,7 +1612,7 @@ Deno.test(
assertThrows(() => {
Deno.listenTls({
hostname: "localhost",
- port: 3500,
+ port: 0,
certFile: "tests/testdata/tls/invalid.crt",
keyFile: "tests/testdata/tls/localhost.key",
});
@@ -1660,7 +1626,7 @@ Deno.test(
assertThrows(() => {
Deno.listenTls({
hostname: "localhost",
- port: 3500,
+ port: 0,
certFile: "tests/testdata/tls/localhost.crt",
keyFile: "tests/testdata/tls/invalid.key",
});