From 8f989cceb8fea5e66e3055a623f238ce85ef1025 Mon Sep 17 00:00:00 2001 From: Nico Jansen Date: Sat, 26 Sep 2020 12:04:22 +0200 Subject: [PATCH] fix(instrumenter): only add header when there are mutats (#2503) Only add the JS header for files that have mutants. For example: don't add it in *.d.ts files. --- .../src/transformers/babel-transformer.ts | 4 +- .../src/transformers/mutant-collector.ts | 4 ++ .../transformers/babel-transformer.spec.ts | 9 +++ .../transformers/mutant-collector.spec.ts | 19 +++++++ .../instrumenter/flow-typed.js.out.snap | 56 +------------------ .../instrumenter/ts-declarations.ts.out.snap | 56 +------------------ .../instrumenter/type-definitions.ts.out.snap | 56 +------------------ 7 files changed, 38 insertions(+), 166 deletions(-) diff --git a/packages/instrumenter/src/transformers/babel-transformer.ts b/packages/instrumenter/src/transformers/babel-transformer.ts index 876733cfe7..221bf22384 100644 --- a/packages/instrumenter/src/transformers/babel-transformer.ts +++ b/packages/instrumenter/src/transformers/babel-transformer.ts @@ -33,5 +33,7 @@ export const transformBabel: AstTransformer = ({ ro } }, }); - root.program.body.unshift(...instrumentationBabelHeader); + if (mutantCollector.hasMutants(originFileName)) { + root.program.body.unshift(...instrumentationBabelHeader); + } }; diff --git a/packages/instrumenter/src/transformers/mutant-collector.ts b/packages/instrumenter/src/transformers/mutant-collector.ts index 56867702ae..876786713c 100644 --- a/packages/instrumenter/src/transformers/mutant-collector.ts +++ b/packages/instrumenter/src/transformers/mutant-collector.ts @@ -33,4 +33,8 @@ export class MutantCollector { public markMutantsAsPlaced(mutants: Mutant[]): void { this.unplacedMutants = this.unplacedMutants.filter((unplaced) => !mutants.includes(unplaced)); } + + public hasMutants(fileName: string) { + return this.mutants.some((mutant) => mutant.fileName === fileName); + } } diff --git a/packages/instrumenter/test/unit/transformers/babel-transformer.spec.ts b/packages/instrumenter/test/unit/transformers/babel-transformer.spec.ts index 88feef8217..f88b88763e 100644 --- a/packages/instrumenter/test/unit/transformers/babel-transformer.spec.ts +++ b/packages/instrumenter/test/unit/transformers/babel-transformer.spec.ts @@ -82,12 +82,21 @@ describe('babel-transformer', () => { it('should add the global stuff on top', () => { const ast = createJSAst({ rawContent: 'foo' }); + mutantCollectorMock.hasMutants.returns(true); transformBabel(ast, mutantCollectorMock, context); for (let i = 0; i < instrumentationBabelHeader.length; i++) { expect(ast.root.program.body[i]).eq(instrumentationBabelHeader[i]); } }); + it('should not add global js header if no mutants were placed in the code', () => { + const ast = createJSAst({ originFileName: 'foo.js', rawContent: 'foo' }); + mutantCollectorMock.hasMutants.returns(false); + transformBabel(ast, mutantCollectorMock, context); + expect(mutantCollectorMock.hasMutants).calledWith('foo.js'); + expect(ast.root.program.body).lengthOf(1); + }); + describe('types', () => { it('should skip type annotations', () => { const ast = createTSAst({ rawContent: 'const foo: string;' }); diff --git a/packages/instrumenter/test/unit/transformers/mutant-collector.spec.ts b/packages/instrumenter/test/unit/transformers/mutant-collector.spec.ts index 5e2668578d..c27f1a006a 100644 --- a/packages/instrumenter/test/unit/transformers/mutant-collector.spec.ts +++ b/packages/instrumenter/test/unit/transformers/mutant-collector.spec.ts @@ -91,4 +91,23 @@ describe(MutantCollector.name, () => { expect(actual).deep.eq([mutants[1]]); }); }); + + describe(MutantCollector.prototype.hasMutants.name, () => { + it('should return true when a mutant is registered for the file', () => { + const input = [createMutant({ fileName: 'foo.js' }), createMutant({ fileName: 'bar.js' })]; + input.map((mutant) => sut.add(mutant.fileName, mutant)); + expect(sut.hasMutants('foo.js')).true; + expect(sut.hasMutants('bar.js')).true; + }); + + it('should return false when no mutants is registered for the file', () => { + const input = [createMutant({ fileName: 'foo.js' }), createMutant({ fileName: 'bar.js' })]; + input.map((mutant) => sut.add(mutant.fileName, mutant)); + expect(sut.hasMutants('baz.js')).false; + }); + + it('should return false when no mutants are registered at all', () => { + expect(sut.hasMutants('baz.js')).false; + }); + }); }); diff --git a/packages/instrumenter/testResources/instrumenter/flow-typed.js.out.snap b/packages/instrumenter/testResources/instrumenter/flow-typed.js.out.snap index cd60b1dd10..2f951e58bc 100644 --- a/packages/instrumenter/testResources/instrumenter/flow-typed.js.out.snap +++ b/packages/instrumenter/testResources/instrumenter/flow-typed.js.out.snap @@ -1,61 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`instrumenter integration type declarations should not produce mutants for flow-types 1`] = ` -"function stryNS_9fa48() { - var g = new Function(\\"return this\\")(); - var ns = g.__stryker__ || (g.__stryker__ = {}); - - if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { - ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); - } - - function retrieveNS() { - return ns; - } - - stryNS_9fa48 = retrieveNS; - return retrieveNS(); -} - -stryNS_9fa48(); - -function stryCov_9fa48() { - var ns = stryNS_9fa48(); - var cov = ns.mutantCoverage || (ns.mutantCoverage = { - static: {}, - perTest: {} - }); - - function cover() { - var c = cov.static; - - if (ns.currentTestId) { - c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; - } - - var a = arguments; - - for (var i = 0; i < a.length; i++) { - c[a[i]] = (c[a[i]] || 0) + 1; - } - } - - stryCov_9fa48 = cover; - cover.apply(null, arguments); -} - -function stryMutAct_9fa48(id) { - var ns = stryNS_9fa48(); - - function isActive(id) { - return ns.activeMutant === id; - } - - stryMutAct_9fa48 = isActive; - return isActive(id); -} - -declare module 'react-test-renderer' {// eslint-disable-next-line no-inner-declarations +"declare module 'react-test-renderer' {// eslint-disable-next-line no-inner-declarations } declare type ReactTestRenderer = { toJSON(): null | ReactTestRendererJSON, diff --git a/packages/instrumenter/testResources/instrumenter/ts-declarations.ts.out.snap b/packages/instrumenter/testResources/instrumenter/ts-declarations.ts.out.snap index e14a783c35..2933e19433 100644 --- a/packages/instrumenter/testResources/instrumenter/ts-declarations.ts.out.snap +++ b/packages/instrumenter/testResources/instrumenter/ts-declarations.ts.out.snap @@ -1,61 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`instrumenter integration type declarations should not produce mutants for a TS declaration file 1`] = ` -"function stryNS_9fa48() { - var g = new Function(\\"return this\\")(); - var ns = g.__stryker__ || (g.__stryker__ = {}); - - if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { - ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); - } - - function retrieveNS() { - return ns; - } - - stryNS_9fa48 = retrieveNS; - return retrieveNS(); -} - -stryNS_9fa48(); - -function stryCov_9fa48() { - var ns = stryNS_9fa48(); - var cov = ns.mutantCoverage || (ns.mutantCoverage = { - static: {}, - perTest: {} - }); - - function cover() { - var c = cov.static; - - if (ns.currentTestId) { - c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; - } - - var a = arguments; - - for (var i = 0; i < a.length; i++) { - c[a[i]] = (c[a[i]] || 0) + 1; - } - } - - stryCov_9fa48 = cover; - cover.apply(null, arguments); -} - -function stryMutAct_9fa48(id) { - var ns = stryNS_9fa48(); - - function isActive(id) { - return ns.activeMutant === id; - } - - stryMutAct_9fa48 = isActive; - return isActive(id); -} - -export declare const globalNamespace = \\"globalNamespace\\"; +"export declare const globalNamespace = \\"globalNamespace\\"; declare function foo(): 'foo'; declare module 'express' {}" `; diff --git a/packages/instrumenter/testResources/instrumenter/type-definitions.ts.out.snap b/packages/instrumenter/testResources/instrumenter/type-definitions.ts.out.snap index ab773126ca..f567b1932c 100644 --- a/packages/instrumenter/testResources/instrumenter/type-definitions.ts.out.snap +++ b/packages/instrumenter/testResources/instrumenter/type-definitions.ts.out.snap @@ -1,61 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`instrumenter integration type declarations should not produce mutants for TS type definitions 1`] = ` -"function stryNS_9fa48() { - var g = new Function(\\"return this\\")(); - var ns = g.__stryker__ || (g.__stryker__ = {}); - - if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { - ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); - } - - function retrieveNS() { - return ns; - } - - stryNS_9fa48 = retrieveNS; - return retrieveNS(); -} - -stryNS_9fa48(); - -function stryCov_9fa48() { - var ns = stryNS_9fa48(); - var cov = ns.mutantCoverage || (ns.mutantCoverage = { - static: {}, - perTest: {} - }); - - function cover() { - var c = cov.static; - - if (ns.currentTestId) { - c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; - } - - var a = arguments; - - for (var i = 0; i < a.length; i++) { - c[a[i]] = (c[a[i]] || 0) + 1; - } - } - - stryCov_9fa48 = cover; - cover.apply(null, arguments); -} - -function stryMutAct_9fa48(id) { - var ns = stryNS_9fa48(); - - function isActive(id) { - return ns.activeMutant === id; - } - - stryMutAct_9fa48 = isActive; - return isActive(id); -} - -/** +"/** * @see https://github.com/stryker-mutator/stryker/issues/2465 */ const flatten = (require('lodash/flatten') as typeof import('lodash/flatten'));"