Skip to content

Commit

Permalink
#21 booleanliteral (#44)
Browse files Browse the repository at this point in the history
* WIP Mutation level support for BooleanLiterals

* Fix prettier

* Tests

* Pleased linter

* Fixed typo

* Added tests for edge cases
  • Loading branch information
Luctia authored and Ja4pp committed Jan 14, 2024
1 parent 73fb957 commit 21f2ba8
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 8 deletions.
38 changes: 32 additions & 6 deletions packages/instrumenter/src/mutators/boolean-literal-mutator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,41 @@ const { types } = babel;

import { NodeMutator } from './index.js';

const booleanLiteralReplacements = Object.freeze({
// prettier-ignore
'true': {replacement: 'false', mutatorName: 'TrueToFalse'},
// prettier-ignore
'false': {replacement: 'true', mutatorName: 'FalseToTrue'},
'!': { replacement: '', mutatorName: 'RemoveNegation' },
} as const);

export const booleanLiteralMutator: NodeMutator = {
name: 'BooleanLiteral',

*mutate(path) {
if (path.isBooleanLiteral()) {
yield types.booleanLiteral(!path.node.value);
}
if (path.isUnaryExpression() && path.node.operator === '!' && path.node.prefix) {
yield deepCloneNode(path.node.argument);
*mutate(path, options: string[] | undefined) {
if (isInMutationLevel(path, options)) {
if (path.isBooleanLiteral()) {
yield types.booleanLiteral(!path.node.value);
}
if (path.isUnaryExpression() && path.node.operator === '!' && path.node.prefix) {
yield deepCloneNode(path.node.argument);
}
}
},
};

function isInMutationLevel(path: any, mutators: string[] | undefined): boolean {
if (mutators === undefined) {
return true;
}
if (path.isBooleanLiteral()) {
const { mutatorName } = booleanLiteralReplacements[path.node.value as keyof typeof booleanLiteralReplacements];
return mutators.some((lit) => lit === mutatorName);
}
return (
path.isUnaryExpression() &&
path.node.operator === '!' &&
path.node.prefix &&
mutators.some((lit: string) => lit === booleanLiteralReplacements['!'].mutatorName)
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
import { expect } from 'chai';

import { MutationLevel } from '@stryker-mutator/api/core';

import { booleanLiteralMutator as sut } from '../../../src/mutators/boolean-literal-mutator.js';
import { expectJSMutation } from '../../helpers/expect-mutation.js';
import { expectJSMutation, expectJSMutationWithLevel } from '../../helpers/expect-mutation.js';

const booleanLiteralLevel: MutationLevel = {
name: 'BooleanLiteralLevel',
BooleanLiteral: ['TrueToFalse', 'RemoveNegation'],
};

const booleanLiteralAllLevel: MutationLevel = {
name: 'BooleanLiteralLevel',
BooleanLiteral: ['TrueToFalse', 'FalseToTrue', 'RemoveNegation'],
};

const booleanLiteralUndefinedLevel: MutationLevel = {
name: 'BooleanLiteralLevel',
};

describe(sut.name, () => {
it('should have name "BooleanLiteral"', () => {
Expand All @@ -19,4 +35,40 @@ describe(sut.name, () => {
it('should mutate !a to a', () => {
expectJSMutation(sut, '!a', 'a');
});

it('should only mutate what is defined in the mutation level', () => {
expectJSMutationWithLevel(
sut,
booleanLiteralLevel.BooleanLiteral,
'if (true) {}; if (false) {}; if (!value) {}',
'if (false) {}; if (false) {}; if (!value) {}',
'if (true) {}; if (false) {}; if (value) {}',
);
});

it('should not mutate anything if there are no values in the mutation level', () => {
expectJSMutationWithLevel(sut, [], 'if (true) {}; if (false) {}; if (!value) {}');
});

it('should mutate everything if everything is in the mutation level', () => {
expectJSMutationWithLevel(
sut,
booleanLiteralAllLevel.BooleanLiteral,
'if (true) {}; if (false) {}; if (!value) {}',
'if (false) {}; if (false) {}; if (!value) {}',
'if (true) {}; if (false) {}; if (value) {}',
'if (true) {}; if (true) {}; if (!value) {}',
);
});

it('should mutate everything if the mutation level is undefined', () => {
expectJSMutationWithLevel(
sut,
booleanLiteralUndefinedLevel.BooleanLiteral,
'if (true) {}; if (false) {}; if (!value) {}',
'if (false) {}; if (false) {}; if (!value) {}',
'if (true) {}; if (false) {}; if (value) {}',
'if (true) {}; if (true) {}; if (!value) {}',
);
});
});
3 changes: 2 additions & 1 deletion testing-project/stryker.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
{
"name": "default",
"ArithmeticOperator": ["+To-", "-To+", "*To/"],
"ArrayDeclaration": ["EmptyArray", "FilledArray", "FilledArrayConstructor"]
"ArrayDeclaration": ["EmptyArray", "FilledArray", "FilledArrayConstructor"],
"BooleanLiteral": ["TrueToFalse", "RemoveNegation"]

},
{
Expand Down

0 comments on commit 21f2ba8

Please sign in to comment.