summaryrefslogtreecommitdiff
path: root/cli/tests/unit
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tests/unit')
-rw-r--r--cli/tests/unit/command_test.ts40
-rw-r--r--cli/tests/unit/files_test.ts27
-rw-r--r--cli/tests/unit/fs_events_test.ts30
-rw-r--r--cli/tests/unit/http_test.ts18
-rw-r--r--cli/tests/unit/kv_test.ts27
-rw-r--r--cli/tests/unit/net_test.ts31
-rw-r--r--cli/tests/unit/serve_test.ts46
7 files changed, 218 insertions, 1 deletions
diff --git a/cli/tests/unit/command_test.ts b/cli/tests/unit/command_test.ts
index 5f56a0c22..299c70b9b 100644
--- a/cli/tests/unit/command_test.ts
+++ b/cli/tests/unit/command_test.ts
@@ -258,6 +258,46 @@ Deno.test(
Deno.test(
{ permissions: { run: true, read: true } },
+ // deno lint bug, see https://github.com/denoland/deno_lint/issues/1206
+ // deno-lint-ignore require-await
+ async function childProcessExplicitResourceManagement() {
+ let dead = undefined;
+ {
+ const command = new Deno.Command(Deno.execPath(), {
+ args: ["eval", "setTimeout(() => {}, 10000)"],
+ stdout: "null",
+ stderr: "null",
+ });
+ await using child = command.spawn();
+ child.status.then(({ signal }) => {
+ dead = signal;
+ });
+ }
+
+ if (Deno.build.os == "windows") {
+ assertEquals(dead, null);
+ } else {
+ assertEquals(dead, "SIGTERM");
+ }
+ },
+);
+
+Deno.test(
+ { permissions: { run: true, read: true } },
+ async function childProcessExplicitResourceManagementManualClose() {
+ const command = new Deno.Command(Deno.execPath(), {
+ args: ["eval", "setTimeout(() => {}, 10000)"],
+ stdout: "null",
+ stderr: "null",
+ });
+ await using child = command.spawn();
+ child.kill("SIGTERM");
+ await child.status;
+ },
+);
+
+Deno.test(
+ { permissions: { run: true, read: true } },
async function commandKillFailed() {
const command = new Deno.Command(Deno.execPath(), {
args: ["eval", "setTimeout(() => {}, 5000)"],
diff --git a/cli/tests/unit/files_test.ts b/cli/tests/unit/files_test.ts
index 873c70c86..3e0390ae6 100644
--- a/cli/tests/unit/files_test.ts
+++ b/cli/tests/unit/files_test.ts
@@ -824,3 +824,30 @@ Deno.test(
assertEquals(res, "hello \uFFFD");
},
);
+
+Deno.test(
+ { permissions: { read: true } },
+ async function fsFileExplicitResourceManagement() {
+ let file2: Deno.FsFile;
+
+ {
+ using file = await Deno.open("cli/tests/testdata/assets/hello.txt");
+ file2 = file;
+
+ const stat = file.statSync();
+ assert(stat.isFile);
+ }
+
+ assertThrows(() => file2.statSync(), Deno.errors.BadResource);
+ },
+);
+
+Deno.test(
+ { permissions: { read: true } },
+ async function fsFileExplicitResourceManagementManualClose() {
+ using file = await Deno.open("cli/tests/testdata/assets/hello.txt");
+ file.close();
+ assertThrows(() => file.statSync(), Deno.errors.BadResource); // definitely closed
+ // calling [Symbol.dispose] after manual close is a no-op
+ },
+);
diff --git a/cli/tests/unit/fs_events_test.ts b/cli/tests/unit/fs_events_test.ts
index 9330f2007..86adeb4d7 100644
--- a/cli/tests/unit/fs_events_test.ts
+++ b/cli/tests/unit/fs_events_test.ts
@@ -107,3 +107,33 @@ Deno.test(
assertEquals(events, []);
},
);
+
+Deno.test(
+ { permissions: { read: true, write: true } },
+ async function watchFsExplicitResourceManagement() {
+ let res;
+ {
+ const testDir = await makeTempDir();
+ using iter = Deno.watchFs(testDir);
+
+ res = iter[Symbol.asyncIterator]().next();
+ }
+
+ const { done } = await res;
+ assert(done);
+ },
+);
+
+Deno.test(
+ { permissions: { read: true, write: true } },
+ async function watchFsExplicitResourceManagementManualClose() {
+ const testDir = await makeTempDir();
+ using iter = Deno.watchFs(testDir);
+
+ const res = iter[Symbol.asyncIterator]().next();
+
+ iter.close();
+ const { done } = await res;
+ assert(done);
+ },
+);
diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts
index 10414cab3..8c7bf9974 100644
--- a/cli/tests/unit/http_test.ts
+++ b/cli/tests/unit/http_test.ts
@@ -2817,6 +2817,24 @@ Deno.test({
},
});
+Deno.test(
+ async function httpConnExplicitResourceManagement() {
+ let promise;
+
+ {
+ const listen = Deno.listen({ port: listenPort });
+ promise = fetch(`http://localhost:${listenPort}/`).catch(() => null);
+ const serverConn = await listen.accept();
+ listen.close();
+
+ using _httpConn = Deno.serveHttp(serverConn);
+ }
+
+ const response = await promise;
+ assertEquals(response, null);
+ },
+);
+
function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
// Based on https://tools.ietf.org/html/rfc2616#section-19.4.6
const tp = new TextProtoReader(r);
diff --git a/cli/tests/unit/kv_test.ts b/cli/tests/unit/kv_test.ts
index 4e3ce5385..0bfc75481 100644
--- a/cli/tests/unit/kv_test.ts
+++ b/cli/tests/unit/kv_test.ts
@@ -2100,3 +2100,30 @@ Deno.test({
db.close();
},
});
+
+Deno.test(
+ { permissions: { read: true } },
+ async function kvExplicitResourceManagement() {
+ let kv2: Deno.Kv;
+
+ {
+ using kv = await Deno.openKv(":memory:");
+ kv2 = kv;
+
+ const res = await kv.get(["a"]);
+ assertEquals(res.versionstamp, null);
+ }
+
+ await assertRejects(() => kv2.get(["a"]), Deno.errors.BadResource);
+ },
+);
+
+Deno.test(
+ { permissions: { read: true } },
+ async function kvExplicitResourceManagementManualClose() {
+ using kv = await Deno.openKv(":memory:");
+ kv.close();
+ await assertRejects(() => kv.get(["a"]), Deno.errors.BadResource);
+ // calling [Symbol.dispose] after manual close is a no-op
+ },
+);
diff --git a/cli/tests/unit/net_test.ts b/cli/tests/unit/net_test.ts
index 2a98b5e26..db99d2480 100644
--- a/cli/tests/unit/net_test.ts
+++ b/cli/tests/unit/net_test.ts
@@ -1242,3 +1242,34 @@ Deno.test({
const listener = Deno.listen({ hostname: "localhost", port: "0" });
listener.close();
});
+
+Deno.test(
+ { permissions: { net: true } },
+ async function listenerExplicitResourceManagement() {
+ let done: Promise<Deno.errors.BadResource>;
+
+ {
+ using listener = Deno.listen({ port: listenPort });
+
+ done = assertRejects(
+ () => listener.accept(),
+ Deno.errors.BadResource,
+ );
+ }
+
+ await done;
+ },
+);
+
+Deno.test(
+ { permissions: { net: true } },
+ async function listenerExplicitResourceManagementManualClose() {
+ using listener = Deno.listen({ port: listenPort });
+ listener.close();
+ await assertRejects( // definitely closed
+ () => listener.accept(),
+ Deno.errors.BadResource,
+ );
+ // calling [Symbol.dispose] after manual close is a no-op
+ },
+);
diff --git a/cli/tests/unit/serve_test.ts b/cli/tests/unit/serve_test.ts
index 2e560af99..9f6bd4aa1 100644
--- a/cli/tests/unit/serve_test.ts
+++ b/cli/tests/unit/serve_test.ts
@@ -48,7 +48,12 @@ function onListen<T>(
async function makeServer(
handler: (req: Request) => Response | Promise<Response>,
): Promise<
- { finished: Promise<void>; abort: () => void; shutdown: () => Promise<void> }
+ {
+ finished: Promise<void>;
+ abort: () => void;
+ shutdown: () => Promise<void>;
+ [Symbol.asyncDispose](): PromiseLike<void>;
+ }
> {
const ac = new AbortController();
const listeningPromise = deferred();
@@ -69,6 +74,9 @@ async function makeServer(
async shutdown() {
await server.shutdown();
},
+ [Symbol.asyncDispose]() {
+ return server[Symbol.asyncDispose]();
+ },
};
}
@@ -297,6 +305,42 @@ Deno.test(
);
Deno.test(
+ { permissions: { net: true, write: true, read: true } },
+ async function httpServerExplicitResourceManagement() {
+ let dataPromise;
+
+ {
+ await using _server = await makeServer(async (_req) => {
+ return new Response((await makeTempFile(1024 * 1024)).readable);
+ });
+
+ const resp = await fetch(`http://localhost:${servePort}`);
+ dataPromise = resp.arrayBuffer();
+ }
+
+ assertEquals((await dataPromise).byteLength, 1048576);
+ },
+);
+
+Deno.test(
+ { permissions: { net: true, write: true, read: true } },
+ async function httpServerExplicitResourceManagementManualClose() {
+ await using server = await makeServer(async (_req) => {
+ return new Response((await makeTempFile(1024 * 1024)).readable);
+ });
+
+ const resp = await fetch(`http://localhost:${servePort}`);
+
+ const [_, data] = await Promise.all([
+ server.shutdown(),
+ resp.arrayBuffer(),
+ ]);
+
+ assertEquals(data.byteLength, 1048576);
+ },
+);
+
+Deno.test(
{ permissions: { read: true, run: true } },
async function httpServerUnref() {
const [statusCode, _output] = await execCode(`