diff options
author | Yoshiya Hinosawa <stibium121@gmail.com> | 2023-02-23 12:27:29 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-23 12:27:29 +0900 |
commit | 3ca23cb642f0320e675ef2d0d51e9eb529171b53 (patch) | |
tree | 434602616b8c30d33d304e35562ae20f1bf2ab7b | |
parent | 93a712fbace4e044ca7dff11209bf83dcb5c6de6 (diff) |
test(ext/node): add tls_test (#17871)
-rw-r--r-- | cli/tests/integration/node_unit_tests.rs | 4 | ||||
-rw-r--r-- | cli/tests/unit_node/tls_test.ts | 122 |
2 files changed, 126 insertions, 0 deletions
diff --git a/cli/tests/integration/node_unit_tests.rs b/cli/tests/integration/node_unit_tests.rs index d29d988ba..d2a6f6ec8 100644 --- a/cli/tests/integration/node_unit_tests.rs +++ b/cli/tests/integration/node_unit_tests.rs @@ -10,6 +10,10 @@ fn node_unit_tests() { .current_dir(util::root_path()) .arg("test") .arg("--unstable") + // TODO(kt3k): This option is required to pass tls_test.ts, + // but this shouldn't be necessary. tls.connect currently doesn't + // pass hostname option correctly and it causes cert errors. + .arg("--unsafely-ignore-certificate-errors") .arg("-A") .arg(util::tests_path().join("unit_node")) .spawn() diff --git a/cli/tests/unit_node/tls_test.ts b/cli/tests/unit_node/tls_test.ts new file mode 100644 index 000000000..79c1e634c --- /dev/null +++ b/cli/tests/unit_node/tls_test.ts @@ -0,0 +1,122 @@ +// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. + +import { + assertEquals, + assertInstanceOf, +} from "../../../test_util/std/testing/asserts.ts"; +import { delay } from "../../../test_util/std/async/delay.ts"; +import { deferred } from "../../../test_util/std/async/deferred.ts"; +import { fromFileUrl, join } from "../../../test_util/std/path/mod.ts"; +import { serveTls } from "../../../test_util/std/http/server.ts"; +import * as tls from "node:tls"; +import * as net from "node:net"; +import * as stream from "node:stream"; + +const tlsTestdataDir = fromFileUrl( + new URL("../testdata/tls", import.meta.url), +); +const keyFile = join(tlsTestdataDir, "localhost.key"); +const certFile = join(tlsTestdataDir, "localhost.crt"); +const key = await Deno.readTextFile(keyFile); +const cert = await Deno.readTextFile(certFile); +const rootCaCert = await Deno.readTextFile(join(tlsTestdataDir, "RootCA.pem")); + +Deno.test("tls.connect makes tls connection", async () => { + const ctl = new AbortController(); + const serve = serveTls(() => new Response("hello"), { + port: 8443, + key, + cert, + signal: ctl.signal, + }); + + await delay(200); + + const conn = tls.connect({ + host: "localhost", + port: 8443, + secureContext: { + ca: rootCaCert, + // deno-lint-ignore no-explicit-any + } as any, + }); + conn.write(`GET / HTTP/1.1 +Host: localhost +Connection: close + +`); + conn.on("data", (chunk) => { + const text = new TextDecoder().decode(chunk); + const bodyText = text.split("\r\n\r\n").at(-1)?.trim(); + assertEquals(bodyText, "hello"); + conn.destroy(); + ctl.abort(); + }); + + await serve; +}); + +Deno.test("tls.createServer creates a TLS server", async () => { + const p = deferred(); + const server = tls.createServer( + // deno-lint-ignore no-explicit-any + { host: "0.0.0.0", key, cert } as any, + (socket: net.Socket) => { + socket.write("welcome!\n"); + socket.setEncoding("utf8"); + socket.pipe(socket).on("data", (data) => { + if (data.toString().trim() === "goodbye") { + socket.destroy(); + } + }); + }, + ); + server.listen(0, async () => { + const conn = await Deno.connectTls({ + hostname: "127.0.0.1", + // deno-lint-ignore no-explicit-any + port: (server.address() as any).port, + caCerts: [rootCaCert], + }); + + const buf = new Uint8Array(100); + await Deno.read(conn.rid, buf); + let text: string; + text = new TextDecoder().decode(buf); + assertEquals(text.replaceAll("\0", ""), "welcome!\n"); + buf.fill(0); + + Deno.write(conn.rid, new TextEncoder().encode("hey\n")); + await Deno.read(conn.rid, buf); + text = new TextDecoder().decode(buf); + assertEquals(text.replaceAll("\0", ""), "hey\n"); + buf.fill(0); + + Deno.write(conn.rid, new TextEncoder().encode("goodbye\n")); + await Deno.read(conn.rid, buf); + text = new TextDecoder().decode(buf); + assertEquals(text.replaceAll("\0", ""), "goodbye\n"); + + conn.close(); + server.close(); + p.resolve(); + }); + await p; +}); + +Deno.test("TLSSocket can construct without options", () => { + // deno-lint-ignore no-explicit-any + new tls.TLSSocket(new stream.PassThrough() as any); +}); + +Deno.test("tlssocket._handle._parentWrap is set", () => { + // Note: This feature is used in popular 'http2-wrapper' module + // https://github.com/szmarczak/http2-wrapper/blob/51eeaf59ff9344fb192b092241bfda8506983620/source/utils/js-stream-socket.js#L6 + const parentWrap = + // deno-lint-ignore no-explicit-any + ((new tls.TLSSocket(new stream.PassThrough() as any, {}) as any) + // deno-lint-ignore no-explicit-any + ._handle as any)! + ._parentWrap; + assertInstanceOf(parentWrap, stream.PassThrough); +}); |