1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-23 15:16:54 -05:00
denoland-deno/cli/tests/unit/tls_test.ts
Casper Beyer 6abf126c2a
chore: remove std directory (#9361)
This removes the std folder from the tree.

Various parts of the tests are pretty tightly dependent 
on std (47 direct imports and 75 indirect imports, not 
counting the cli tests that use them as fixtures) so I've 
added std as a submodule for now.
2021-02-02 12:05:46 +01:00

378 lines
9.6 KiB
TypeScript

// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
import {
assert,
assertEquals,
assertStrictEquals,
assertThrows,
assertThrowsAsync,
deferred,
unitTest,
} from "./test_util.ts";
import { BufReader, BufWriter } from "../../../test_util/std/io/bufio.ts";
import { TextProtoReader } from "../../../test_util/std/textproto/mod.ts";
const encoder = new TextEncoder();
const decoder = new TextDecoder();
unitTest(async function connectTLSNoPerm(): Promise<void> {
await assertThrowsAsync(async () => {
await Deno.connectTls({ hostname: "github.com", port: 443 });
}, Deno.errors.PermissionDenied);
});
unitTest(async function connectTLSCertFileNoReadPerm(): Promise<void> {
await assertThrowsAsync(async () => {
await Deno.connectTls({
hostname: "github.com",
port: 443,
certFile: "cli/tests/tls/RootCA.crt",
});
}, Deno.errors.PermissionDenied);
});
unitTest(
{ perms: { read: true, net: true } },
function listenTLSNonExistentCertKeyFiles(): void {
const options = {
hostname: "localhost",
port: 3500,
certFile: "cli/tests/tls/localhost.crt",
keyFile: "cli/tests/tls/localhost.key",
};
assertThrows(() => {
Deno.listenTls({
...options,
certFile: "./non/existent/file",
});
}, Deno.errors.NotFound);
assertThrows(() => {
Deno.listenTls({
...options,
keyFile: "./non/existent/file",
});
}, Deno.errors.NotFound);
},
);
unitTest({ perms: { net: true } }, function listenTLSNoReadPerm(): void {
assertThrows(() => {
Deno.listenTls({
hostname: "localhost",
port: 3500,
certFile: "cli/tests/tls/localhost.crt",
keyFile: "cli/tests/tls/localhost.key",
});
}, Deno.errors.PermissionDenied);
});
unitTest(
{
perms: { read: true, write: true, net: true },
},
function listenTLSEmptyKeyFile(): void {
const options = {
hostname: "localhost",
port: 3500,
certFile: "cli/tests/tls/localhost.crt",
keyFile: "cli/tests/tls/localhost.key",
};
const testDir = Deno.makeTempDirSync();
const keyFilename = testDir + "/key.pem";
Deno.writeFileSync(keyFilename, new Uint8Array([]), {
mode: 0o666,
});
assertThrows(() => {
Deno.listenTls({
...options,
keyFile: keyFilename,
});
}, Error);
},
);
unitTest(
{ perms: { read: true, write: true, net: true } },
function listenTLSEmptyCertFile(): void {
const options = {
hostname: "localhost",
port: 3500,
certFile: "cli/tests/tls/localhost.crt",
keyFile: "cli/tests/tls/localhost.key",
};
const testDir = Deno.makeTempDirSync();
const certFilename = testDir + "/cert.crt";
Deno.writeFileSync(certFilename, new Uint8Array([]), {
mode: 0o666,
});
assertThrows(() => {
Deno.listenTls({
...options,
certFile: certFilename,
});
}, Error);
},
);
unitTest(
{ perms: { read: true, net: true } },
async function dialAndListenTLS(): Promise<void> {
const resolvable = deferred();
const hostname = "localhost";
const port = 3500;
const listener = Deno.listenTls({
hostname,
port,
certFile: "cli/tests/tls/localhost.crt",
keyFile: "cli/tests/tls/localhost.key",
});
const response = encoder.encode(
"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n",
);
listener.accept().then(
async (conn): Promise<void> => {
assert(conn.remoteAddr != null);
assert(conn.localAddr != null);
await conn.write(response);
// TODO(bartlomieju): this might be a bug
setTimeout(() => {
conn.close();
resolvable.resolve();
}, 0);
},
);
const conn = await Deno.connectTls({
hostname,
port,
certFile: "cli/tests/tls/RootCA.pem",
});
assert(conn.rid > 0);
const w = new BufWriter(conn);
const r = new BufReader(conn);
const body = `GET / HTTP/1.1\r\nHost: ${hostname}:${port}\r\n\r\n`;
const writeResult = await w.write(encoder.encode(body));
assertEquals(body.length, writeResult);
await w.flush();
const tpr = new TextProtoReader(r);
const statusLine = await tpr.readLine();
assert(statusLine !== null, `line must be read: ${String(statusLine)}`);
const m = statusLine.match(/^(.+?) (.+?) (.+?)$/);
assert(m !== null, "must be matched");
const [_, proto, status, ok] = m;
assertEquals(proto, "HTTP/1.1");
assertEquals(status, "200");
assertEquals(ok, "OK");
const headers = await tpr.readMIMEHeader();
assert(headers !== null);
const contentLength = parseInt(headers.get("content-length")!);
const bodyBuf = new Uint8Array(contentLength);
await r.readFull(bodyBuf);
assertEquals(decoder.decode(bodyBuf), "Hello World\n");
conn.close();
listener.close();
await resolvable;
},
);
async function tlsPair(port: number): Promise<[Deno.Conn, Deno.Conn]> {
const listener = Deno.listenTls({
hostname: "localhost",
port,
certFile: "cli/tests/tls/localhost.crt",
keyFile: "cli/tests/tls/localhost.key",
});
const acceptPromise = listener.accept();
const connectPromise = Deno.connectTls({
hostname: "localhost",
port,
certFile: "cli/tests/tls/RootCA.pem",
});
const connections = await Promise.all([acceptPromise, connectPromise]);
listener.close();
return connections;
}
async function sendCloseWrite(conn: Deno.Conn): Promise<void> {
const buf = new Uint8Array(1024);
let n: number | null;
// Send 1.
n = await conn.write(new Uint8Array([1]));
assertStrictEquals(n, 1);
// Send EOF.
await conn.closeWrite();
// Receive 2.
n = await conn.read(buf);
assertStrictEquals(n, 1);
assertStrictEquals(buf[0], 2);
conn.close();
}
async function receiveCloseWrite(conn: Deno.Conn): Promise<void> {
const buf = new Uint8Array(1024);
let n: number | null;
// Receive 1.
n = await conn.read(buf);
assertStrictEquals(n, 1);
assertStrictEquals(buf[0], 1);
// Receive EOF.
n = await conn.read(buf);
assertStrictEquals(n, null);
// Send 2.
n = await conn.write(new Uint8Array([2]));
assertStrictEquals(n, 1);
conn.close();
}
async function sendAlotReceiveNothing(conn: Deno.Conn): Promise<void> {
// Start receive op.
const readBuf = new Uint8Array(1024);
const readPromise = conn.read(readBuf);
// Send 1 MB of data.
const writeBuf = new Uint8Array(1 << 20);
writeBuf.fill(42);
await conn.write(writeBuf);
// Send EOF.
await conn.closeWrite();
// Close the connection.
conn.close();
// Read op should be canceled.
await assertThrowsAsync(
async () => await readPromise,
Deno.errors.Interrupted,
);
}
async function receiveAlotSendNothing(conn: Deno.Conn): Promise<void> {
const readBuf = new Uint8Array(1024);
let n: number | null;
// Receive 1 MB of data.
for (let nread = 0; nread < 1 << 20; nread += n!) {
n = await conn.read(readBuf);
assertStrictEquals(typeof n, "number");
assert(n! > 0);
assertStrictEquals(readBuf[0], 42);
}
// Close the connection, without sending anything at all.
conn.close();
}
unitTest(
{ perms: { read: true, net: true } },
async function tlsServerStreamHalfClose(): Promise<void> {
const [serverConn, clientConn] = await tlsPair(3501);
await Promise.all([
sendCloseWrite(serverConn),
receiveCloseWrite(clientConn),
]);
},
);
unitTest(
{ perms: { read: true, net: true } },
async function tlsClientStreamHalfClose(): Promise<void> {
const [serverConn, clientConn] = await tlsPair(3502);
await Promise.all([
sendCloseWrite(clientConn),
receiveCloseWrite(serverConn),
]);
},
);
unitTest(
{ perms: { read: true, net: true } },
async function tlsServerStreamCancelRead(): Promise<void> {
const [serverConn, clientConn] = await tlsPair(3503);
await Promise.all([
sendAlotReceiveNothing(serverConn),
receiveAlotSendNothing(clientConn),
]);
},
);
unitTest(
{ perms: { read: true, net: true } },
async function tlsClientStreamCancelRead(): Promise<void> {
const [serverConn, clientConn] = await tlsPair(3504);
await Promise.all([
sendAlotReceiveNothing(clientConn),
receiveAlotSendNothing(serverConn),
]);
},
);
unitTest(
{ perms: { read: true, net: true } },
async function startTls(): Promise<void> {
const hostname = "smtp.gmail.com";
const port = 587;
const encoder = new TextEncoder();
let conn = await Deno.connect({
hostname,
port,
});
let writer = new BufWriter(conn);
let reader = new TextProtoReader(new BufReader(conn));
let line: string | null = (await reader.readLine()) as string;
assert(line.startsWith("220"));
await writer.write(encoder.encode(`EHLO ${hostname}\r\n`));
await writer.flush();
while ((line = (await reader.readLine()) as string)) {
assert(line.startsWith("250"));
if (line.startsWith("250 ")) break;
}
await writer.write(encoder.encode("STARTTLS\r\n"));
await writer.flush();
line = await reader.readLine();
// Received the message that the server is ready to establish TLS
assertEquals(line, "220 2.0.0 Ready to start TLS");
conn = await Deno.startTls(conn, { hostname });
writer = new BufWriter(conn);
reader = new TextProtoReader(new BufReader(conn));
// After that use TLS communication again
await writer.write(encoder.encode(`EHLO ${hostname}\r\n`));
await writer.flush();
while ((line = (await reader.readLine()) as string)) {
assert(line.startsWith("250"));
if (line.startsWith("250 ")) break;
}
conn.close();
},
);