From ff6962abfcfa1f15bd6ba88c7316dbc36a63129a Mon Sep 17 00:00:00 2001 From: Nico Jansen Date: Tue, 3 Oct 2017 09:07:23 +0200 Subject: [PATCH] fix(sandbox): Prevent hanging child processes (#402) * Rename `SandboxCoordinator` -> `SandboxPool` * Make sure newly created sandboxes are also disposed if the SandboxPool is already disposed fixes #396 --- packages/stryker/src/Sandbox.ts | 10 +- .../{SandboxCoordinator.ts => SandboxPool.ts} | 25 ++- .../src/process/InitialTestExecutor.ts | 3 +- .../src/process/MutationTestExecutor.ts | 4 +- ...xCoordinatorSpec.ts => SandboxPoolSpec.ts} | 47 ++--- packages/stryker/test/unit/SandboxSpec.ts | 182 +++++++++--------- .../unit/process/InitialTestExecutorSpec.ts | 7 +- .../unit/process/MutationTestExecutorSpec.ts | 22 +-- 8 files changed, 154 insertions(+), 146 deletions(-) rename packages/stryker/src/{SandboxCoordinator.ts => SandboxPool.ts} (67%) rename packages/stryker/test/unit/{SandboxCoordinatorSpec.ts => SandboxPoolSpec.ts} (66%) diff --git a/packages/stryker/src/Sandbox.ts b/packages/stryker/src/Sandbox.ts index 53004f7cab..22a577da2c 100644 --- a/packages/stryker/src/Sandbox.ts +++ b/packages/stryker/src/Sandbox.ts @@ -29,7 +29,7 @@ export default class Sandbox { private workingFolder: string; private testHooksFile = path.resolve('___testHooksForStryker.js'); - constructor(private options: Config, private index: number, files: ReadonlyArray, private testFramework: TestFramework | null, private coverageInstrumenter: CoverageInstrumenter | null) { + private constructor(private options: Config, private index: number, files: ReadonlyArray, private testFramework: TestFramework | null, private coverageInstrumenter: CoverageInstrumenter | null) { this.workingFolder = TempFolder.instance().createRandomFolder('sandbox'); log.debug('Creating a sandbox for files in %s', this.workingFolder); this.files = files.slice(); // Create a copy @@ -46,11 +46,17 @@ export default class Sandbox { } } - public async initialize(): Promise { + private async initialize(): Promise { await this.fillSandbox(); return this.initializeTestRunner(); } + public static create(options: Config, index: number, files: ReadonlyArray, testFramework: TestFramework | null, coverageInstrumenter: CoverageInstrumenter | null) + : Promise { + const sandbox = new Sandbox(options, index, files, testFramework, coverageInstrumenter); + return sandbox.initialize().then(() => sandbox); + } + public run(timeout: number): Promise { return this.testRunner.run({ timeout }); } diff --git a/packages/stryker/src/SandboxCoordinator.ts b/packages/stryker/src/SandboxPool.ts similarity index 67% rename from packages/stryker/src/SandboxCoordinator.ts rename to packages/stryker/src/SandboxPool.ts index bef21a4800..f69e5cf4d3 100644 --- a/packages/stryker/src/SandboxCoordinator.ts +++ b/packages/stryker/src/SandboxPool.ts @@ -6,10 +6,11 @@ import { File } from 'stryker-api/core'; import { TestFramework } from 'stryker-api/test_framework'; import Sandbox from './Sandbox'; -export default class SandboxCoordinator { +export default class SandboxPool { - private readonly log = getLogger(SandboxCoordinator.name); + private readonly log = getLogger(SandboxPool.name); private readonly sandboxes: Sandbox[] = []; + private isDisposed: boolean = false; constructor(private options: Config, private testFramework: TestFramework | null, private initialFiles: File[]) { } @@ -29,19 +30,27 @@ export default class SandboxCoordinator { numConcurrentRunners = 1; } this.log.info(`Creating ${numConcurrentRunners} test runners (based on ${numConcurrentRunnersSource})`); + const sandboxes = Observable.range(0, numConcurrentRunners) - .map(n => new Sandbox(this.options, n, this.initialFiles, this.testFramework, null)) - .flatMap(sandbox => sandbox.initialize() - .then(() => sandbox)) - .do(sandbox => this.registerSandbox(sandbox)); + .flatMap(n => this.registerSandbox(Sandbox.create(this.options, n, this.initialFiles, this.testFramework, null))); return sandboxes; } - private registerSandbox(sandbox: Sandbox) { - this.sandboxes.push(sandbox); + private registerSandbox(promisedSandbox: Promise): Promise { + return promisedSandbox.then(sandbox => { + if (this.isDisposed) { + // This sandbox is too late for the party. Dispose it to prevent hanging child processes + // See issue #396 + sandbox.dispose(); + } else { + this.sandboxes.push(sandbox); + } + return sandbox; + }); } public disposeAll() { + this.isDisposed = true; return Promise.all(this.sandboxes.map(sandbox => sandbox.dispose())); } } diff --git a/packages/stryker/src/process/InitialTestExecutor.ts b/packages/stryker/src/process/InitialTestExecutor.ts index a22f408b90..2b4f7eb1cf 100644 --- a/packages/stryker/src/process/InitialTestExecutor.ts +++ b/packages/stryker/src/process/InitialTestExecutor.ts @@ -57,8 +57,7 @@ export default class InitialTestExecutor { throw new Error(`Could not transpile input files: ${transpileResult.error}`); } else { this.logTranspileResult(transpileResult); - const sandbox = new Sandbox(this.options, 0, transpileResult.outputFiles, this.testFramework, this.coverageInstrumenter); - await sandbox.initialize(); + const sandbox = await Sandbox.create(this.options, 0, transpileResult.outputFiles, this.testFramework, this.coverageInstrumenter); const runResult = await sandbox.run(INITIAL_RUN_TIMEOUT); await sandbox.dispose(); return { runResult, transpiledFiles: transpileResult.outputFiles }; diff --git a/packages/stryker/src/process/MutationTestExecutor.ts b/packages/stryker/src/process/MutationTestExecutor.ts index a6e1d9f2dc..cad347a9fb 100644 --- a/packages/stryker/src/process/MutationTestExecutor.ts +++ b/packages/stryker/src/process/MutationTestExecutor.ts @@ -9,7 +9,7 @@ import TranspiledMutant from '../TranspiledMutant'; import StrictReporter from '../reporters/StrictReporter'; import TestableMutant from '../TestableMutant'; import MutantTranspiler from '../transpiler/MutantTranspiler'; -import SandboxCoordinator from '../SandboxCoordinator'; +import SandboxPool from '../SandboxPool'; export default class MutationTestExecutor { @@ -18,7 +18,7 @@ export default class MutationTestExecutor { } async run(allMutants: TestableMutant[]): Promise { - const sandboxPool = new SandboxCoordinator(this.config, this.testFramework, this.transpiledFiles); + const sandboxPool = new SandboxPool(this.config, this.testFramework, this.transpiledFiles); const mutantTranspiler = new MutantTranspiler(this.config); await mutantTranspiler.initialize(this.inputFiles); const result = await this.runInsideSandboxes( diff --git a/packages/stryker/test/unit/SandboxCoordinatorSpec.ts b/packages/stryker/test/unit/SandboxPoolSpec.ts similarity index 66% rename from packages/stryker/test/unit/SandboxCoordinatorSpec.ts rename to packages/stryker/test/unit/SandboxPoolSpec.ts index 8ae73940f3..bb656b4228 100644 --- a/packages/stryker/test/unit/SandboxCoordinatorSpec.ts +++ b/packages/stryker/test/unit/SandboxPoolSpec.ts @@ -2,15 +2,14 @@ import { File } from 'stryker-api/core'; import * as os from 'os'; import { expect } from 'chai'; import { Config } from 'stryker-api/config'; -import SandboxCoordinator from '../../src/SandboxCoordinator'; +import SandboxPool from '../../src/SandboxPool'; import { TestFramework } from 'stryker-api/test_framework'; import { Mock, mock, testFramework, textFile, config } from '../helpers/producers'; -import * as strykerSandbox from '../../src/Sandbox'; import Sandbox from '../../src/Sandbox'; import '../helpers/globals'; -describe('SandboxCoordinator', () => { - let sut: SandboxCoordinator; +describe('SandboxPool', () => { + let sut: SandboxPool; let firstSandbox: Mock; let secondSandbox: Mock; let options: Config; @@ -23,50 +22,44 @@ describe('SandboxCoordinator', () => { expectedTestFramework = testFramework(); coverageInstrumenter = 'a coverage instrumenter'; firstSandbox = mock(Sandbox); - firstSandbox.initialize.resolves(); firstSandbox.dispose.resolves(); secondSandbox = mock(Sandbox); - secondSandbox.initialize.resolves(); secondSandbox.dispose.resolves(); - const genericSandboxForAllSubsequentCallsToNewSandbox = mock(Sandbox); - genericSandboxForAllSubsequentCallsToNewSandbox.initialize.resolves(); + const genericSandboxForAllSubsequentCallsToNewSandbox = mock(Sandbox); genericSandboxForAllSubsequentCallsToNewSandbox.dispose.resolves(); - global.sandbox.stub(strykerSandbox, 'default') - .returns(genericSandboxForAllSubsequentCallsToNewSandbox) - .onCall(0).returns(firstSandbox) - .onCall(1).returns(secondSandbox); + global.sandbox.stub(Sandbox, 'create') + .resolves(genericSandboxForAllSubsequentCallsToNewSandbox) + .onCall(0).resolves(firstSandbox) + .onCall(1).resolves(secondSandbox); expectedInputFiles = [textFile()]; - sut = new SandboxCoordinator(options, expectedTestFramework, expectedInputFiles); + sut = new SandboxPool(options, expectedTestFramework, expectedInputFiles); }); describe('streamSandboxes', () => { it('should use maxConcurrentTestRunners when set', async () => { options.maxConcurrentTestRunners = 1; await sut.streamSandboxes().toArray().toPromise(); - expect(strykerSandbox.default).calledWithNew; - expect(strykerSandbox.default).to.have.callCount(1); - expect(strykerSandbox.default).calledWith(options, 0, expectedInputFiles, expectedTestFramework, null); + expect(Sandbox.create).to.have.callCount(1); + expect(Sandbox.create).calledWith(options, 0, expectedInputFiles, expectedTestFramework, null); }); it('should use cpuCount when maxConcurrentTestRunners is set too high', async () => { global.sandbox.stub(os, 'cpus').returns([1, 2, 3]); // stub 3 cpus options.maxConcurrentTestRunners = 100; const actual = await sut.streamSandboxes().toArray().toPromise(); - expect(strykerSandbox.default).calledWithNew; expect(actual).lengthOf(3); - expect(strykerSandbox.default).to.have.callCount(3); - expect(strykerSandbox.default).calledWith(options, 0, expectedInputFiles, expectedTestFramework, null); + expect(Sandbox.create).to.have.callCount(3); + expect(Sandbox.create).calledWith(options, 0, expectedInputFiles, expectedTestFramework, null); }); it('should use the cpuCount when maxConcurrentTestRunners is <= 0', async () => { global.sandbox.stub(os, 'cpus').returns([1, 2, 3]); // stub 3 cpus options.maxConcurrentTestRunners = 0; const actual = await sut.streamSandboxes().toArray().toPromise(); - expect(strykerSandbox.default).calledWithNew; - expect(strykerSandbox.default).to.have.callCount(3); + expect(Sandbox.create).to.have.callCount(3); expect(actual).lengthOf(3); - expect(strykerSandbox.default).calledWith(options, 0, expectedInputFiles, expectedTestFramework, null); + expect(Sandbox.create).calledWith(options, 0, expectedInputFiles, expectedTestFramework, null); }); it('should use the cpuCount - 1 when a transpiler is configured', async () => { @@ -74,9 +67,17 @@ describe('SandboxCoordinator', () => { options.maxConcurrentTestRunners = 2; global.sandbox.stub(os, 'cpus').returns([1, 2]); // stub 2 cpus const actual = await sut.streamSandboxes().toArray().toPromise(); - expect(strykerSandbox.default).to.have.callCount(1); + expect(Sandbox.create).to.have.callCount(1); expect(actual).lengthOf(1); }); + + // see https://github.com/stryker-mutator/stryker/issues/396 + it('should dispose the newly created sandboxes if the sandbox pool is already disposed', async () => { + await sut.disposeAll(); + const actualSandboxes = await sut.streamSandboxes().toArray().toPromise(); + actualSandboxes.forEach(actual => expect(actual.dispose).called); + expect(actualSandboxes).to.have.length.greaterThan(0); + }); }); describe('dispose', () => { it('should have disposed all sandboxes', async () => { diff --git a/packages/stryker/test/unit/SandboxSpec.ts b/packages/stryker/test/unit/SandboxSpec.ts index 914483947f..ee61408caa 100644 --- a/packages/stryker/test/unit/SandboxSpec.ts +++ b/packages/stryker/test/unit/SandboxSpec.ts @@ -71,12 +71,13 @@ describe('Sandbox', () => { hooksForTestRun: sinon.stub().returns('jsm.filter()') }; coverageInstrumenter.instrumenterStreamForFile.returns(expectedInstrumenterStream); - sut = new Sandbox(options, 3, files, testFrameworkStub, coverageInstrumenter); }); - describe('when initialize()', () => { + describe('when create()', () => { - beforeEach(() => sut.initialize()); + beforeEach(async () => { + sut = await Sandbox.create(options, 3, files, testFrameworkStub, coverageInstrumenter); + }); it('should have instrumented the input files', () => { expect(coverageInstrumenter.instrumenterStreamForFile).calledWith(expectedFileToMutate); @@ -111,124 +112,119 @@ describe('Sandbox', () => { describe('when constructed with a testFramework but without a CoverageInstrumenter', () => { - beforeEach(() => sut = new Sandbox(options, 3, files, testFrameworkStub, null)); + beforeEach(async () => { + sut = await Sandbox.create(options, 3, files, testFrameworkStub, null); + }); it('should have created a workingFolder', () => { expect(TempFolder.instance().createRandomFolder).to.have.been.calledWith('sandbox'); }); - describe('when initialized()', () => { + it('should have copied the input files', () => { + expect(fileUtils.writeFile).calledWith(expectedTargetFileToMutate, textFiles[0].content); + expect(fileUtils.writeFile).calledWith(path.join(workingFolder, 'file2'), textFiles[1].content); + }); - beforeEach(() => sut.initialize()); + it('should have created the isolated test runner without framework hook', () => { + const expectedSettings: IsolatedRunnerOptions = { + files: [ + fileDescriptor({ name: expectedTestFrameworkHooksFile, mutated: false, included: true, transpiled: false }), + fileDescriptor({ name: expectedTargetFileToMutate, mutated: true, included: true }), + fileDescriptor({ name: path.join(workingFolder, 'file2'), mutated: false, included: false }), + fileDescriptor({ name: webFileUrl, mutated: false, included: true, kind: FileKind.Web, transpiled: false }) + ], + port: 46, + strykerOptions: options, + sandboxWorkingFolder: workingFolder + }; + expect(ResilientTestRunnerFactory.create).calledWith(options.testRunner, expectedSettings); + }); - it('should have copied the input files', () => { - expect(fileUtils.writeFile).calledWith(expectedTargetFileToMutate, textFiles[0].content); - expect(fileUtils.writeFile).calledWith(path.join(workingFolder, 'file2'), textFiles[1].content); - }); + describe('when run', () => { + it('should run the testRunner', () => sut.run(231313).then(() => expect(testRunner.run).to.have.been.calledWith({ timeout: 231313 }))); + }); - it('should have created the isolated test runner without framework hook', () => { - const expectedSettings: IsolatedRunnerOptions = { - files: [ - fileDescriptor({ name: expectedTestFrameworkHooksFile, mutated: false, included: true, transpiled: false }), - fileDescriptor({ name: expectedTargetFileToMutate, mutated: true, included: true }), - fileDescriptor({ name: path.join(workingFolder, 'file2'), mutated: false, included: false }), - fileDescriptor({ name: webFileUrl, mutated: false, included: true, kind: FileKind.Web, transpiled: false }) - ], - port: 46, - strykerOptions: options, - sandboxWorkingFolder: workingFolder - }; - expect(ResilientTestRunnerFactory.create).calledWith(options.testRunner, expectedSettings); + describe('when runMutant()', () => { + let transpiledMutant: TranspiledMutant; + let actualRunResult: RunResult; + let mutant: Mutant; + let sourceFile: SourceFile; + const testFilterCodeFragment = 'Some code fragment'; + + beforeEach(() => { + mutant = createMutant({ fileName: expectedFileToMutate.name, replacement: 'mutated', range: [0, 8] }); + sourceFile = new SourceFile(textFile({ content: 'original code' })); + + const testableMutant = new TestableMutant( + mutant, + new SourceFile(textFile({ content: 'original code' }))); + testableMutant.addTestResult(1, testResult({ timeSpentMs: 10 })); + testableMutant.addTestResult(2, testResult({ timeSpentMs: 2 })); + transpiledMutant = new TranspiledMutant(testableMutant, { + error: null, + outputFiles: [textFile({ name: expectedFileToMutate.name, content: 'mutated code' })] + }); + testFrameworkStub.filter.returns(testFilterCodeFragment); }); - describe('when run', () => { - it('should run the testRunner', () => sut.run(231313).then(() => expect(testRunner.run).to.have.been.calledWith({ timeout: 231313 }))); - }); + describe('when mutant has scopedTestIds', () => { - describe('when runMutant()', () => { - let transpiledMutant: TranspiledMutant; - let actualRunResult: RunResult; - let mutant: Mutant; - let sourceFile: SourceFile; - const testFilterCodeFragment = 'Some code fragment'; - - beforeEach(() => { - mutant = createMutant({ fileName: expectedFileToMutate.name, replacement: 'mutated', range: [0, 8] }); - sourceFile = new SourceFile(textFile({ content: 'original code' })); - - const testableMutant = new TestableMutant( - mutant, - new SourceFile(textFile({ content: 'original code' }))); - testableMutant.addTestResult(1, testResult({ timeSpentMs: 10 })); - testableMutant.addTestResult(2, testResult({ timeSpentMs: 2 })); - transpiledMutant = new TranspiledMutant(testableMutant, { - error: null, - outputFiles: [textFile({ name: expectedFileToMutate.name, content: 'mutated code' })] - }); - testFrameworkStub.filter.returns(testFilterCodeFragment); + beforeEach(async () => { + actualRunResult = await sut.runMutant(transpiledMutant); }); - describe('when mutant has scopedTestIds', () => { - - beforeEach(async () => { - actualRunResult = await sut.runMutant(transpiledMutant); - }); - - it('should save the mutant to disk', () => { - expect(fileUtils.writeFile).to.have.been.calledWith(expectedTargetFileToMutate, 'mutated code'); - }); + it('should save the mutant to disk', () => { + expect(fileUtils.writeFile).to.have.been.calledWith(expectedTargetFileToMutate, 'mutated code'); + }); - it('should filter the scoped tests', () => { - expect(testFrameworkStub.filter).to.have.been.calledWith(transpiledMutant.mutant.scopedTestIds); - }); + it('should filter the scoped tests', () => { + expect(testFrameworkStub.filter).to.have.been.calledWith(transpiledMutant.mutant.scopedTestIds); + }); - it('should write the filter code fragment to hooks file', () => { - expect(fileUtils.writeFile).calledWith(expectedTestFrameworkHooksFile, wrapInClosure(testFilterCodeFragment)); - }); + it('should write the filter code fragment to hooks file', () => { + expect(fileUtils.writeFile).calledWith(expectedTestFrameworkHooksFile, wrapInClosure(testFilterCodeFragment)); + }); - it('should have ran testRunner with correct timeout', () => { - expect(testRunner.run).calledWith({ timeout: 12 * 23 + 1000 }); - }); + it('should have ran testRunner with correct timeout', () => { + expect(testRunner.run).calledWith({ timeout: 12 * 23 + 1000 }); + }); - it('should have reset the source file', () => { - expect(fileUtils.writeFile).to.have.been.calledWith(expectedTargetFileToMutate, 'original code'); - }); + it('should have reset the source file', () => { + expect(fileUtils.writeFile).to.have.been.calledWith(expectedTargetFileToMutate, 'original code'); }); }); }); }); describe('when constructed without a testFramework or CoverageInstrumenter', () => { - beforeEach(() => sut = new Sandbox(options, 3, files, null, null)); - - describe('and initialized', () => { + beforeEach(async () => { + sut = await Sandbox.create(options, 3, files, null, null); + }); - beforeEach(() => sut.initialize()); - it('should have created the isolated test runner', () => { - const expectedSettings: IsolatedRunnerOptions = { - files: [ - fileDescriptor({ name: path.join(workingFolder, 'file1'), mutated: true, included: true }), - fileDescriptor({ name: path.join(workingFolder, 'file2'), mutated: false, included: false }), - fileDescriptor({ name: webFileUrl, mutated: false, included: true, transpiled: false, kind: FileKind.Web }) - ], - port: 46, - strykerOptions: options, - sandboxWorkingFolder: workingFolder - }; - expect(ResilientTestRunnerFactory.create).to.have.been.calledWith(options.testRunner, expectedSettings); - }); + it('should have created the isolated test runner', () => { + const expectedSettings: IsolatedRunnerOptions = { + files: [ + fileDescriptor({ name: path.join(workingFolder, 'file1'), mutated: true, included: true }), + fileDescriptor({ name: path.join(workingFolder, 'file2'), mutated: false, included: false }), + fileDescriptor({ name: webFileUrl, mutated: false, included: true, transpiled: false, kind: FileKind.Web }) + ], + port: 46, + strykerOptions: options, + sandboxWorkingFolder: workingFolder + }; + expect(ResilientTestRunnerFactory.create).to.have.been.calledWith(options.testRunner, expectedSettings); + }); - describe('when runMutant()', () => { + describe('when runMutant()', () => { - beforeEach(() => { - const mutant = new TestableMutant(createMutant(), new SourceFile(textFile())); - return sut.runMutant(new TranspiledMutant(mutant, transpileResult({ outputFiles: [textFile({ name: expectedTargetFileToMutate })] }))); - }); + beforeEach(() => { + const mutant = new TestableMutant(createMutant(), new SourceFile(textFile())); + return sut.runMutant(new TranspiledMutant(mutant, transpileResult({ outputFiles: [textFile({ name: expectedTargetFileToMutate })] }))); + }); - it('should not filter any tests', () => { - expect(fileUtils.writeFile).not.calledWith(expectedTestFrameworkHooksFile); - }); + it('should not filter any tests', () => { + expect(fileUtils.writeFile).not.calledWith(expectedTestFrameworkHooksFile); }); }); }); diff --git a/packages/stryker/test/unit/process/InitialTestExecutorSpec.ts b/packages/stryker/test/unit/process/InitialTestExecutorSpec.ts index 0cb5f811f4..f0ef7fd552 100644 --- a/packages/stryker/test/unit/process/InitialTestExecutorSpec.ts +++ b/packages/stryker/test/unit/process/InitialTestExecutorSpec.ts @@ -1,6 +1,5 @@ import { EOL } from 'os'; import { expect } from 'chai'; -import * as strykerSandbox from '../../../src/Sandbox'; import { default as StrykerSandbox } from '../../../src/Sandbox'; import InitialTestExecutor, { InitialTestRunResult } from '../../../src/process/InitialTestExecutor'; import { File } from 'stryker-api/core'; @@ -29,7 +28,7 @@ describe('InitialTestExecutor run', () => { beforeEach(() => { strykerSandboxMock = producers.mock(StrykerSandbox); transpilerFacadeMock = producers.mock(TranspilerFacade); - sandbox.stub(strykerSandbox, 'default').returns(strykerSandboxMock); + sandbox.stub(StrykerSandbox, 'create').resolves(strykerSandboxMock); sandbox.stub(transpilerFacade, 'default').returns(transpilerFacadeMock); testFrameworkMock = producers.testFramework(); coverageInstrumenter = new CoverageInstrumenter('off', testFrameworkMock); @@ -66,13 +65,11 @@ describe('InitialTestExecutor run', () => { it('should create a sandbox with correct arguments', async () => { await sut.run(); - expect(strykerSandbox.default).calledWith(options, 0, transpileResultMock.outputFiles, testFrameworkMock, coverageInstrumenter); - expect(strykerSandbox.default).calledWithNew; + expect(StrykerSandbox.create).calledWith(options, 0, transpileResultMock.outputFiles, testFrameworkMock, coverageInstrumenter); }); it('should initialize, run and dispose the sandbox', async () => { await sut.run(); - expect(strykerSandboxMock.initialize).to.have.been.called; expect(strykerSandboxMock.run).to.have.been.calledWith(60 * 1000 * 5); expect(strykerSandboxMock.dispose).to.have.been.called; }); diff --git a/packages/stryker/test/unit/process/MutationTestExecutorSpec.ts b/packages/stryker/test/unit/process/MutationTestExecutorSpec.ts index 84746ebed7..56d9631ed0 100644 --- a/packages/stryker/test/unit/process/MutationTestExecutorSpec.ts +++ b/packages/stryker/test/unit/process/MutationTestExecutorSpec.ts @@ -11,7 +11,7 @@ import MutantTestExecutor from '../../../src/process/MutationTestExecutor'; import TranspiledMutant from '../../../src/TranspiledMutant'; import { MutantStatus } from 'stryker-api/report'; import MutantTranspiler, * as mutantTranspiler from '../../../src/transpiler/MutantTranspiler'; -import SandboxCoordinator, * as sandboxCoordinator from '../../../src/SandboxCoordinator'; +import SandboxPool, * as sandboxPool from '../../../src/SandboxPool'; import { transpiledMutant, testResult, Mock, mock, textFile, config, testFramework, testableMutant, mutantResult } from '../../helpers/producers'; import '../../helpers/globals'; import TestableMutant from '../../../src/TestableMutant'; @@ -28,7 +28,7 @@ const createTranspiledMutants = (...n: number[]) => { describe('MutationTestExecutor', () => { - let sandboxCoordinatorMock: Mock; + let sandboxPoolMock: Mock; let mutantTranspilerMock: Mock; let testFrameworkMock: TestFramework; let transpiledMutants: TranspiledMutant[]; @@ -40,12 +40,12 @@ describe('MutationTestExecutor', () => { let mutants: TestableMutant[]; beforeEach(() => { - sandboxCoordinatorMock = mock(SandboxCoordinator); + sandboxPoolMock = mock(SandboxPool); mutantTranspilerMock = mock(MutantTranspiler); mutantTranspilerMock.initialize.resolves(); - sandboxCoordinatorMock.disposeAll.resolves(); + sandboxPoolMock.disposeAll.resolves(); testFrameworkMock = testFramework(); - sandbox.stub(sandboxCoordinator, 'default').returns(sandboxCoordinatorMock); + sandbox.stub(sandboxPool, 'default').returns(sandboxPoolMock); sandbox.stub(mutantTranspiler, 'default').returns(mutantTranspilerMock); reporter = mock(BroadcastReporter); inputFiles = [textFile({ name: 'input.ts' })]; @@ -58,9 +58,9 @@ describe('MutationTestExecutor', () => { beforeEach(async () => { sut = new MutantTestExecutor(expectedConfig, inputFiles, transpiledFiles, testFrameworkMock, reporter); - const sandbox = mock(Sandbox); + const sandbox = mock(Sandbox); sandbox.runMutant.resolves(mutantResult()); - sandboxCoordinatorMock.streamSandboxes.returns(Observable.of(sandbox)); + sandboxPoolMock.streamSandboxes.returns(Observable.of(sandbox)); mutantTranspilerMock.transpileMutants.returns(Observable.empty()); await sut.run(mutants); }); @@ -70,8 +70,8 @@ describe('MutationTestExecutor', () => { expect(mutantTranspiler.default).calledWithNew; }); it('should create the sandbox pool', () => { - expect(sandboxCoordinator.default).calledWith(expectedConfig, testFrameworkMock, transpiledFiles); - expect(sandboxCoordinator.default).calledWithNew; + expect(sandboxPool.default).calledWith(expectedConfig, testFrameworkMock, transpiledFiles); + expect(sandboxPool.default).calledWithNew; }); it('should initialize the mutantTranspiler', () => { @@ -79,7 +79,7 @@ describe('MutationTestExecutor', () => { }); it('should dispose all sandboxes afterwards', () => { - expect(sandboxCoordinatorMock.disposeAll).called; + expect(sandboxPoolMock.disposeAll).called; }); }); @@ -94,7 +94,7 @@ describe('MutationTestExecutor', () => { firstSandbox = mock(Sandbox); secondSandbox = mock(Sandbox); mutantTranspilerMock.transpileMutants.returns(Observable.of(...transpiledMutants)); - sandboxCoordinatorMock.streamSandboxes.returns(Observable.of(...[firstSandbox, secondSandbox])); + sandboxPoolMock.streamSandboxes.returns(Observable.of(...[firstSandbox, secondSandbox])); sut = new MutantTestExecutor(config(), inputFiles, transpiledFiles, testFrameworkMock, reporter);