From 1ff24efd4908fdb9a714881958952017fe39f68e Mon Sep 17 00:00:00 2001 From: David Sherret Date: Tue, 28 Sep 2021 09:34:46 -0400 Subject: [PATCH] chore: ensure first process in shared flock test does not enter and exit lock before second enters --- cli/tests/unit/flock_test.ts | 63 ++++++++++++++++++++++++++---------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/cli/tests/unit/flock_test.ts b/cli/tests/unit/flock_test.ts index 1dc5651396c54a..42873cb0c43d30 100644 --- a/cli/tests/unit/flock_test.ts +++ b/cli/tests/unit/flock_test.ts @@ -49,6 +49,9 @@ async function runFlockTests(opts: { sync: boolean }) { firstExclusive: false, secondExclusive: false, sync: opts.sync, + // need to wait for both to enter the lock to prevent the case where the + // first process enters and exits the lock before the second even enters + waitBothEnteredLock: true, }), false, "shared does not block shared", @@ -59,6 +62,7 @@ async function checkFirstBlocksSecond(opts: { firstExclusive: boolean; secondExclusive: boolean; sync: boolean; + waitBothEnteredLock?: boolean; }) { const firstProcess = runFlockTestProcess({ exclusive: opts.firstExclusive, @@ -71,24 +75,31 @@ async function checkFirstBlocksSecond(opts: { try { const sleep = (time: number) => new Promise((r) => setTimeout(r, time)); - // wait for both processes to signal that they're ready - await Promise.all([firstProcess.waitSignal(), secondProcess.waitSignal()]); + await Promise.all([ + firstProcess.waitStartup(), + secondProcess.waitStartup(), + ]); - // signal to the first process to enter the lock - await firstProcess.signal(); - await firstProcess.waitSignal(); // entering signal - await firstProcess.waitSignal(); // entered signal - // signal the second to enter the lock - await secondProcess.signal(); - await secondProcess.waitSignal(); // entering signal + await firstProcess.enterLock(); + await firstProcess.waitEnterLock(); + + await secondProcess.enterLock(); await sleep(100); - // signal to the first to exit the lock - await firstProcess.signal(); - // collect the final output so we know it's exited the lock + + if (!opts.waitBothEnteredLock) { + await firstProcess.exitLock(); + } + + await secondProcess.waitEnterLock(); + + if (opts.waitBothEnteredLock) { + await firstProcess.exitLock(); + } + + await secondProcess.exitLock(); + + // collect the final output const firstPsTimes = await firstProcess.getTimes(); - // signal to the second to exit the lock - await secondProcess.waitSignal(); // entered signal - await secondProcess.signal(); const secondPsTimes = await secondProcess.getTimes(); return firstPsTimes.exitTime < secondPsTimes.enterTime; } finally { @@ -131,6 +142,9 @@ function runFlockTestProcess(opts: { exclusive: boolean; sync: boolean }) { // release the lock ${opts.sync ? "Deno.funlockSync(rid);" : "await Deno.funlock(rid);"} + // exited signal + Deno.stdout.writeSync(new Uint8Array(1)); + // output the enter and exit time console.log(JSON.stringify({ enterTime, exitTime })); `; @@ -141,9 +155,24 @@ function runFlockTestProcess(opts: { exclusive: boolean; sync: boolean }) { stdin: "piped", }); + const waitSignal = () => process.stdout.read(new Uint8Array(1)); + const signal = () => process.stdin.write(new Uint8Array(1)); + return { - waitSignal: () => process.stdout.read(new Uint8Array(1)), - signal: () => process.stdin.write(new Uint8Array(1)), + async waitStartup() { + await waitSignal(); + }, + async enterLock() { + await signal(); + await waitSignal(); // entering signal + }, + async waitEnterLock() { + await waitSignal(); + }, + async exitLock() { + await signal(); + await waitSignal(); + }, getTimes: async () => { const outputBytes = await readAll(process.stdout); const text = new TextDecoder().decode(outputBytes);