oxmutate 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/binding/oxmutate.win32-x64-msvc.node +0 -0
- package/dist/cli.js +3 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +1 -0
- package/dist/coordinator.js +2 -2
- package/dist/reports.js +18 -2
- package/package.json +1 -1
|
Binary file
|
package/dist/cli.js
CHANGED
|
@@ -58,6 +58,8 @@ function overridesFrom(o, root) {
|
|
|
58
58
|
overrides.timeoutMS = o['mutantTimeout'];
|
|
59
59
|
if (o['strykerCompat'] === true)
|
|
60
60
|
overrides.strykerCompat = true;
|
|
61
|
+
if (o['ignoreStatic'] === true)
|
|
62
|
+
overrides.ignoreStatic = true;
|
|
61
63
|
if (o['incremental'] === true)
|
|
62
64
|
overrides.incremental = true;
|
|
63
65
|
if (typeof o['flakyReruns'] === 'number')
|
|
@@ -87,6 +89,7 @@ const runCommand = defineCommand({
|
|
|
87
89
|
concurrency: { type: 'number', description: 'worker processes (default: cores - 1, at most 8)' },
|
|
88
90
|
mutantTimeout: { type: 'number', description: 'absolute slack per mutant, ms (default 500; Stryker 5000)' },
|
|
89
91
|
strykerCompat: { type: 'boolean', description: 'reproduce Stryker 10.0.0 skips (no mutants inside `as` casts or enums)' },
|
|
92
|
+
ignoreStatic: { type: 'boolean', description: 'skip static mutants (module-level code): faster, and the score leaves them out' },
|
|
90
93
|
incremental: { type: 'boolean', description: 'reuse verdicts whose source and covering tests did not change' },
|
|
91
94
|
flakyReruns: { type: 'number', description: 're-runs for verdicts with nondeterministic tests (default 2; 0 disables)' },
|
|
92
95
|
reporter: { type: 'string', description: 'comma-separated: clear-text, json, sarif, html (default clear-text,json)' },
|
package/dist/config.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface Thresholds {
|
|
|
6
6
|
/** Fail the run (exit 1) below this score. `null`: never fail on score. */
|
|
7
7
|
break: number | null;
|
|
8
8
|
}
|
|
9
|
+
/** Why a static mutant is Ignored under `ignoreStatic`; the summary counts them by it. */
|
|
10
|
+
export declare const IGNORE_STATIC_REASON = "static mutant (ignoreStatic)";
|
|
9
11
|
export interface Options {
|
|
10
12
|
root: string;
|
|
11
13
|
mutate: string[];
|
package/dist/config.js
CHANGED
|
@@ -3,6 +3,7 @@ import { availableParallelism } from 'node:os';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { pathToFileURL } from 'node:url';
|
|
5
5
|
import { resolveEsm } from './resolve.js';
|
|
6
|
+
export const IGNORE_STATIC_REASON = 'static mutant (ignoreStatic)';
|
|
6
7
|
const NOT_NEEDED = {
|
|
7
8
|
inPlace: 'oxmutate never copies or rewrites the project; instrumented sources are served from memory',
|
|
8
9
|
tempDirName: 'no sandbox directory exists',
|
package/dist/coordinator.js
CHANGED
|
@@ -5,7 +5,7 @@ import path from 'node:path';
|
|
|
5
5
|
import { ambientRuntime, run as spawn } from 'bellpull';
|
|
6
6
|
import { checkSurvivors } from './checker.js';
|
|
7
7
|
import { runCommandMutants } from './command-runner.js';
|
|
8
|
-
import { disables } from './config.js';
|
|
8
|
+
import { IGNORE_STATIC_REASON, disables } from './config.js';
|
|
9
9
|
import { rangeDisables } from './directives.js';
|
|
10
10
|
import { guardDisk, isClean } from './diskguard.js';
|
|
11
11
|
import { globToRegExp, matchFiles } from './files.js';
|
|
@@ -271,7 +271,7 @@ export async function run(options) {
|
|
|
271
271
|
m.static = true;
|
|
272
272
|
if (options.ignoreStatic) {
|
|
273
273
|
m.status = 'Ignored';
|
|
274
|
-
m.statusReason =
|
|
274
|
+
m.statusReason = IGNORE_STATIC_REASON;
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
277
|
}
|
package/dist/reports.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { IGNORE_STATIC_REASON } from './config.js';
|
|
4
5
|
export const VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
|
|
5
6
|
const REPLACEMENT_WIDTH = 60;
|
|
6
7
|
const ELLIPSIS = '...';
|
|
@@ -116,10 +117,25 @@ function frozenLine(r) {
|
|
|
116
117
|
const sign = f.delta >= 0 ? '+' : '';
|
|
117
118
|
return [` frozen oracle vs ${f.base}: ${f.headScore.toFixed(2)}% with the change's tests, ${f.baseScore.toFixed(2)}% with the base's (${sign}${f.delta.toFixed(2)}), ${String(f.weakened.length)} mutant(s) the change stopped detecting`];
|
|
118
119
|
}
|
|
119
|
-
|
|
120
|
+
const STATIC_SHARE_WORTH_SAYING = 0.5;
|
|
121
|
+
const PERCENT = 100;
|
|
122
|
+
function staticLine(r) {
|
|
123
|
+
const statics = r.mutants.filter((m) => m.static);
|
|
124
|
+
if (statics.length === 0)
|
|
125
|
+
return [];
|
|
126
|
+
const ignored = statics.filter((m) => m.statusReason === IGNORE_STATIC_REASON).length;
|
|
127
|
+
if (ignored > 0)
|
|
128
|
+
return [` static mutants: ${String(ignored)} ignored (ignoreStatic), not scored`];
|
|
129
|
+
const share = r.stats.wallMs > 0 ? r.stats.staticMs / r.stats.wallMs : 0;
|
|
130
|
+
const hint = share >= STATIC_SHARE_WORTH_SAYING ? '; --ignore-static skips them, and the score then leaves them out' : '';
|
|
131
|
+
return [` static mutants: ${String(statics.length)} decided in ${(r.stats.staticMs / MS_PER_S).toFixed(1)} s, ${(share * PERCENT).toFixed(0)}% of the run${hint}`];
|
|
132
|
+
}
|
|
133
|
+
function whereItWent(r) {
|
|
134
|
+
const s = r.stats;
|
|
120
135
|
const lines = [];
|
|
121
136
|
if (s.warmUnitMs > 0)
|
|
122
137
|
lines.push(` warm servers ran ${(s.warmUnitMs / MS_PER_S).toFixed(1)} s, ${(s.warmArmedMs / MS_PER_S).toFixed(1)} s of it inside test runs`);
|
|
138
|
+
lines.push(...staticLine(r));
|
|
123
139
|
const c = s.isolatedByCause;
|
|
124
140
|
const causes = [`static ${String(c.static)}`, `stopped ${String(c.stopped)}`, `unfinished ${String(c.unfinished)}`, `re-run ${String(c.rerun)}`, `survivors confirmed ${String(c.confirm)}`, `flaky ${String(c.flaky)}`];
|
|
125
141
|
if (s.isolatedRuns > 0)
|
|
@@ -142,7 +158,7 @@ export function textSummary(r, opts = {}) {
|
|
|
142
158
|
const corrected = corrections(s);
|
|
143
159
|
if (corrected.length)
|
|
144
160
|
lines.push(` corrected: ${corrected.join(' · ')}`);
|
|
145
|
-
lines.push(...whereItWent(
|
|
161
|
+
lines.push(...whereItWent(r));
|
|
146
162
|
lines.push(...frozenLine(r));
|
|
147
163
|
lines.push(...specLines(r));
|
|
148
164
|
const survivors = r.mutants.filter((m) => m.status === 'Survived' || m.status === 'NoCoverage');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oxmutate",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Mutation testing for JavaScript and TypeScript on the oxc engine, run warm inside the project's own Vitest, with CI lanes, SARIF and an agent surface. No dependency outside the burgee family. A Stryker migration path.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ofri Peretz <ofriperetzdev@gmail.com>",
|