Skip to content

Commit

Permalink
fix(arithmatic-mutator): Don't mutate obvious string concat (#2648)
Browse files Browse the repository at this point in the history
Don't mutate `"a" + "b"` into `"a" - "b"`. This only works for 'obvious'
string concats.
  • Loading branch information
Garethp authored and nicojs committed Dec 9, 2020
1 parent f3a177d commit 71f8f9a
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 15 deletions.
8 changes: 4 additions & 4 deletions e2e/test/angular-project/verify/verify.ts
Expand Up @@ -3,15 +3,15 @@ import { expectMetrics } from '../../../helpers';
describe('After running stryker on angular project', () => {
it('should report mutation score', async () => {
await expectMetrics({
mutationScore: 42.86,
killed: 3,
mutationScore: 33.33,
killed: 2,
survived: 0,
noCoverage: 4,
compileErrors: 0,
})
});
// -------------------|---------|----------|-----------|------------|----------|---------|
// File | % score | # killed | # timeout | # survived | # no cov | # error |
// -------------------|---------|----------|-----------|------------|----------|---------|
// All files | 42.86 | 3 | 0 | 0 | 4 | 0 |
// All files | 33.33 | 2 | 0 | 0 | 4 | 0 |
});
});
16 changes: 8 additions & 8 deletions e2e/test/jest-react/verify/verify.ts
Expand Up @@ -4,22 +4,22 @@ describe('After running stryker on jest-react project', () => {
it('should report expected scores', async () => {
await expectMetricsResult({
metrics: produceMetrics({
killed: 33,
killed: 32,
timeout: 0,
mutationScore: 67.35,
mutationScoreBasedOnCoveredCode: 67.35,
mutationScore: 66.67,
mutationScoreBasedOnCoveredCode: 66.67,
survived: 16,
totalCovered: 49,
totalDetected: 33,
totalMutants: 49,
totalCovered: 48,
totalDetected: 32,
totalMutants: 48,
totalUndetected: 16,
totalValid: 49
totalValid: 48
}),
});
/*
---------------|---------|----------|-----------|------------|----------|---------|
File | % score | # killed | # timeout | # survived | # no cov | # error |
---------------|---------|----------|-----------|------------|----------|---------|
All files | 67.35 | 33 | 0 | 16 | 0 | 0 |*/
All files | 66.67 | 32 | 0 | 16 | 0 | 0 |*/
});
});
17 changes: 14 additions & 3 deletions packages/instrumenter/src/mutators/arithmetic-operator-mutator.ts
Expand Up @@ -18,7 +18,7 @@ export class ArithmeticOperatorMutator implements NodeMutator {
public name = 'ArithmeticOperator';

public mutate(path: NodePath): NodeMutation[] {
if (path.isBinaryExpression() && this.isSupported(path.node.operator)) {
if (path.isBinaryExpression() && this.isSupported(path.node.operator, path.node)) {
const mutatedOperator = this.operators[path.node.operator];
const replacement = types.cloneNode(path.node, false);
replacement.operator = mutatedOperator;
Expand All @@ -28,7 +28,18 @@ export class ArithmeticOperatorMutator implements NodeMutator {
return [];
}

private isSupported(operator: string): operator is keyof typeof ArithmeticOperators {
return Object.keys(this.operators).includes(operator);
private isSupported(operator: string, node: types.BinaryExpression): operator is keyof typeof ArithmeticOperators {
if (!Object.keys(this.operators).includes(operator)) {
return false;
}

const stringTypes = ['StringLiteral', 'TemplateLiteral'];
const leftType = node.left.type === 'BinaryExpression' ? node.left.right.type : node.left.type;

if (stringTypes.includes(node.right.type) || stringTypes.includes(leftType)) {
return false;
}

return true;
}
}
Expand Up @@ -23,4 +23,16 @@ describe(ArithmeticOperatorMutator.name, () => {
expectJSMutation(sut, 'a / b', 'a * b');
expectJSMutation(sut, 'a % b', 'a * b');
});

it('should not mutate string literal concatenation', () => {
expectJSMutation(sut, '"a" + "b"');
expectJSMutation(sut, 'const a = 1; "a" + a');
expectJSMutation(sut, '3 + "a"');

expectJSMutation(sut, '`a` + `b`');
expectJSMutation(sut, 'const a = 1; `a` + a');
expectJSMutation(sut, '3 + `a`');

expectJSMutation(sut, '"a" + b + "c" + d + "e"');
});
});

0 comments on commit 71f8f9a

Please sign in to comment.