From e97b1e8d0ec7bc1cb5c7fd6260952f40860f4df7 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Mon, 26 Feb 2024 15:18:07 +0100 Subject: [PATCH] chore(e2e-tests): account for upstream server TLS option changes MONGOSH-1718 (#1838) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The server will no longer start when TLS is enabled without a CA certificate argument. This does not affect our tests’ functionality, only how we start the server in them. --- packages/e2e-tests/test/e2e-tls.spec.ts | 12 +++++-- packages/e2e-tests/test/test-shell.ts | 47 +++++++++++++++---------- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/packages/e2e-tests/test/e2e-tls.spec.ts b/packages/e2e-tests/test/e2e-tls.spec.ts index 2c79cebb3..36d5aa6b2 100644 --- a/packages/e2e-tests/test/e2e-tls.spec.ts +++ b/packages/e2e-tests/test/e2e-tls.spec.ts @@ -115,6 +115,8 @@ describe('e2e TLS', function () { '--tlsCertificateKeyFile', SERVER_KEY, '--tlsAllowConnectionsWithoutCertificates', + '--tlsCAFile', + CA_CERT, ], }); @@ -184,7 +186,9 @@ describe('e2e TLS', function () { }); const result = await shell.waitForPromptOrExit(); expect(result.state).to.equal('exit'); - shell.assertContainsOutput('unable to verify the first certificate'); + shell.assertContainsOutput( + /unable to verify the first certificate|self[- ]signed certificate in certificate chain/ + ); }); it('fails with invalid CA (connection string)', async function () { @@ -199,7 +203,9 @@ describe('e2e TLS', function () { }); const result = await shell.waitForPromptOrExit(); expect(result.state).to.equal('exit'); - shell.assertContainsOutput('unable to verify the first certificate'); + shell.assertContainsOutput( + /unable to verify the first certificate|self[- ]signed certificate in certificate chain/ + ); }); it('fails when providing a CRL including the servers cert', async function () { @@ -640,6 +646,8 @@ describe('e2e TLS', function () { 'requireTLS', '--tlsCertificateKeyFile', SERVER_INVALIDHOST_KEY, + '--tlsCAFile', + CA_CERT, '--tlsAllowConnectionsWithoutCertificates', ], }); diff --git a/packages/e2e-tests/test/test-shell.ts b/packages/e2e-tests/test/test-shell.ts index 77e67ad30..0d5dfefab 100644 --- a/packages/e2e-tests/test/test-shell.ts +++ b/packages/e2e-tests/test/test-shell.ts @@ -1,8 +1,12 @@ import type Mocha from 'mocha'; import assert from 'assert'; -import type { ChildProcess } from 'child_process'; +import type { + ChildProcess, + ChildProcessWithoutNullStreams, +} from 'child_process'; import { spawn } from 'child_process'; import { once } from 'events'; +import { inspect } from 'util'; import path from 'path'; import stripAnsi from 'strip-ansi'; import { eventually } from '../../../testing/eventually'; @@ -20,6 +24,12 @@ const PROMPT_PATTERN = /^([^<>]*> ?)+$/m; const ERROR_PATTERN_1 = /Thrown:\n([^>]*)/gm; // node <= 12.14 const ERROR_PATTERN_2 = /Uncaught[:\n ]+([^>]*)/gm; +function matches(str: string, pattern: string | RegExp): boolean { + return typeof pattern === 'string' + ? str.includes(pattern) + : pattern.test(str); +} + /** * Test shell helper class. */ @@ -36,7 +46,7 @@ export class TestShell { consumeStdio?: boolean; } = { args: [] } ): TestShell { - let shellProcess: ChildProcess; + let shellProcess: ChildProcessWithoutNullStreams; let env = options.env || process.env; if (options.forceTerminal) { @@ -88,7 +98,7 @@ export class TestShell { static async killall(): Promise { const exitPromises: Promise[] = []; while (TestShell._openShells.length) { - const shell = TestShell._openShells.pop(); + const shell = TestShell._openShells.pop()!; shell.kill(); exitPromises.push(shell.waitForExit()); } @@ -110,13 +120,16 @@ export class TestShell { await TestShell.killall(); } - private _process: ChildProcess; + private _process: ChildProcessWithoutNullStreams; private _output: string; private _rawOutput: string; private _onClose: Promise; - constructor(shellProcess: ChildProcess, consumeStdio = true) { + constructor( + shellProcess: ChildProcessWithoutNullStreams, + consumeStdio = true + ) { this._process = shellProcess; this._output = ''; this._rawOutput = ''; @@ -229,38 +242,34 @@ export class TestShell { } } - assertContainsOutput(expectedOutput: string): void { + assertContainsOutput(expectedOutput: string | RegExp): void { const onlyOutputLines = this._getOutputLines(); - if (!onlyOutputLines.join('\n').includes(expectedOutput)) { + if (!matches(onlyOutputLines.join('\n'), expectedOutput)) { throw new assert.AssertionError({ - message: `Expected shell output to include ${JSON.stringify( - expectedOutput - )}`, + message: `Expected shell output to include ${inspect(expectedOutput)}`, actual: this._output, expected: expectedOutput, }); } } - assertContainsError(expectedError: string): void { + assertContainsError(expectedError: string | RegExp): void { const allErrors = this._getAllErrors(); - if (!allErrors.find((error) => error.includes(expectedError))) { + if (!allErrors.find((error) => matches(error, expectedError))) { throw new assert.AssertionError({ - message: `Expected shell errors to include ${JSON.stringify( - expectedError - )}`, + message: `Expected shell errors to include ${inspect(expectedError)}`, actual: this._output, expected: expectedError, }); } } - assertNotContainsOutput(unexpectedOutput: string): void { + assertNotContainsOutput(unexpectedOutput: string | RegExp): void { const onlyOutputLines = this._getOutputLines(); - if (onlyOutputLines.join('\n').includes(unexpectedOutput)) { + if (matches(onlyOutputLines.join('\n'), unexpectedOutput)) { throw new assert.AssertionError({ - message: `Expected shell output not to include ${JSON.stringify( + message: `Expected shell output not to include ${inspect( unexpectedOutput )}`, actual: this._output, @@ -288,6 +297,6 @@ export class TestShell { if (!match) { return null; } - return match.groups.logId; + return match.groups!.logId; } }