UNPKG

@stryker-mutator/core

Version:

The extendable JavaScript mutation testing framework

87 lines 5.1 kB
import { errorToString } from '@stryker-mutator/util'; import { expect } from 'chai'; import { factory, assertions } from '@stryker-mutator/test-helpers'; import { ChildProcessCrashedError } from '../../../src/child-proxy/child-process-crashed-error.js'; import { OutOfMemoryError } from '../../../src/child-proxy/out-of-memory-error.js'; import { RetryRejectedDecorator } from '../../../src/test-runner/retry-rejected-decorator.js'; import { TestRunnerDecorator } from '../../../src/test-runner/test-runner-decorator.js'; import { currentLogMock } from '../../helpers/log-mock.js'; describe(RetryRejectedDecorator.name, () => { let sut; let testRunner1; let testRunner2; let availableTestRunners; let logMock; const crashedError = new ChildProcessCrashedError(42, ''); beforeEach(() => { testRunner1 = factory.testRunner(); testRunner2 = factory.testRunner(); logMock = currentLogMock(); availableTestRunners = [testRunner1, testRunner2]; sut = new RetryRejectedDecorator(() => { var _a; return (_a = availableTestRunners.shift()) !== null && _a !== void 0 ? _a : factory.testRunner(); }); }); it('should not override `init`', () => { expect(sut.init).to.be.eq(TestRunnerDecorator.prototype.init); }); it('should not override `dispose`', () => { expect(sut.dispose).to.be.eq(TestRunnerDecorator.prototype.dispose); }); describeRun('dryRun', (suite, options) => suite.dryRun(options), () => factory.dryRunOptions({ timeout: 23 }), () => factory.completeDryRunResult()); describeRun('mutantRun', (suite, options) => suite.mutantRun(options), () => factory.mutantRunOptions({ timeout: 23 }), () => factory.survivedMutantRunResult()); function describeRun(runMethod, act, optionsFactory, resultFactory) { describe(runMethod, () => { let options; let expectedResult; beforeEach(() => { options = optionsFactory(); expectedResult = resultFactory(); }); it('should pass through resolved values', async () => { // @ts-expect-error TS isn't smart enough testRunner1[runMethod].resolves(expectedResult); const result = await act(sut, options); expect(testRunner1[runMethod]).to.have.been.calledWith(options); expect(result).to.eq(expectedResult); }); it('should retry on a new test runner if a run is rejected', async () => { testRunner1[runMethod].rejects(new Error('Error')); // @ts-expect-error TS isn't smart enough testRunner2[runMethod].resolves(expectedResult); const result = await act(sut, options); expect(result).to.eq(expectedResult); }); it('should retry if a `ChildProcessCrashedError` occurred reject appears', async () => { testRunner1[runMethod].rejects(crashedError); // @ts-expect-error TS isn't smart enough testRunner2[runMethod].resolves(expectedResult); const result = await act(sut, options); expect(result).to.eq(expectedResult); }); it('should log and retry when an `OutOfMemoryError` occurred.', async () => { testRunner1[runMethod].rejects(new OutOfMemoryError(123, 123)); // @ts-expect-error TS isn't smart enough testRunner2[runMethod].resolves(expectedResult); const result = await act(sut, options); expect(result).to.eq(expectedResult); expect(logMock.info).calledWith("Test runner process [%s] ran out of memory. You probably have a memory leak in your tests. Don't worry, Stryker will restart the process, but you might want to investigate this later, because this decreases performance.", 123); }); it('should dispose a test runner when it rejected, before creating a new one', async () => { testRunner1[runMethod].rejects(crashedError); // @ts-expect-error TS isn't smart enough testRunner2[runMethod].resolves(expectedResult); await act(sut, options); expect(testRunner1.dispose).calledBefore(testRunner2.init); }); it('should retry at most 1 times before rejecting', async () => { const finalError = new Error('foo'); testRunner1[runMethod].rejects(new Error('bar')); testRunner2[runMethod].rejects(finalError); const result = await act(sut, options); assertions.expectErrored(result); expect(result.errorMessage).to.be.deep.eq(`Test runner crashed. Tried twice to restart it without any luck. Last time the error message was: ${errorToString(finalError)}`); expect(availableTestRunners).to.have.lengthOf(0); }); }); } }); //# sourceMappingURL=retry-rejected-decorator.spec.js.map