-
Notifications
You must be signed in to change notification settings - Fork 84
chore(e2e-tests): force wait for initialization before writing input #2600
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -20,6 +20,16 @@ type SignalType = ChildProcess extends { kill: (signal: infer T) => any } | |||||||||
| ? T | ||||||||||
| : never; | ||||||||||
|
|
||||||||||
| export interface TestShellInputOptions { | ||||||||||
| end?: boolean; | ||||||||||
| requireFinishedInitialization?: boolean; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| export interface TestShellWaitForPromptOptions { | ||||||||||
| timeout?: number; | ||||||||||
| promptPattern?: RegExp; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| // Assume that prompt strings are those that end in '> ' but do not contain | ||||||||||
| // < or > (so that e.g. '- <repl>' in a stack trace is not considered a prompt). | ||||||||||
| const PROMPT_PATTERN = /^([^<>]*> ?)+$/m; | ||||||||||
|
|
@@ -152,6 +162,7 @@ export class TestShell { | |||||||||
| private _output: string; | ||||||||||
| private _rawOutput: string; | ||||||||||
| private _onClose: Promise<number>; | ||||||||||
| private _initializationKnownToBeFinished = false; | ||||||||||
|
|
||||||||||
| constructor( | ||||||||||
| shellProcess: ChildProcessWithoutNullStreams, | ||||||||||
|
|
@@ -205,11 +216,14 @@ export class TestShell { | |||||||||
| }); | ||||||||||
| } | ||||||||||
| }); | ||||||||||
| // Not technically true, but in practice the patterns we wait for | ||||||||||
| // are sufficient to indicate that initialization is done. | ||||||||||
| this._initializationKnownToBeFinished = true; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| async waitForPrompt( | ||||||||||
| start = 0, | ||||||||||
| opts: { timeout?: number; promptPattern?: RegExp } = {} | ||||||||||
| opts: TestShellWaitForPromptOptions = {} | ||||||||||
| ): Promise<void> { | ||||||||||
| await eventually( | ||||||||||
| () => { | ||||||||||
|
|
@@ -247,10 +261,13 @@ export class TestShell { | |||||||||
| }, | ||||||||||
| { ...opts } | ||||||||||
| ); | ||||||||||
| this._initializationKnownToBeFinished = true; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| waitForAnyExit(): Promise<number> { | ||||||||||
| return this._onClose; | ||||||||||
| async waitForAnyExit(): Promise<number> { | ||||||||||
| const code = await this._onClose; | ||||||||||
| this._initializationKnownToBeFinished = true; | ||||||||||
| return code; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| async waitForSuccessfulExit(): Promise<void> { | ||||||||||
|
|
@@ -267,7 +284,7 @@ export class TestShell { | |||||||||
| } | ||||||||||
|
|
||||||||||
| async waitForPromptOrExit( | ||||||||||
| opts: { timeout?: number; start?: number } = {} | ||||||||||
| opts: TestShellWaitForPromptOptions & { start?: number } = {} | ||||||||||
| ): Promise<TestShellStartupResult> { | ||||||||||
| return Promise.race([ | ||||||||||
| this.waitForPrompt(opts.start ?? 0, opts).then( | ||||||||||
|
|
@@ -283,21 +300,29 @@ export class TestShell { | |||||||||
| this._process.kill(signal); | ||||||||||
| } | ||||||||||
|
|
||||||||||
| writeInput(chars: string, { end = false } = {}): void { | ||||||||||
| writeInput( | ||||||||||
| chars: string, | ||||||||||
| { | ||||||||||
| end = false, | ||||||||||
| requireFinishedInitialization = true, | ||||||||||
| }: TestShellInputOptions = {} | ||||||||||
| ): void { | ||||||||||
| if (requireFinishedInitialization && !this._initializationKnownToBeFinished) | ||||||||||
| throw new Error('Wait for shell to be initialized before writing input'); | ||||||||||
|
||||||||||
| throw new Error('Wait for shell to be initialized before writing input'); | |
| throw new Error( | |
| "Cannot write input before shell initialization completes. Call waitForPrompt(), waitForLine(), or waitForAnyExit() first, or set requireFinishedInitialization to false." | |
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any strong feelings? I imagine anybody getting this error would look up the logic where it's being thrown (i.e. the code), so I'd personally am okay with leaning towards brevity, but I also don't care too deeply
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah don't mind either way either.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure this is what causes failures like https://spruce.mongodb.com/task/mongosh_e2e_tests_macos_14_e2e_tests_darwin_patch_3c88417f1acaedf70850dfbc09675eb011a1f9db_692dafff12de3c00077a3431_25_12_01_15_10_57/logs?execution=0