Skip to content

Commit

Permalink
cleanup: node 10, rm unused deps, refactor reporters
Browse files Browse the repository at this point in the history
  • Loading branch information
bttmly committed Mar 27, 2019
1 parent 0cb7ba0 commit dd00c0f
Show file tree
Hide file tree
Showing 15 changed files with 1,367 additions and 290 deletions.
6 changes: 0 additions & 6 deletions .babelrc

This file was deleted.

3 changes: 1 addition & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
"curly": 0,
"new-cap": 0,
"no-underscore-dangle": 0,
// because we use function declarations everywhere
"no-use-before-define": 0,
"comma-dangle": [2, "always-multiline"]
},
Expand All @@ -18,4 +17,4 @@
"describe": 1,
"xdescribe": 1
}
}
}
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ dogfood: compile
rm -rf ./.perturb
node ./lib/cli -s lib

dogfood-fork: compile
rm -rf ./.perturb
node ./lib/cli -s lib -u fork

ci: compile
node ./lib/cli -s lib -k 85

Expand Down
22 changes: 8 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,19 @@
},
"repository": "git@github.com:bttmly/perturb.git",
"dependencies": {
"bluebird": "^3.1.5",
"chalk": "^2.3.2",
"change-case": "^2.2.0",
"commander": "^2.18.0",
"commander": "^2.19.0",
"debug": "^2.2.0",
"diff": "^1.4.0",
"escodegen": "^1.8.0",
"esprima": "^4.0.0",
"estraverse": "^4.2.0",
"fs-extra": "^0.16.5",
"glob": "^4.5.3",
"graceful-fs": "^4.1.4",
"lodash.omitby": "^4.6.0",
"object-assign": "^2.0.0",
"ramda": "^0.18.0"
"fs-extra": "7.0.1",
"glob": "7.1.3",
"p-map-series": "^2.0.0",
"ramda": "^0.18.0",
"typescript": "^3.4.0-rc"
},
"devDependencies": {
"@types/bluebird": "^3.5.20",
Expand All @@ -35,20 +33,16 @@
"@types/estree": "^0.0.38",
"@types/fs-extra": "^5.0.1",
"@types/glob": "^5.0.35",
"@types/lodash.omitby": "^4.6.4",
"@types/mocha": "^5.0.0",
"@types/node": "^9.6.1",
"@types/ramda": "^0.25.21",
"babel-eslint": "^8.2.2",
"eslint": "^1.1.0",
"expect": "^1.20.2",
"growl": "^1.8.1",
"mocha": "^2.5.3",
"mocha": "^6.0.2",
"nyc": "^10.0.0",
"prettier": "^1.11.1",
"tslint": "^5.9.1",
"typescript": "3.1.1",
"watch": "^0.13.0"
"tslint": "^5.9.1"
},
"scripts": {
"example": "make example",
Expand Down
48 changes: 37 additions & 11 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,35 @@ interface PackageJSON {
version: string;
}

const pkg: PackageJSON = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json"), "utf8"));
const pkg: PackageJSON = JSON.parse(
fs.readFileSync(path.join(__dirname, "../package.json"), "utf8"),
);

program
.version(pkg.version)
.option("-r, --rootDir <rootDir>", "root directory of the project")
.option("-t, --testDir <testDir>", "test directory relative to root directory")
.option("-s, --sourceDir <sourceDir>", "source directory relative to root directory")
.option("-x, --testGlob <testGlob>", "glob for selecting files in test directory")
.option("-y, --sourceGlob <sourceGlob>", "glob for selecting files in source directory")
.option(
"-t, --testDir <testDir>",
"test directory relative to root directory",
)
.option(
"-s, --sourceDir <sourceDir>",
"source directory relative to root directory",
)
.option(
"-x, --testGlob <testGlob>",
"glob for selecting files in test directory",
)
.option(
"-y, --sourceGlob <sourceGlob>",
"glob for selecting files in source directory",
)
.option("-c, --testCmd <testCmd>", "test command")
.option("-k, --killRateMin <i>", "minimum kill rate to exit with code 0", parseInt)
.option(
"-k, --killRateMin <i>",
"minimum kill rate to exit with code 0",
parseInt,
)
.option("-u, --runner <runner>", "name of runner or runner plugin")
.parse(process.argv);

Expand All @@ -44,13 +62,13 @@ const args: OptionalPerturbConfig = R.pickBy(R.complement(R.isNil), {
});

// sync errors inside perturb don't seem to properly cause a non-zero exit w/o this
process.on("uncaughtException", (err) => {
process.on("uncaughtException", err => {
console.log("uncaught error in perturb process", err);
throw err;
});

// sync errors inside perturb don't seem to properly cause a non-zero exit w/o this
process.on("unhandledRejection", (err) => {
process.on("unhandledRejection", err => {
throw err;
});

Expand All @@ -65,9 +83,17 @@ process.on("unhandledRejection", (err) => {
if (config.killRateMin === 0) return;

if (killRate < config.killRateMin) {
console.error(`❌ Mutant kill rate was ${killRate} which is below minimum acceptable value ${config.killRateMin}`)
console.error(
`❌ Mutant kill rate was ${killRate} which is below minimum acceptable value ${
config.killRateMin
}`,
);
process.exitCode = 1;
} else {
console.log(`✅ Mutant kill rate was ${killRate} which is above minimum acceptable value ${config.killRateMin}`)
console.log(
`✅ Mutant kill rate was ${killRate} which is above minimum acceptable value ${
config.killRateMin
}`,
);
}
})();
})();
9 changes: 6 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as R from "ramda";
import * as Bluebird from "bluebird";
import pMapSeries from "p-map-series";
import { spawn } from "child_process";
import * as assert from "assert";

Expand Down Expand Up @@ -96,7 +96,7 @@ export default async function perturb(inputCfg: OptionalPerturbConfig) {
}

// run the mutatnts and gather the results
const results: RunnerResult[] = await Bluebird.mapSeries(mutants, handler);
const results: RunnerResult[] = await pMapSeries(mutants, handler);

const duration = (Date.now() - start) / 1000;
console.log(
Expand Down Expand Up @@ -124,7 +124,10 @@ export default async function perturb(inputCfg: OptionalPerturbConfig) {
}
}

function makeMutantHandler(Runner: RunnerPluginConstructor, reporter: ReporterPlugin) {
function makeMutantHandler(
Runner: RunnerPluginConstructor,
reporter: ReporterPlugin,
) {
return async function handler(mutant: Mutant): Promise<RunnerResult> {
const runner = new Runner(mutant);
await runner.setup();
Expand Down
49 changes: 0 additions & 49 deletions src/reporters/delta.ts

This file was deleted.

38 changes: 10 additions & 28 deletions src/reporters/diff.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
const chalk = require("chalk");
import * as R from "ramda";
import chalk from "chalk";
import { diffLines } from "diff";
import { sentence } from "change-case";

import delta from "./delta";
import { stats, delta, identifier } from "./helpers";

import {
ReporterPlugin,
RunnerResult,
Expand All @@ -15,37 +14,29 @@ const plugin: ReporterPlugin = {
name: "diff",
type: "reporter",
onResult(r: RunnerResult) {
console.log(generateReport(r));
console.log(resultDiff(r));
},
onFinish(rs: RunnerResult[], cfg: PerturbConfig, m?: PerturbMetadata) {
const [killed] = R.partition(r => r.error, rs);
const total = rs.length;
const killCount = killed.length;
const killRate = Number((killCount / total).toFixed(4)) * 100;
console.log(`Total: ${total}. Killed: ${killCount}. Rate: ${killRate}%`);
const { total, killed, rate } = stats(rs);
console.log(`Total: ${total}. Killed: ${killed}. Rate: ${rate}%`);
delta(rs, cfg);
},
};
export default plugin;

function generateReport(r: RunnerResult): string {
function resultDiff(r: RunnerResult): string {
const plus = "+ ";
const minus = "- ";
const alive = "#ALIVE: ";
const dead = "#DEAD: ";

const id = identifier(r);

// TODO: shorter output format for killed?

// if (r.error) {
// return chalk.gray(id);
// }

const title = r.error
? chalk.gray(dead + id)
: chalk.red.underline(alive + id);

return [
title,
r.error ? chalk.gray(id) : chalk.red.underline(id),
...generateDiff(r).map((entry: any) => {
const color = r.error ? "gray" : entry.added ? "green" : "red";
const sign = entry.added ? plus : minus;
Expand All @@ -65,12 +56,3 @@ function generateDiff(r: RunnerResult) {
(node: any) => node.added || node.removed,
);
}

function identifier(r: RunnerResult) {
const loc = r.loc.start.line + "," + r.loc.start.column;

// hack :/
const file = r.sourceFile.split(".perturb")[1];

return sentence(r.mutatorName) + " " + file + "@" + loc;
}
62 changes: 62 additions & 0 deletions src/reporters/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import * as fs from "fs";
import * as path from "path";

import { RunnerResult, PerturbConfig } from "../types";

export interface Stats {
total: number;
killed: number;
rate: number;
}

export function stats(results: RunnerResult[]): Stats {
const killed = results.filter(r => r.error).length;
const total = results.length;
return {
total,
killed,
rate: Number((killed / total).toFixed(4)) * 100,
};
}

export function identifier(r: RunnerResult, includeErrorMessage = false) {
const loc = r.loc.start.line + "," + r.loc.start.column;
return [
r.error ? "#DEAD:" : "#ALIVE:",
r.mutatorName,
r.sourceFile.split(".perturb")[1],
`@${loc}`,
(includeErrorMessage && r.error && r.error.message) || "",
].join(" ");
}

// configurable?
const RECORD_FILE = path.join(__dirname, "../../run-record.json");

function writeResult(last: any, s: Stats, root: string) {
last[root] = s;
try {
fs.writeFileSync(RECORD_FILE, JSON.stringify(last));
} catch (e) {
// log error?
}
}

export function delta(rs: RunnerResult[], cfg: PerturbConfig) {
const s = stats(rs);
let record: any = {};
try {
record = require(RECORD_FILE);
if (record[cfg.projectRoot]) {
console.log("change in total:", s.total - record[cfg.projectRoot].total);
console.log(
"change in killed:",
s.killed - record[cfg.projectRoot].killed,
);
}
} catch (e) {
// file doesn't exist
} finally {
writeResult(record, s, cfg.projectRoot);
}
}
12 changes: 1 addition & 11 deletions src/reporters/name.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { ReporterPlugin, RunnerResult } from "../types";
import { identifier } from "./helpers";

const plugin: ReporterPlugin = {
name: "names",
Expand All @@ -14,14 +15,3 @@ const plugin: ReporterPlugin = {
};

export default plugin;

function identifier(r: RunnerResult) {
const loc = r.loc.start.line + "," + r.loc.start.column;
return [
r.error ? "DEAD: " : "ALIVE:",
r.mutatorName,
r.sourceFile.split(".perturb")[1],
`@${loc}`,
(r.error && r.error.message) || "",
].join(" ");
}
Loading

0 comments on commit dd00c0f

Please sign in to comment.