From fd71c75aeea24a4aeac0c8fbf5d6cf4b94aa800d Mon Sep 17 00:00:00 2001 From: "Kamat, Trivikram" <16024985+trivikr@users.noreply.github.com> Date: Wed, 17 Jun 2026 17:57:29 -0700 Subject: [PATCH] test: wait for debugger pause state on startup The debugger helper waited for the initial break by matching the human-readable break banner. On slow systems the CLI can reach the prompt before that banner is observed, causing flaky timeouts. Use setContextLineNumber(2) to probe the debugger CLI state. The command requires a pause state and leaves the default context line setting unchanged. Retry while it reports that execution is not paused. Wait for the probe response and the next prompt together, so later test commands cannot consume probe output. Signed-off-by: Kamat, Trivikram <16024985+trivikr@users.noreply.github.com> Assisted-by: openai:gpt-5.5 --- test/common/debugger.js | 53 ++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/test/common/debugger.js b/test/common/debugger.js index dbaa62e71d3f1c..bbdcea93a92007 100644 --- a/test/common/debugger.js +++ b/test/common/debugger.js @@ -6,6 +6,9 @@ const BREAK_MESSAGE = new RegExp('(?:' + [ 'assert', 'break', 'break on start', 'debugCommand', 'exception', 'other', 'promiseRejection', 'step', ].join('|') + ') in', 'i'); +const NOT_PAUSED_MESSAGE = /requires execution to be paused/i; +const PAUSE_STATE_MESSAGE = + /requires execution to be paused|contextLine has been changed/i; let TIMEOUT = common.platformTimeout(10000); // Some macOS and Windows machines require more time to receive the outputs from the client. @@ -56,7 +59,7 @@ function startCLI(args, flags = [], spawnOpts = {}, opts = { randomPort: true }) return output; }, - waitFor(pattern) { + waitFor(pattern, offset = 0, timeout = TIMEOUT) { function checkPattern(str) { if (Array.isArray(pattern)) { return pattern.every((p) => p.test(str)); @@ -66,9 +69,10 @@ function startCLI(args, flags = [], spawnOpts = {}, opts = { randomPort: true }) return new Promise((resolve, reject) => { function checkOutput() { - if (checkPattern(getOutput())) { + const output = getOutput().slice(offset); + if (checkPattern(output)) { tearDown(); - resolve(); + resolve(output); } } @@ -89,12 +93,12 @@ function startCLI(args, flags = [], spawnOpts = {}, opts = { randomPort: true }) } // Capture stack trace here to show where waitFor was called from when it times out. - const timeoutErr = new Error(`Timeout (${TIMEOUT}) while waiting for ${pattern}`); + const timeoutErr = new Error(`Timeout (${timeout}) while waiting for ${pattern}`); const timer = setTimeout(() => { tearDown(); timeoutErr.output = this.output; reject(timeoutErr); - }, TIMEOUT); + }, timeout); function tearDown() { clearTimeout(timer); @@ -108,16 +112,47 @@ function startCLI(args, flags = [], spawnOpts = {}, opts = { randomPort: true }) }); }, - waitForPrompt() { - return this.waitFor(/>\s+$/); + async waitForPaused() { + const deadline = Date.now() + TIMEOUT; + + function getRemainingTime() { + return deadline - Date.now(); + } + + await this.waitForPrompt(getRemainingTime()); + + while (getRemainingTime() > 0) { + const offset = this.output.length; + this.writeLine('setContextLineNumber(2)', false); + const output = await this.waitFor([ + PAUSE_STATE_MESSAGE, + />\s+$/, + ], offset, getRemainingTime()); + + if (!NOT_PAUSED_MESSAGE.test(output)) { + return; + } + + await new Promise((resolve) => + setTimeout(resolve, Math.min(100, getRemainingTime()))); + } + + const timeoutErr = + new Error(`Timeout (${TIMEOUT}) while waiting for a debugger pause state`); + timeoutErr.output = this.output; + throw timeoutErr; + }, + + waitForPrompt(timeout = TIMEOUT) { + return this.waitFor(/>\s+$/, 0, timeout); }, async waitForInitialBreak() { - await this.waitFor(/break (?:on start )?in/i); + await this.waitForPaused(); if (isPreBreak(this.output)) { await this.command('next', false); - return this.waitFor(/break in/); + await this.waitForPaused(); } },