From 97ee8519ee3f7a08938a65d0679074a7f69d8920 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Tue, 3 Dec 2024 18:50:28 +0100 Subject: [PATCH] fix(e2e-tests): increase timeouts for AWS tests MONGOSH-1924 This should hopefully address AWS auth test flakiness on s390x, where DNS queries can take multiple seconds each due to the host CI setup. --- packages/e2e-tests/test/e2e-aws.spec.ts | 38 +++++++++--- packages/e2e-tests/test/test-shell.ts | 78 ++++++++++++++----------- 2 files changed, 73 insertions(+), 43 deletions(-) diff --git a/packages/e2e-tests/test/e2e-aws.spec.ts b/packages/e2e-tests/test/e2e-aws.spec.ts index 421a723fb..003f7b6c8 100644 --- a/packages/e2e-tests/test/e2e-aws.spec.ts +++ b/packages/e2e-tests/test/e2e-aws.spec.ts @@ -83,7 +83,11 @@ function getConnectionString(username?: string, password?: string): string { } describe('e2e AWS AUTH', function () { - this.timeout(60_000); // AWS auth tests can take longer than the default timeout in CI + // AWS auth tests can take longer than the default timeout in CI + // DNS resolution for many hosts in particular can be time-intensive in some + // CI environments + this.timeout(80_000); + const initialWaitForPromptTimeoutOptions = { timeout: 60_000 }; let expectedAssumedRole: string; before(function () { @@ -128,7 +132,9 @@ describe('e2e AWS AUTH', function () { AWS_SECRET_ACCESS_KEY, ], }); - const result = await shell.waitForPromptOrExit(); + const result = await shell.waitForPromptOrExit( + initialWaitForPromptTimeoutOptions + ); expect(result.state).to.equal('prompt'); const connectionStatus = await shell.executeLine( @@ -150,7 +156,9 @@ describe('e2e AWS AUTH', function () { tokenDetails.token, ], }); - const result = await shell.waitForPromptOrExit(); + const result = await shell.waitForPromptOrExit( + initialWaitForPromptTimeoutOptions + ); expect(result.state).to.equal('prompt'); const connectionStatus = await shell.executeLine( @@ -165,7 +173,9 @@ describe('e2e AWS AUTH', function () { const shell = this.startTestShell({ args: [getConnectionString(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY)], }); - const result = await shell.waitForPromptOrExit(); + const result = await shell.waitForPromptOrExit( + initialWaitForPromptTimeoutOptions + ); expect(result.state).to.equal('prompt'); const connectionStatus = await shell.executeLine( @@ -186,7 +196,9 @@ describe('e2e AWS AUTH', function () { )}`, ], }); - const result = await shell.waitForPromptOrExit(); + const result = await shell.waitForPromptOrExit( + initialWaitForPromptTimeoutOptions + ); expect(result.state).to.equal('prompt'); const connectionStatus = await shell.executeLine( @@ -208,7 +220,9 @@ describe('e2e AWS AUTH', function () { AWS_SECRET_ACCESS_KEY, }, }); - const result = await shell.waitForPromptOrExit(); + const result = await shell.waitForPromptOrExit( + initialWaitForPromptTimeoutOptions + ); expect(result.state).to.equal('prompt'); const connectionStatus = await shell.executeLine( @@ -228,7 +242,9 @@ describe('e2e AWS AUTH', function () { AWS_SESSION_TOKEN: tokenDetails.token, }, }); - const result = await shell.waitForPromptOrExit(); + const result = await shell.waitForPromptOrExit( + initialWaitForPromptTimeoutOptions + ); expect(result.state).to.equal('prompt'); const connectionStatus = await shell.executeLine( @@ -254,7 +270,9 @@ describe('e2e AWS AUTH', function () { AWS_SECRET_ACCESS_KEY: 'invalid', }, }); - const result = await shell.waitForPromptOrExit(); + const result = await shell.waitForPromptOrExit( + initialWaitForPromptTimeoutOptions + ); expect(result.state).to.equal('prompt'); const connectionStatus = await shell.executeLine( @@ -282,7 +300,9 @@ describe('e2e AWS AUTH', function () { AWS_SESSION_TOKEN: 'invalid', }, }); - const result = await shell.waitForPromptOrExit(); + const result = await shell.waitForPromptOrExit( + initialWaitForPromptTimeoutOptions + ); expect(result.state).to.equal('prompt'); const connectionStatus = await shell.executeLine( diff --git a/packages/e2e-tests/test/test-shell.ts b/packages/e2e-tests/test/test-shell.ts index 1420b380d..75e6f23cb 100644 --- a/packages/e2e-tests/test/test-shell.ts +++ b/packages/e2e-tests/test/test-shell.ts @@ -199,40 +199,46 @@ export class TestShell { }); } - async waitForPrompt(start = 0): Promise { - await eventually(() => { - const output = this._output.slice(start); - const lines = output.split('\n'); - const found = !!lines - .filter((l) => PROMPT_PATTERN.exec(l)) // a line that is the prompt must at least match the pattern - .find((l) => { - // in some situations the prompt occurs multiple times in the line (but only in tests!) - const prompts = l - .trim() - .replace(/>$/g, '') - .split('>') - .map((m) => m.trim()); - // if there are multiple prompt parts they must all equal - if (prompts.length > 1) { - for (const p of prompts) { - if (p !== prompts[0]) { - return false; + async waitForPrompt( + start = 0, + opts: { timeout?: number } = {} + ): Promise { + await eventually( + () => { + const output = this._output.slice(start); + const lines = output.split('\n'); + const found = !!lines + .filter((l) => PROMPT_PATTERN.exec(l)) // a line that is the prompt must at least match the pattern + .find((l) => { + // in some situations the prompt occurs multiple times in the line (but only in tests!) + const prompts = l + .trim() + .replace(/>$/g, '') + .split('>') + .map((m) => m.trim()); + // if there are multiple prompt parts they must all equal + if (prompts.length > 1) { + for (const p of prompts) { + if (p !== prompts[0]) { + return false; + } } } - } - return true; - }); - if (!found) { - throw new assert.AssertionError({ - message: 'expected prompt', - expected: PROMPT_PATTERN.toString(), - actual: - this._output.slice(0, start) + - '[prompt search starts here]' + - output, - }); - } - }); + return true; + }); + if (!found) { + throw new assert.AssertionError({ + message: 'expected prompt', + expected: PROMPT_PATTERN.toString(), + actual: + this._output.slice(0, start) + + '[prompt search starts here]' + + output, + }); + } + }, + { ...opts } + ); } waitForExit(): Promise { @@ -248,9 +254,13 @@ export class TestShell { return this.output; } - async waitForPromptOrExit(): Promise { + async waitForPromptOrExit( + opts: { timeout?: number; start?: number } = {} + ): Promise { return Promise.race([ - this.waitForPrompt().then(() => ({ state: 'prompt' } as const)), + this.waitForPrompt(opts.start ?? 0, opts).then( + () => ({ state: 'prompt' } as const) + ), this.waitForExit().then((c) => ({ state: 'exit', exitCode: c } as const)), ]); }