0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-10-31 09:14:20 -04:00
denoland-deno/cli/tests/unit/net_test.ts
Yoshiya Hinosawa 66c5f41c5b
test(cli): refactor the usages of delay (#11098)
This PR refactors the usages of delay utility in js unit testing. The same
utiliy is defined in several places with different names. This PR replaces those
usages with the one provided in std/async/delay.ts to improve the readability
and consistency of test code.
2021-06-25 03:44:14 +02:00

600 lines
17 KiB
TypeScript

// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
import {
assert,
assertEquals,
assertNotEquals,
assertThrows,
assertThrowsAsync,
deferred,
delay,
unitTest,
} 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);
assertNotEquals(listener.rid, 0);
listener.close();
});
unitTest(
{
perms: { net: true },
},
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(
{ ignore: Deno.build.os === "windows", perms: { read: true } },
function netUnixListenWritePermission(): void {
assertThrows(() => {
const filePath = Deno.makeTempFileSync();
const socket = Deno.listen({
path: filePath,
transport: "unix",
});
assert(socket.addr.transport === "unix");
assertEquals(socket.addr.path, filePath);
socket.close();
}, Deno.errors.PermissionDenied);
},
);
unitTest(
{ ignore: Deno.build.os === "windows", perms: { read: true } },
function netUnixPacketListenWritePermission(): void {
assertThrows(() => {
const filePath = Deno.makeTempFileSync();
const socket = Deno.listenDatagram({
path: filePath,
transport: "unixpacket",
});
assert(socket.addr.transport === "unixpacket");
assertEquals(socket.addr.path, filePath);
socket.close();
}, Deno.errors.PermissionDenied);
},
);
unitTest(
{
perms: { net: true },
},
async function netTcpCloseWhileAccept(): Promise<void> {
const listener = Deno.listen({ port: 4501 });
const p = listener.accept();
listener.close();
await assertThrowsAsync(
async (): Promise<void> => {
await p;
},
Deno.errors.BadResource,
"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();
await assertThrowsAsync(
async (): Promise<void> => {
await p;
},
Deno.errors.BadResource,
"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(
{ 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]);
const byteLength = await alice.send(sent, bob.addr);
assertEquals(byteLength, 3);
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(
{ perms: { net: true } },
async function netUdpConcurrentSendReceive(): Promise<void> {
const socket = Deno.listenDatagram({ port: 3500, transport: "udp" });
assert(socket.addr.transport === "udp");
assertEquals(socket.addr.port, 3500);
assertEquals(socket.addr.hostname, "127.0.0.1");
const recvPromise = socket.receive();
const sendBuf = new Uint8Array([1, 2, 3]);
const sendLen = await socket.send(sendBuf, socket.addr);
assertEquals(sendLen, 3);
const [recvBuf, _recvAddr] = await recvPromise;
assertEquals(recvBuf.length, 3);
assertEquals(1, recvBuf[0]);
assertEquals(2, recvBuf[1]);
assertEquals(3, recvBuf[2]);
socket.close();
},
);
unitTest(
{ perms: { net: true } },
async function netUdpBorrowMutError(): Promise<void> {
const socket = Deno.listenDatagram({
port: 4501,
transport: "udp",
});
// Panic happened on second send: BorrowMutError
const a = socket.send(new Uint8Array(), socket.addr);
const b = socket.send(new Uint8Array(), socket.addr);
await Promise.all([a, b]);
socket.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]);
const byteLength = await alice.send(sent, bob.addr);
assertEquals(byteLength, 3);
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();
},
);
// TODO(piscisaureus): Enable after Tokio v0.3/v1.0 upgrade.
unitTest(
{ ignore: true, perms: { read: true, write: true } },
async function netUnixPacketConcurrentSendReceive(): Promise<void> {
const filePath = await Deno.makeTempFile();
const socket = Deno.listenDatagram({
path: filePath,
transport: "unixpacket",
});
assert(socket.addr.transport === "unixpacket");
assertEquals(socket.addr.path, filePath);
const recvPromise = socket.receive();
const sendBuf = new Uint8Array([1, 2, 3]);
const sendLen = await socket.send(sendBuf, socket.addr);
assertEquals(sendLen, 3);
const [recvBuf, _recvAddr] = await recvPromise;
assertEquals(recvBuf.length, 3);
assertEquals(1, recvBuf[0]);
assertEquals(2, recvBuf[1]);
assertEquals(3, recvBuf[2]);
socket.close();
},
);
unitTest(
{ perms: { net: true } },
async function netTcpListenIteratorBreakClosesResource(): Promise<void> {
const promise = deferred();
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 delay(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(
{ 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(
{
perms: { net: true },
},
async function netCloseWriteSuccess() {
const addr = { hostname: "127.0.0.1", port: 3500 };
const listener = Deno.listen(addr);
const closeDeferred = deferred();
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]);
// Verify that the write end of the socket is closed.
// TODO(piscisaureus): assert that thrown error is of a specific type.
await assertThrowsAsync(async () => {
await conn.write(new Uint8Array([1, 2, 3]));
});
closeDeferred.resolve();
listener.close();
conn.close();
},
);
unitTest(
{
perms: { net: true },
},
async function netHangsOnClose() {
let acceptedConn: Deno.Conn;
const resolvable = deferred();
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;
},
);
unitTest(
{
perms: { net: true },
},
function netExplicitUndefinedHostname() {
const listener = Deno.listen({ hostname: undefined, port: 8080 });
assertEquals((listener.addr as Deno.NetAddr).hostname, "0.0.0.0");
listener.close();
},
);