@t09tanaka/test-gates 0.5.0 → 0.5.2
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/CHANGELOG.md +12 -0
- package/dist/cli.js +69 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.2
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- `selfcheck --jobs` really no longer keeps every other control apart because of the word `require` in a string, a template, a comment or a regular expression. 0.5.1 fixed the reason given for a spec, but the plan of which controls run on their own still looked at the whole text.
|
|
8
|
+
|
|
9
|
+
## 0.5.1
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- `selfcheck --jobs` no longer keeps every other control apart because the word `require` appears inside a string, a template, a comment or a regular expression (`'sslmode=require'`, `// pass it to require`). Only code is looked at now. Handing `require` on under another name (`const r = require`) still counts as loading a module whose name is computed.
|
|
14
|
+
|
|
3
15
|
## 0.5.0
|
|
4
16
|
|
|
5
17
|
This release makes the gates quicker to check in CI: `test-gates mutation --shard <index>/<total>` splits the mutation run over parallel jobs, and `selfcheck --jobs` runs more controls side by side. Nothing changes for a run without the new option:
|
package/dist/cli.js
CHANGED
|
@@ -5447,6 +5447,9 @@ var REACHES = [
|
|
|
5447
5447
|
];
|
|
5448
5448
|
var COMPUTED_LOAD = /(?:require|import)\((?!['"])|\brequire(?!\(|\.resolve\b|[\w$])|\bimport\.meta\.glob\b/;
|
|
5449
5449
|
var COMPUTED = "loads a module whose name is computed";
|
|
5450
|
+
function loadsComputed(source) {
|
|
5451
|
+
return COMPUTED_LOAD.test(withoutLiterals(source).replace(/\s/g, ""));
|
|
5452
|
+
}
|
|
5450
5453
|
var STRING = /(^|[:,([={?+&|;])(\s*)(['"])((?:\\.|(?!\3)[^\\\n])*)\3(?=\s*(?:[,}\]);:+?&|]|$))/gm;
|
|
5451
5454
|
function withoutStrings(source) {
|
|
5452
5455
|
return source.replace(
|
|
@@ -5458,6 +5461,70 @@ function withoutStrings(source) {
|
|
|
5458
5461
|
)
|
|
5459
5462
|
);
|
|
5460
5463
|
}
|
|
5464
|
+
var BEFORE_REGEX = /(?:^|[(,=:[!&|?{};+\-*%<>~^]|\b(?:return|typeof|case|in|of|void|delete|throw|new|yield|await))\s*$/;
|
|
5465
|
+
var COMMENT_OR_STRING = /\/\/[^\n]*|\/\*[\s\S]*?(?:\*\/|$)|(['"])(?:\\.|(?!\1)[^\\\n])*\1?/y;
|
|
5466
|
+
var REGEX = /\/(?:\\.|\[(?:\\.|[^\]\\\n])*\]?|[^/\\\n[])*\/?/y;
|
|
5467
|
+
var TEMPLATE_TEXT = /(?:\\[\s\S]|[^`\\$]|\$(?!\{))*/y;
|
|
5468
|
+
function withoutLiterals(source) {
|
|
5469
|
+
let out = "";
|
|
5470
|
+
let i = 0;
|
|
5471
|
+
const blank = (text) => text.replace(/[^\n]/g, " ");
|
|
5472
|
+
const enclosed = (literal) => {
|
|
5473
|
+
const closed = literal.length > 1 && literal.endsWith(literal.charAt(0));
|
|
5474
|
+
return literal.charAt(0) + blank(literal.slice(1, closed ? -1 : void 0)) + (closed ? literal.charAt(0) : "");
|
|
5475
|
+
};
|
|
5476
|
+
const take = (pattern) => {
|
|
5477
|
+
pattern.lastIndex = i;
|
|
5478
|
+
const found = pattern.exec(source)?.[0] ?? null;
|
|
5479
|
+
if (found !== null) {
|
|
5480
|
+
i += found.length;
|
|
5481
|
+
}
|
|
5482
|
+
return found;
|
|
5483
|
+
};
|
|
5484
|
+
const code = (inBraces) => {
|
|
5485
|
+
while (i < source.length) {
|
|
5486
|
+
const c = source[i];
|
|
5487
|
+
const literal = take(COMMENT_OR_STRING);
|
|
5488
|
+
if (literal !== null) {
|
|
5489
|
+
out += literal.startsWith("/") ? blank(literal) : enclosed(literal);
|
|
5490
|
+
} else if (c === "/" && BEFORE_REGEX.test(out)) {
|
|
5491
|
+
out += enclosed(take(REGEX));
|
|
5492
|
+
} else if (c === "`") {
|
|
5493
|
+
i += 1;
|
|
5494
|
+
out += "`";
|
|
5495
|
+
template();
|
|
5496
|
+
} else if (c === "}" && inBraces) {
|
|
5497
|
+
return;
|
|
5498
|
+
} else if (c === "{" && inBraces) {
|
|
5499
|
+
braces("{");
|
|
5500
|
+
} else {
|
|
5501
|
+
out += c;
|
|
5502
|
+
i += 1;
|
|
5503
|
+
}
|
|
5504
|
+
}
|
|
5505
|
+
};
|
|
5506
|
+
const braces = (open) => {
|
|
5507
|
+
i += open.length;
|
|
5508
|
+
out += open;
|
|
5509
|
+
code(true);
|
|
5510
|
+
if (i < source.length) {
|
|
5511
|
+
i += 1;
|
|
5512
|
+
out += "}";
|
|
5513
|
+
}
|
|
5514
|
+
};
|
|
5515
|
+
const template = () => {
|
|
5516
|
+
out += blank(take(TEMPLATE_TEXT));
|
|
5517
|
+
if (source.startsWith("${", i)) {
|
|
5518
|
+
braces("${");
|
|
5519
|
+
template();
|
|
5520
|
+
} else if (i < source.length) {
|
|
5521
|
+
i += 1;
|
|
5522
|
+
out += "`";
|
|
5523
|
+
}
|
|
5524
|
+
};
|
|
5525
|
+
code(false);
|
|
5526
|
+
return out;
|
|
5527
|
+
}
|
|
5461
5528
|
var PURE_BUILTINS = [
|
|
5462
5529
|
"assert",
|
|
5463
5530
|
"assert/strict",
|
|
@@ -5473,13 +5540,12 @@ var PURE_BUILTINS = [
|
|
|
5473
5540
|
];
|
|
5474
5541
|
var RUNNER_PACKAGES = ["vitest", "@jest/globals"];
|
|
5475
5542
|
function reachesOutside(file, trusted) {
|
|
5476
|
-
const dense = file.source.replace(/\s/g, "");
|
|
5477
5543
|
const code = withoutStrings(file.source).replace(/\s/g, "");
|
|
5478
5544
|
const mark = REACHES.find((text) => code.includes(text));
|
|
5479
5545
|
if (mark !== void 0) {
|
|
5480
5546
|
return `uses ${mark.replace(/[.?[(:]+$/, "")}`;
|
|
5481
5547
|
}
|
|
5482
|
-
if (
|
|
5548
|
+
if (loadsComputed(file.source)) {
|
|
5483
5549
|
return COMPUTED;
|
|
5484
5550
|
}
|
|
5485
5551
|
for (const { specifier, builtin } of file.imports) {
|
|
@@ -5519,7 +5585,7 @@ function jobsPlan(input) {
|
|
|
5519
5585
|
const reaches = loaded.flatMap((file) => {
|
|
5520
5586
|
const reach = reachesOutside(file, input.trusted);
|
|
5521
5587
|
const said = reach === null ? [] : [`${file.path} ${reach}`];
|
|
5522
|
-
if (!
|
|
5588
|
+
if (!loadsComputed(file.source)) {
|
|
5523
5589
|
return said;
|
|
5524
5590
|
}
|
|
5525
5591
|
computed = true;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t09tanaka/test-gates",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Test gates for the code that must not be wrong: per-file 100% coverage as the floor, mutation testing with a per-mutant allow list as the real check.",
|
|
5
5
|
"author": "t09tanaka",
|
|
6
6
|
"license": "MIT",
|