diff options
author | Matt Mastracci <matthew@mastracci.com> | 2024-04-02 18:36:34 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-03 00:36:34 +0000 |
commit | 57572dafd5218119efb510a5e8a1cc82d4afa92f (patch) | |
tree | 69b430d41246ff6c57ff0cda72fa799e078e46f1 /tests/unit/tls_test.ts | |
parent | 219a27dde51bf4c04af2d905f71d1cec021ee98e (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.ts | 218 |
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", }); |