summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
Diffstat (limited to 'cli')
-rw-r--r--cli/dts/lib.deno.ns.d.ts26
-rw-r--r--cli/tests/unit/flock_test.ts102
2 files changed, 128 insertions, 0 deletions
diff --git a/cli/dts/lib.deno.ns.d.ts b/cli/dts/lib.deno.ns.d.ts
index 420a08da4..996aff363 100644
--- a/cli/dts/lib.deno.ns.d.ts
+++ b/cli/dts/lib.deno.ns.d.ts
@@ -787,6 +787,32 @@ declare namespace Deno {
*/
export function fdatasync(rid: number): Promise<void>;
+ /** **UNSTABLE**: New API should be tested first.
+ *
+ * Acquire an advisory file-system lock for the provided file. `exclusive`
+ * defaults to `false`.
+ */
+ export function flock(rid: number, exclusive?: boolean): Promise<void>;
+
+ /** **UNSTABLE**: New API should be tested first.
+ *
+ * Acquire an advisory file-system lock for the provided file. `exclusive`
+ * defaults to `false`.
+ */
+ export function flockSync(rid: number, exclusive?: boolean): void;
+
+ /** **UNSTABLE**: New API should be tested first.
+ *
+ * Release an advisory file-system lock for the provided file.
+ */
+ export function funlock(rid: number): Promise<void>;
+
+ /** **UNSTABLE**: New API should be tested first.
+ *
+ * Release an advisory file-system lock for the provided file.
+ */
+ export function funlockSync(rid: number): void;
+
/** Close the given resource ID (rid) which has been previously opened, such
* as via opening or creating a file. Closing a file when you are finished
* with it is important to avoid leaking resources.
diff --git a/cli/tests/unit/flock_test.ts b/cli/tests/unit/flock_test.ts
new file mode 100644
index 000000000..13d09bcf5
--- /dev/null
+++ b/cli/tests/unit/flock_test.ts
@@ -0,0 +1,102 @@
+// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
+import { assertEquals, unitTest } from "./test_util.ts";
+
+unitTest(
+ { perms: { read: true, run: true, hrtime: true } },
+ async function flockFileSync() {
+ const path = "cli/tests/testdata/fixture.json";
+ const script = (exclusive: boolean, wait: number) => `
+ const { rid } = Deno.openSync("${path}");
+ Deno.flockSync(rid, ${exclusive ? "true" : "false"});
+ await new Promise(res => setTimeout(res, ${wait}));
+ Deno.funlockSync(rid);
+ `;
+ const run = (e: boolean, w: number) =>
+ Deno.run({ cmd: [Deno.execPath(), "eval", "--unstable", script(e, w)] });
+ const firstBlocksSecond = async (
+ first: boolean,
+ second: boolean,
+ ): Promise<boolean> => {
+ const firstPs = run(first, 1000);
+ await new Promise((res) => setTimeout(res, 250));
+ const start = performance.now();
+ const secondPs = run(second, 0);
+ await secondPs.status();
+ const didBlock = (performance.now() - start) > 500;
+ firstPs.close();
+ secondPs.close();
+ return didBlock;
+ };
+
+ assertEquals(
+ await firstBlocksSecond(true, false),
+ true,
+ "exclusive blocks shared",
+ );
+ assertEquals(
+ await firstBlocksSecond(false, true),
+ true,
+ "shared blocks exclusive",
+ );
+ assertEquals(
+ await firstBlocksSecond(true, true),
+ true,
+ "exclusive blocks exclusive",
+ );
+ assertEquals(
+ await firstBlocksSecond(false, false),
+ false,
+ "shared does not block shared",
+ );
+ },
+);
+
+unitTest(
+ { perms: { read: true, run: true, hrtime: true } },
+ async function flockFileAsync() {
+ const path = "cli/tests/testdata/fixture.json";
+ const script = (exclusive: boolean, wait: number) => `
+ const { rid } = await Deno.open("${path}");
+ await Deno.flock(rid, ${exclusive ? "true" : "false"});
+ await new Promise(res => setTimeout(res, ${wait}));
+ await Deno.funlock(rid);
+ `;
+ const run = (e: boolean, w: number) =>
+ Deno.run({ cmd: [Deno.execPath(), "eval", "--unstable", script(e, w)] });
+ const firstBlocksSecond = async (
+ first: boolean,
+ second: boolean,
+ ): Promise<boolean> => {
+ const firstPs = run(first, 1000);
+ await new Promise((res) => setTimeout(res, 250));
+ const start = performance.now();
+ const secondPs = run(second, 0);
+ await secondPs.status();
+ const didBlock = (performance.now() - start) > 500;
+ firstPs.close();
+ secondPs.close();
+ return didBlock;
+ };
+
+ assertEquals(
+ await firstBlocksSecond(true, false),
+ true,
+ "exclusive blocks shared",
+ );
+ assertEquals(
+ await firstBlocksSecond(false, true),
+ true,
+ "shared blocks exclusive",
+ );
+ assertEquals(
+ await firstBlocksSecond(true, true),
+ true,
+ "exclusive blocks exclusive",
+ );
+ assertEquals(
+ await firstBlocksSecond(false, false),
+ false,
+ "shared does not block shared",
+ );
+ },
+);