Skip to content

Commit

Permalink
more flexible mocha child implementation using child_process.fork
Browse files Browse the repository at this point in the history
  • Loading branch information
bttmly committed Jul 26, 2016
1 parent 5140840 commit 8764594
Show file tree
Hide file tree
Showing 48 changed files with 309 additions and 203 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pids
*.seed

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
lib-covw

# Coverage directory used by tools like istanbul
coverage
Expand All @@ -34,4 +34,5 @@ example/.DS_Store
example/.perturb
typings
lib
built
built
logs
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ events:

dogfood:
rm -rf ./.perturb
rm -rf ./built
./node_modules/.bin/tsc
node ./run.js dogfood
node ./run.js dogfood $(RUNNER)

build:
./node_modules/.bin/tsc --strictNullChecks
Expand Down
24 changes: 4 additions & 20 deletions run.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const path = require("path");

function run (perturb, which, cb) {
function run (perturb, which, runner) {
let config;

switch (which) {
case "dogfood":
config = {
rootDir: path.join(__dirname, ".."),
sourceDir: "built",
runner: "mocha",
runner: runner || "mocha",
reporter: "name",
testCmd: "make test-bail",
};
break;
Expand All @@ -24,23 +25,6 @@ function run (perturb, which, cb) {
throw new Error("Unknown config " + which);
}

if (cb) {
return perturb(config, function (err, results) {
if (err) {
console.log("fatal error in perturb");
console.log(err);
console.log(err.stack);
cb(err);
process.exit(1);
}

try {
console.log("kill count", results.filter(r => r.error).length, "/", results.length)
} catch (e) {}
cb(null, results);
});
}

return perturb(config)
.then(function (results) {
console.log("DONE!");
Expand All @@ -53,7 +37,7 @@ function run (perturb, which, cb) {
}

if (!module.parent) {
run(require("./built"), process.argv[2]);
run(require("./built"), process.argv[2], process.argv[3]);
}

module.exports = run;
2 changes: 1 addition & 1 deletion src/constants/binary-operator-swaps.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export = {
"+": "-",
"-": "+",
"*": "/",
Expand Down
2 changes: 1 addition & 1 deletion src/constants/errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export = {
NotKeyedIterable: "Node must be an Immutable.js keyed iterable",
WrongNodeType: "Node is of wrong type. Actual: %s; Expected: %s",
TestsFailed: "Test command `%s` failed. Tests must be passing for perturb to work properly.",
Expand Down
2 changes: 1 addition & 1 deletion src/constants/func-nodes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var S = require("estraverse").Syntax;

module.exports = {
export = {
[S.FunctionDeclaration]: S.FunctionDeclaration,
[S.FunctionExpression]: S.FunctionExpression,
[S.ArrowFunctionExpression]: S.ArrowFunctionExpression,
Expand Down
2 changes: 1 addition & 1 deletion src/constants/js-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export = {
func: "function",
bool: "boolean",
str: "string",
Expand Down
2 changes: 1 addition & 1 deletion src/constants/messages.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export = {
TestsPassed: "Test command exited with `0`. Continuing...",
ExecutingTests: "executing `%s` ...",
DefaultTest: "npm test",
Expand Down
2 changes: 1 addition & 1 deletion src/constants/node-attrs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export = {
operator: "operator",
elements: "elements",
properties: "properties",
Expand Down
2 changes: 1 addition & 1 deletion src/constants/node-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = {
export = {
AssignmentExpression: "AssignmentExpression",
ArrayExpression: "ArrayExpression",
ArrowFunctionExpression: "ArrowFunctionExpression",
Expand Down
2 changes: 1 addition & 1 deletion src/constants/test-nodes.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var S = require("estraverse").Syntax;

module.exports = {
export = {
[S.IfStatement]: S.IfStatement,
[S.WhileStatement]: S.WhileStatement,
[S.DoWhileStatement]: S.DoWhileStatement,
Expand Down
4 changes: 3 additions & 1 deletion src/file-system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function getFilePaths (config: PerturbConfig): FilePathResult {
};
}

export = function createFsHelpers (c: PerturbConfig) {
function createFsHelpers (c: PerturbConfig) {
return <FsHelper>{
setup () {
setupPerturbDirectory(c);
Expand All @@ -78,3 +78,5 @@ export = function createFsHelpers (c: PerturbConfig) {
},
};
}

export = createFsHelpers;
15 changes: 7 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function hasTests (m: Match): boolean {
return Boolean(R.path(["tests", "length"], m));
}

module.exports = function perturb (_cfg: PerturbConfig) {
function perturb (_cfg: PerturbConfig) {
const cfg = makeConfig(_cfg);

console.log("init with config\n", cfg);
Expand Down Expand Up @@ -95,16 +95,13 @@ module.exports = function perturb (_cfg: PerturbConfig) {

function makeMutantHandler (Runner: RunnerPluginCtor, reporter: ReporterPlugin) {
return function handler (m: Mutant): Promise<RunnerResult> {
let _result;
const runner = new Runner(m);
let _before, _result;
return runner.setup(m)
.then(before => {
_before = before;
return runner.run(m)
})
return runner.setup()
.then(() => runner.run())
.then(result => {
_result = result;
return runner.cleanup(result, _before);
return runner.cleanup();
})
.then(() => {
if (reporter.onResult) {
Expand Down Expand Up @@ -141,3 +138,5 @@ Promise.prototype.finally = function (cb) {
reason => this.constructor.resolve(cb()).then(() => { throw reason; })
);
}

export = perturb;
4 changes: 3 additions & 1 deletion src/make-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const defaultConfig: PerturbConfig = {
runner: "mocha-child-process",
}

export = function makeConfig (userConfig = {}): PerturbConfig {
function makeConfig (userConfig = {}): PerturbConfig {
let fileConfig;

try {
Expand All @@ -36,3 +36,5 @@ export = function makeConfig (userConfig = {}): PerturbConfig {

return <PerturbConfig>assign({}, defaultConfig, fileConfig, userConfig);
}

export = makeConfig;
4 changes: 3 additions & 1 deletion src/make-mutants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const FS_SETTINGS = {
encoding: "utf8",
};

export = function makeMutants (match: Match): Mutant[] {
function makeMutants (match: Match): Mutant[] {
const { source, tests } = match;
const { ast, code } = parse(source);
const paths: Path[] = getMutationPaths(ast).map(p => p.map(String));
Expand Down Expand Up @@ -102,3 +102,5 @@ function parse (source: string) {
throw err;
}
}

export = makeMutants;
2 changes: 1 addition & 1 deletion src/matchers/base-comparative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
// source: project/lib/dir/file.js
// test: project/test/dir/file.js

module.exports = <ComparativeMatcherPlugin>{
export = <ComparativeMatcherPlugin>{
type: "comparative",
makeMatcher: function (c: PerturbConfig): ComparativeMatcher {
return function (sourceFile: string, testFile: string): boolean {
Expand Down
2 changes: 1 addition & 1 deletion src/matchers/base-generative.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
// input: project/lib/dir/car.js
// output: project/test/dir/car.js

module.exports = <GenerativeMatcherPlugin>{
export = <GenerativeMatcherPlugin>{
type: "generative",
makeMatcher: function(c: PerturbConfig): GenerativeMatcher {
return function(sourceFile: string) {
Expand Down
4 changes: 2 additions & 2 deletions src/matchers/contains-comparative.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const path = require("path");
import path = require("path");

import {
ComparativeMatcherPlugin,
Expand All @@ -16,7 +16,7 @@ function withoutExt (file) {
return file.slice(0, -1 * path.extname(file).length);
}

module.exports = <ComparativeMatcherPlugin>{
export = <ComparativeMatcherPlugin>{
type: "comparative",
makeMatcher: function(c: PerturbConfig): ComparativeMatcher {
return function(sourceFile: string, testFile: string): boolean {
Expand Down
58 changes: 32 additions & 26 deletions src/matchers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import {
Match
} from "../types";

import baseGenerative = require("./base-generative");
import baseComparative = require("./base-comparative");
import containsComparative = require("./contains-comparative");

interface runMatcher {
(matcher: ComparativeMatcher | GenerativeMatcher, source: string, tests: string[]): string[];
}
Expand All @@ -29,39 +33,41 @@ function runGenerative (
return R.contains(name, tests) ? [name] : [];
}

export = function getMatcher (c: PerturbConfig) {
const builtIns = new Map<string, MatcherPlugin>([
["base-generative", baseGenerative],
["base-comparative", baseComparative],
["contains-comparative", containsComparative],
]);

function getMatcher (c: PerturbConfig) {
const matcherPlugin = getMatcherPlugin(c.matcher);
const {type} = matcherPlugin;
const matcher = matcherPlugin.makeMatcher(c);

return function findMatches (sources: string[], tests: string[]): Match[] {
const runMatch: runMatcher = type === "generative" ? runGenerative : runComparative;
return sources.map(function (source) {
return <Match>{ source, tests: runMatch(matcher, source, tests) };
});
return sources.map(source => ({
source, tests: runMatch(matcher, source, tests),
}));
}
}

const baseGenerative = require("./base-generative");
const baseComparative = require("./base-comparative");
const containsComparative = require("./contains-comparative");

const builtIns = new Map<string, MatcherPlugin>([
["base-generative", baseGenerative],
["base-comparative", baseComparative],
["contains-comparative", containsComparative],
]);

function getMatcherPlugin (name): MatcherPlugin {
const plugin = builtIns.get(name);
if (plugin) return plugin;

try {
// TODO -- runtime type check this import
return require(`perturb-matcher-plugin-${name}`);
} catch (err) {
console.log("Fatal error: unable to resolve MATCHER plugin name", name);
throw err;
function getMatcherPlugin (input: string | MatcherPlugin): MatcherPlugin {
if (typeof input === "string") {
const plugin = builtIns.get(input);

if (plugin) return plugin;

try {
// TODO -- runtime type check this import
return require(`perturb-matcher-plugin-${input}`);
} catch (err) {
console.log("Fatal error: unable to resolve MATCHER plugin name", input);
throw err;
}
} else {
return input;
}
}
}

export = getMatcher;
2 changes: 1 addition & 1 deletion src/mutators/drop-member-assignment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { MutatorPlugin } from "../types";

// drops a member assignment
// `obj.prop = 'value';` => `obj.prop;`
module.exports = <MutatorPlugin>{
export = <MutatorPlugin>{
name: "drop-member-assignment",
nodeTypes: [Syntax.AssignmentExpression],
filter: function (node) {
Expand Down
2 changes: 1 addition & 1 deletion src/mutators/drop-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const voidNode = require("./_void-node");

import { MutatorPlugin } from "../types";

module.exports = <MutatorPlugin>{
export = <MutatorPlugin>{
name: "drop-node",
nodeTypes: [
Syntax.ContinueStatement,
Expand Down
2 changes: 1 addition & 1 deletion src/mutators/drop-operator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface ArgumentedNode extends ESTree.Node {
argument: any
}

module.exports = <MutatorPlugin>{
export = <MutatorPlugin>{
name: "drop-operator",
nodeTypes: [
Syntax.ThrowStatement,
Expand Down
2 changes: 1 addition & 1 deletion src/mutators/drop-return.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface MaybeArgumentedNode extends ESTree.Node {
argument?: any
}

module.exports = <MutatorPlugin>{
export = <MutatorPlugin>{
name: "drop-return",
nodeTypes: [Syntax.ReturnStatement],
mutator: function (node: MaybeArgumentedNode) {
Expand Down
2 changes: 1 addition & 1 deletion src/mutators/drop-void-call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { MutatorPlugin } from "../types";
// drops a function call made for side effects
// (the return value isn't assigned to a variable)
// (will this cause lots of test timeouts due to uncalled callbacks?)
module.exports = <MutatorPlugin>{
export = <MutatorPlugin>{
name: "dropVoidCall",
nodeTypes: [Syntax.ExpressionStatement],
filter: function (node) {
Expand Down
4 changes: 1 addition & 3 deletions src/mutators/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
const R = require("ramda");

import {
MutatorPlugin
} from "../types";
import { MutatorPlugin } from "../types";

const coreMutators: MutatorPlugin[] = [
require("./drop-member-assignment"),
Expand Down
Loading

0 comments on commit 8764594

Please sign in to comment.