summaryrefslogtreecommitdiff
path: root/cli/tests/unit/net_test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tests/unit/net_test.ts')
-rw-r--r--cli/tests/unit/net_test.ts527
1 files changed, 527 insertions, 0 deletions
diff --git a/cli/tests/unit/net_test.ts b/cli/tests/unit/net_test.ts
new file mode 100644
index 000000000..9e9a1e5e8
--- /dev/null
+++ b/cli/tests/unit/net_test.ts
@@ -0,0 +1,527 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+import {
+ unitTest,
+ assert,
+ assertEquals,
+ createResolvable,
+} from "./test_util.ts";
+
+unitTest({ perms: { net: true } }, function netTcpListenClose(): void {
+ const listener = Deno.listen({ hostname: "127.0.0.1", port: 3500 });
+ assert(listener.addr.transport === "tcp");
+ assertEquals(listener.addr.hostname, "127.0.0.1");
+ assertEquals(listener.addr.port, 3500);
+ listener.close();
+});
+
+unitTest(
+ {
+ perms: { net: true },
+ // TODO:
+ ignore: Deno.build.os === "windows",
+ },
+ function netUdpListenClose(): void {
+ const socket = Deno.listenDatagram({
+ hostname: "127.0.0.1",
+ port: 3500,
+ transport: "udp",
+ });
+ assert(socket.addr.transport === "udp");
+ assertEquals(socket.addr.hostname, "127.0.0.1");
+ assertEquals(socket.addr.port, 3500);
+ socket.close();
+ }
+);
+
+unitTest(
+ { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
+ function netUnixListenClose(): void {
+ const filePath = Deno.makeTempFileSync();
+ const socket = Deno.listen({
+ path: filePath,
+ transport: "unix",
+ });
+ assert(socket.addr.transport === "unix");
+ assertEquals(socket.addr.path, filePath);
+ socket.close();
+ }
+);
+
+unitTest(
+ { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
+ function netUnixPacketListenClose(): void {
+ const filePath = Deno.makeTempFileSync();
+ const socket = Deno.listenDatagram({
+ path: filePath,
+ transport: "unixpacket",
+ });
+ assert(socket.addr.transport === "unixpacket");
+ assertEquals(socket.addr.path, filePath);
+ socket.close();
+ }
+);
+
+unitTest(
+ {
+ perms: { net: true },
+ },
+ async function netTcpCloseWhileAccept(): Promise<void> {
+ const listener = Deno.listen({ port: 4501 });
+ const p = listener.accept();
+ listener.close();
+ let err;
+ try {
+ await p;
+ } catch (e) {
+ err = e;
+ }
+ assert(!!err);
+ assert(err instanceof Error);
+ assertEquals(err.message, "Listener has been closed");
+ }
+);
+
+unitTest(
+ { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
+ async function netUnixCloseWhileAccept(): Promise<void> {
+ const filePath = await Deno.makeTempFile();
+ const listener = Deno.listen({
+ path: filePath,
+ transport: "unix",
+ });
+ const p = listener.accept();
+ listener.close();
+ let err;
+ try {
+ await p;
+ } catch (e) {
+ err = e;
+ }
+ assert(!!err);
+ assert(err instanceof Error);
+ assertEquals(err.message, "Listener has been closed");
+ }
+);
+
+unitTest(
+ { perms: { net: true } },
+ async function netTcpConcurrentAccept(): Promise<void> {
+ const listener = Deno.listen({ port: 4502 });
+ let acceptErrCount = 0;
+ const checkErr = (e: Error): void => {
+ if (e.message === "Listener has been closed") {
+ assertEquals(acceptErrCount, 1);
+ } else if (e.message === "Another accept task is ongoing") {
+ acceptErrCount++;
+ } else {
+ throw new Error("Unexpected error message");
+ }
+ };
+ const p = listener.accept().catch(checkErr);
+ const p1 = listener.accept().catch(checkErr);
+ await Promise.race([p, p1]);
+ listener.close();
+ await Promise.all([p, p1]);
+ assertEquals(acceptErrCount, 1);
+ }
+);
+
+// TODO(jsouto): Enable when tokio updates mio to v0.7!
+unitTest(
+ { ignore: true, perms: { read: true, write: true } },
+ async function netUnixConcurrentAccept(): Promise<void> {
+ const filePath = await Deno.makeTempFile();
+ const listener = Deno.listen({ transport: "unix", path: filePath });
+ let acceptErrCount = 0;
+ const checkErr = (e: Error): void => {
+ if (e.message === "Listener has been closed") {
+ assertEquals(acceptErrCount, 1);
+ } else if (e.message === "Another accept task is ongoing") {
+ acceptErrCount++;
+ } else {
+ throw new Error("Unexpected error message");
+ }
+ };
+ const p = listener.accept().catch(checkErr);
+ const p1 = listener.accept().catch(checkErr);
+ await Promise.race([p, p1]);
+ listener.close();
+ await [p, p1];
+ assertEquals(acceptErrCount, 1);
+ }
+);
+
+unitTest({ perms: { net: true } }, async function netTcpDialListen(): Promise<
+ void
+> {
+ const listener = Deno.listen({ port: 3500 });
+ listener.accept().then(
+ async (conn): Promise<void> => {
+ assert(conn.remoteAddr != null);
+ assert(conn.localAddr.transport === "tcp");
+ assertEquals(conn.localAddr.hostname, "127.0.0.1");
+ assertEquals(conn.localAddr.port, 3500);
+ await conn.write(new Uint8Array([1, 2, 3]));
+ conn.close();
+ }
+ );
+
+ const conn = await Deno.connect({ hostname: "127.0.0.1", port: 3500 });
+ assert(conn.remoteAddr.transport === "tcp");
+ assertEquals(conn.remoteAddr.hostname, "127.0.0.1");
+ assertEquals(conn.remoteAddr.port, 3500);
+ assert(conn.localAddr != null);
+ const buf = new Uint8Array(1024);
+ const readResult = await conn.read(buf);
+ assertEquals(3, readResult);
+ assertEquals(1, buf[0]);
+ assertEquals(2, buf[1]);
+ assertEquals(3, buf[2]);
+ assert(conn.rid > 0);
+
+ assert(readResult !== null);
+
+ const readResult2 = await conn.read(buf);
+ assertEquals(readResult2, null);
+
+ listener.close();
+ conn.close();
+});
+
+unitTest(
+ { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
+ async function netUnixDialListen(): Promise<void> {
+ const filePath = await Deno.makeTempFile();
+ const listener = Deno.listen({ path: filePath, transport: "unix" });
+ listener.accept().then(
+ async (conn): Promise<void> => {
+ assert(conn.remoteAddr != null);
+ assert(conn.localAddr.transport === "unix");
+ assertEquals(conn.localAddr.path, filePath);
+ await conn.write(new Uint8Array([1, 2, 3]));
+ conn.close();
+ }
+ );
+ const conn = await Deno.connect({ path: filePath, transport: "unix" });
+ assert(conn.remoteAddr.transport === "unix");
+ assertEquals(conn.remoteAddr.path, filePath);
+ assert(conn.remoteAddr != null);
+ const buf = new Uint8Array(1024);
+ const readResult = await conn.read(buf);
+ assertEquals(3, readResult);
+ assertEquals(1, buf[0]);
+ assertEquals(2, buf[1]);
+ assertEquals(3, buf[2]);
+ assert(conn.rid > 0);
+
+ assert(readResult !== null);
+
+ const readResult2 = await conn.read(buf);
+ assertEquals(readResult2, null);
+
+ listener.close();
+ conn.close();
+ }
+);
+
+unitTest(
+ { ignore: Deno.build.os === "windows", perms: { net: true } },
+ async function netUdpSendReceive(): Promise<void> {
+ const alice = Deno.listenDatagram({ port: 3500, transport: "udp" });
+ assert(alice.addr.transport === "udp");
+ assertEquals(alice.addr.port, 3500);
+ assertEquals(alice.addr.hostname, "127.0.0.1");
+
+ const bob = Deno.listenDatagram({ port: 4501, transport: "udp" });
+ assert(bob.addr.transport === "udp");
+ assertEquals(bob.addr.port, 4501);
+ assertEquals(bob.addr.hostname, "127.0.0.1");
+
+ const sent = new Uint8Array([1, 2, 3]);
+ await alice.send(sent, bob.addr);
+
+ const [recvd, remote] = await bob.receive();
+ assert(remote.transport === "udp");
+ assertEquals(remote.port, 3500);
+ assertEquals(recvd.length, 3);
+ assertEquals(1, recvd[0]);
+ assertEquals(2, recvd[1]);
+ assertEquals(3, recvd[2]);
+ alice.close();
+ bob.close();
+ }
+);
+
+unitTest(
+ { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
+ async function netUnixPacketSendReceive(): Promise<void> {
+ const filePath = await Deno.makeTempFile();
+ const alice = Deno.listenDatagram({
+ path: filePath,
+ transport: "unixpacket",
+ });
+ assert(alice.addr.transport === "unixpacket");
+ assertEquals(alice.addr.path, filePath);
+
+ const bob = Deno.listenDatagram({
+ path: filePath,
+ transport: "unixpacket",
+ });
+ assert(bob.addr.transport === "unixpacket");
+ assertEquals(bob.addr.path, filePath);
+
+ const sent = new Uint8Array([1, 2, 3]);
+ await alice.send(sent, bob.addr);
+
+ const [recvd, remote] = await bob.receive();
+ assert(remote.transport === "unixpacket");
+ assertEquals(remote.path, filePath);
+ assertEquals(recvd.length, 3);
+ assertEquals(1, recvd[0]);
+ assertEquals(2, recvd[1]);
+ assertEquals(3, recvd[2]);
+ alice.close();
+ bob.close();
+ }
+);
+
+unitTest(
+ { perms: { net: true } },
+ async function netTcpListenIteratorBreakClosesResource(): Promise<void> {
+ const promise = createResolvable();
+
+ async function iterate(listener: Deno.Listener): Promise<void> {
+ let i = 0;
+
+ for await (const conn of listener) {
+ conn.close();
+ i++;
+
+ if (i > 1) {
+ break;
+ }
+ }
+
+ promise.resolve();
+ }
+
+ const addr = { hostname: "127.0.0.1", port: 8888 };
+ const listener = Deno.listen(addr);
+ iterate(listener);
+
+ await new Promise((resolve: () => void, _) => {
+ setTimeout(resolve, 100);
+ });
+ const conn1 = await Deno.connect(addr);
+ conn1.close();
+ const conn2 = await Deno.connect(addr);
+ conn2.close();
+
+ await promise;
+ }
+);
+
+unitTest(
+ { perms: { net: true } },
+ async function netTcpListenCloseWhileIterating(): Promise<void> {
+ const listener = Deno.listen({ port: 8000 });
+ const nextWhileClosing = listener[Symbol.asyncIterator]().next();
+ listener.close();
+ assertEquals(await nextWhileClosing, { value: undefined, done: true });
+
+ const nextAfterClosing = listener[Symbol.asyncIterator]().next();
+ assertEquals(await nextAfterClosing, { value: undefined, done: true });
+ }
+);
+
+unitTest(
+ { ignore: Deno.build.os === "windows", perms: { net: true } },
+ async function netUdpListenCloseWhileIterating(): Promise<void> {
+ const socket = Deno.listenDatagram({ port: 8000, transport: "udp" });
+ const nextWhileClosing = socket[Symbol.asyncIterator]().next();
+ socket.close();
+ assertEquals(await nextWhileClosing, { value: undefined, done: true });
+
+ const nextAfterClosing = socket[Symbol.asyncIterator]().next();
+ assertEquals(await nextAfterClosing, { value: undefined, done: true });
+ }
+);
+
+unitTest(
+ { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
+ async function netUnixListenCloseWhileIterating(): Promise<void> {
+ const filePath = Deno.makeTempFileSync();
+ const socket = Deno.listen({ path: filePath, transport: "unix" });
+ const nextWhileClosing = socket[Symbol.asyncIterator]().next();
+ socket.close();
+ assertEquals(await nextWhileClosing, { value: undefined, done: true });
+
+ const nextAfterClosing = socket[Symbol.asyncIterator]().next();
+ assertEquals(await nextAfterClosing, { value: undefined, done: true });
+ }
+);
+
+unitTest(
+ { ignore: Deno.build.os === "windows", perms: { read: true, write: true } },
+ async function netUnixPacketListenCloseWhileIterating(): Promise<void> {
+ const filePath = Deno.makeTempFileSync();
+ const socket = Deno.listenDatagram({
+ path: filePath,
+ transport: "unixpacket",
+ });
+ const nextWhileClosing = socket[Symbol.asyncIterator]().next();
+ socket.close();
+ assertEquals(await nextWhileClosing, { value: undefined, done: true });
+
+ const nextAfterClosing = socket[Symbol.asyncIterator]().next();
+ assertEquals(await nextAfterClosing, { value: undefined, done: true });
+ }
+);
+
+unitTest(
+ {
+ // FIXME(bartlomieju)
+ ignore: true,
+ perms: { net: true },
+ },
+ async function netListenAsyncIterator(): Promise<void> {
+ const addr = { hostname: "127.0.0.1", port: 3500 };
+ const listener = Deno.listen(addr);
+ const runAsyncIterator = async (): Promise<void> => {
+ for await (const conn of listener) {
+ await conn.write(new Uint8Array([1, 2, 3]));
+ conn.close();
+ }
+ };
+ runAsyncIterator();
+ const conn = await Deno.connect(addr);
+ const buf = new Uint8Array(1024);
+ const readResult = await conn.read(buf);
+ assertEquals(3, readResult);
+ assertEquals(1, buf[0]);
+ assertEquals(2, buf[1]);
+ assertEquals(3, buf[2]);
+ assert(conn.rid > 0);
+
+ assert(readResult !== null);
+
+ const readResult2 = await conn.read(buf);
+ assertEquals(readResult2, null);
+
+ listener.close();
+ conn.close();
+ }
+);
+
+unitTest(
+ {
+ // FIXME(bartlomieju)
+ ignore: true,
+ perms: { net: true },
+ },
+ async function netCloseWriteSuccess() {
+ const addr = { hostname: "127.0.0.1", port: 3500 };
+ const listener = Deno.listen(addr);
+ const closeDeferred = createResolvable();
+ listener.accept().then(async (conn) => {
+ await conn.write(new Uint8Array([1, 2, 3]));
+ await closeDeferred;
+ conn.close();
+ });
+ const conn = await Deno.connect(addr);
+ conn.closeWrite(); // closing write
+ const buf = new Uint8Array(1024);
+ // Check read not impacted
+ const readResult = await conn.read(buf);
+ assertEquals(3, readResult);
+ assertEquals(1, buf[0]);
+ assertEquals(2, buf[1]);
+ assertEquals(3, buf[2]);
+ // Check write should be closed
+ let err;
+ try {
+ await conn.write(new Uint8Array([1, 2, 3]));
+ } catch (e) {
+ err = e;
+ }
+ assert(!!err);
+ assert(err instanceof Deno.errors.BrokenPipe);
+ closeDeferred.resolve();
+ listener.close();
+ conn.close();
+ }
+);
+
+unitTest(
+ {
+ // FIXME(bartlomieju)
+ ignore: true,
+ perms: { net: true },
+ },
+ async function netDoubleCloseWrite() {
+ const addr = { hostname: "127.0.0.1", port: 3500 };
+ const listener = Deno.listen(addr);
+ const closeDeferred = createResolvable();
+ listener.accept().then(async (conn) => {
+ await closeDeferred;
+ conn.close();
+ });
+ const conn = await Deno.connect(addr);
+ conn.closeWrite(); // closing write
+ let err;
+ try {
+ // Duplicated close should throw error
+ conn.closeWrite();
+ } catch (e) {
+ err = e;
+ }
+ assert(!!err);
+ assert(err instanceof Deno.errors.NotConnected);
+ closeDeferred.resolve();
+ listener.close();
+ conn.close();
+ }
+);
+
+unitTest(
+ {
+ perms: { net: true },
+ },
+ async function netHangsOnClose() {
+ let acceptedConn: Deno.Conn;
+ const resolvable = createResolvable();
+
+ async function iteratorReq(listener: Deno.Listener): Promise<void> {
+ const p = new Uint8Array(10);
+ const conn = await listener.accept();
+ acceptedConn = conn;
+
+ try {
+ while (true) {
+ const nread = await conn.read(p);
+ if (nread === null) {
+ break;
+ }
+ await conn.write(new Uint8Array([1, 2, 3]));
+ }
+ } catch (err) {
+ assert(!!err);
+ assert(err instanceof Deno.errors.BadResource);
+ }
+
+ resolvable.resolve();
+ }
+
+ const addr = { hostname: "127.0.0.1", port: 3500 };
+ const listener = Deno.listen(addr);
+ iteratorReq(listener);
+ const conn = await Deno.connect(addr);
+ await conn.write(new Uint8Array([1, 2, 3, 4]));
+ const buf = new Uint8Array(10);
+ await conn.read(buf);
+ conn!.close();
+ acceptedConn!.close();
+ listener.close();
+ await resolvable;
+ }
+);