From 2a7f936a7cabacbe9417b2474de3f8209a88185b Mon Sep 17 00:00:00 2001 From: Taylor Mullen Date: Sat, 14 Feb 2026 11:48:17 -0800 Subject: [PATCH] test(rig): refactor cleanDir to use Atomics.wait for reliable sync sleep and increase retries --- packages/test-utils/src/test-rig.ts | 71 +++++++++++++++-------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/packages/test-utils/src/test-rig.ts b/packages/test-utils/src/test-rig.ts index c3e5451499..fdbb316d01 100644 --- a/packages/test-utils/src/test-rig.ts +++ b/packages/test-utils/src/test-rig.ts @@ -363,37 +363,8 @@ export class TestRig { if (!this._initialized) { // Clean up existing directories from previous runs (e.g. retries) - const cleanDir = (dir: string) => { - if (fs.existsSync(dir)) { - for (let i = 0; i < 5; i++) { - try { - fs.rmSync(dir, { recursive: true, force: true }); - return; - } catch (err) { - if (i === 4) { - console.error( - `Failed to clean directory ${dir} after 5 attempts:`, - err, - ); - throw err; - } - const delay = Math.pow(2, i) * 1000; - const sleepCmd = - process.platform === 'win32' - ? `timeout /t ${Math.max(1, Math.floor(delay / 1000))} /nobreak` - : `sleep ${delay / 1000}`; - try { - execSync(sleepCmd, { stdio: 'ignore' }); - } catch { - /* ignore */ - } - } - } - } - }; - - cleanDir(this.testDir); - cleanDir(this.homeDir); + this._cleanDir(this.testDir); + this._cleanDir(this.homeDir); this._initialized = true; } @@ -411,6 +382,36 @@ export class TestRig { this._createSettingsFile(options.settings); } + private _cleanDir(dir: string) { + if (fs.existsSync(dir)) { + for (let i = 0; i < 10; i++) { + try { + fs.rmSync(dir, { recursive: true, force: true }); + return; + } catch (err) { + if (i === 9) { + console.error( + `Failed to clean directory ${dir} after 10 attempts:`, + err, + ); + throw err; + } + const delay = Math.min(Math.pow(2, i) * 1000, 10000); // Max 10s delay + try { + const sharedBuffer = new Int32Array(new SharedArrayBuffer(4)); + Atomics.wait(sharedBuffer, 0, 0, delay); + } catch { + // Fallback for environments where SharedArrayBuffer might be restricted + const start = Date.now(); + while (Date.now() - start < delay) { + /* busy wait */ + } + } + } + } + } + } + private _createSettingsFile(overrideSettings?: Record) { const projectGeminiDir = join(this.testDir!, GEMINI_DIR); mkdirSync(projectGeminiDir, { recursive: true }); @@ -896,21 +897,21 @@ export class TestRig { // Clean up test directory and home directory if (this.testDir && !env['KEEP_OUTPUT']) { try { - fs.rmSync(this.testDir, { recursive: true, force: true }); + this._cleanDir(this.testDir); } catch (error) { // Ignore cleanup errors if (env['VERBOSE'] === 'true' || env['CI'] === 'true') { - console.warn('Cleanup warning:', (error as Error).message); + console.warn('Cleanup warning (testDir):', (error as Error).message); } } } if (this.homeDir && !env['KEEP_OUTPUT']) { try { - fs.rmSync(this.homeDir, { recursive: true, force: true }); + this._cleanDir(this.homeDir); } catch (error) { // Ignore cleanup errors if (env['VERBOSE'] === 'true' || env['CI'] === 'true') { - console.warn('Cleanup warning:', (error as Error).message); + console.warn('Cleanup warning (homeDir):', (error as Error).message); } } }