diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/dts/lib.deno.ns.d.ts | 26 | ||||
-rw-r--r-- | cli/tests/unit/flock_test.ts | 102 |
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", + ); + }, +); |