apex-mutation-testing 1.6.1 → 1.7.1
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/README.md +35 -4
- package/lib/commands/apex/mutation/test/run.d.ts +1 -0
- package/lib/commands/apex/mutation/test/run.js +4 -0
- package/lib/commands/apex/mutation/test/run.js.map +1 -1
- package/lib/mutator/unaryOperatorInsertionMutator.d.ts +1 -1
- package/lib/mutator/unaryOperatorInsertionMutator.js +12 -17
- package/lib/mutator/unaryOperatorInsertionMutator.js.map +1 -1
- package/lib/service/configReader.js +1 -0
- package/lib/service/configReader.js.map +1 -1
- package/lib/service/exactColoring.d.ts +25 -0
- package/lib/service/exactColoring.js +143 -0
- package/lib/service/exactColoring.js.map +1 -0
- package/lib/service/groupExecutor.d.ts +29 -0
- package/lib/service/groupExecutor.js +194 -0
- package/lib/service/groupExecutor.js.map +1 -0
- package/lib/service/mutantGenerator.d.ts +2 -0
- package/lib/service/mutantGenerator.js +26 -1
- package/lib/service/mutantGenerator.js.map +1 -1
- package/lib/service/mutationGrouper.d.ts +22 -0
- package/lib/service/mutationGrouper.js +130 -0
- package/lib/service/mutationGrouper.js.map +1 -0
- package/lib/service/mutationLocation.d.ts +12 -0
- package/lib/service/mutationLocation.js +54 -0
- package/lib/service/mutationLocation.js.map +1 -0
- package/lib/service/mutationTestingService.d.ts +3 -6
- package/lib/service/mutationTestingService.js +71 -177
- package/lib/service/mutationTestingService.js.map +1 -1
- package/lib/service/timeUtils.d.ts +1 -0
- package/lib/service/timeUtils.js +8 -0
- package/lib/service/timeUtils.js.map +1 -1
- package/lib/type/ApexMutationParameter.d.ts +1 -0
- package/messages/apex.mutation.test.run.md +13 -1
- package/npm-shrinkwrap.json +2487 -4351
- package/oclif.manifest.json +7 -1
- package/package.json +18 -15
package/README.md
CHANGED
|
@@ -22,7 +22,7 @@ sf apex mutation test run --apex-class MyClass --test-class MyClassTest
|
|
|
22
22
|
|
|
23
23
|
## What is it mutation testing ?
|
|
24
24
|
|
|
25
|
-
Mutation testing is a software testing technique that evaluates the quality of your test suite by introducing small changes (mutations) to your code and checking if your tests can detect these changes. It helps identify weaknesses in your test coverage by measuring how effectively your tests can catch intentional bugs. cf [wikipedia](https://en.wikipedia.org/wiki/Mutation_testing)
|
|
25
|
+
Mutation testing is a software testing technique that evaluates the quality of your test suite by introducing small changes (mutations) to your code and checking if your tests can detect these changes. It helps identify weaknesses in your test coverage by measuring how effectively your tests can catch intentional bugs. cf [wikipedia](https://en.wikipedia.org/wiki/Mutation_testing)
|
|
26
26
|
|
|
27
27
|
The apex-mutation-testing plugin implements this technique for Salesforce Apex code by:
|
|
28
28
|
|
|
@@ -113,7 +113,8 @@ The config file supports the following attributes:
|
|
|
113
113
|
},
|
|
114
114
|
"threshold": 80,
|
|
115
115
|
"skipPatterns": ["System\\.debug", "Logger\\."],
|
|
116
|
-
"lines": ["1-10", "25-30", "42"]
|
|
116
|
+
"lines": ["1-10", "25-30", "42"],
|
|
117
|
+
"mutationGrouping": true
|
|
117
118
|
}
|
|
118
119
|
```
|
|
119
120
|
|
|
@@ -126,6 +127,7 @@ The config file supports the following attributes:
|
|
|
126
127
|
| `threshold` | `number` | Minimum mutation score (0–100) required for the command to succeed |
|
|
127
128
|
| `skipPatterns` | `string[]` | RE2 regex patterns to skip lines from mutation (e.g., `System\\.debug`) |
|
|
128
129
|
| `lines` | `string[]` | Line ranges to restrict mutation to (e.g., `1-10`, `42`) |
|
|
130
|
+
| `mutationGrouping` | `boolean` | Pack mutations with disjoint tests into one deploy + run (clique → DSATUR → exact coloring). Off by default. |
|
|
129
131
|
|
|
130
132
|
**Mutual exclusivity:** You cannot specify both `include` and `exclude` within the same group.
|
|
131
133
|
For example, setting both `mutators.include` and `mutators.exclude` will result in an error.
|
|
@@ -217,6 +219,31 @@ Config file equivalent:
|
|
|
217
219
|
}
|
|
218
220
|
```
|
|
219
221
|
|
|
222
|
+
#### Mutation Grouping
|
|
223
|
+
|
|
224
|
+
Run multiple independent mutations in a single deployment + test run by passing `--mutation-grouping`. The flag turns on a three-stage pipeline:
|
|
225
|
+
|
|
226
|
+
1. **Lower-bound clique** — for every test method, gather the mutations it covers; the largest such set is a clique in the conflict graph and a free lower bound on the chromatic number.
|
|
227
|
+
2. **DSATUR** — pre-color the witness clique, then partition the remaining mutations with the strongest polynomial-time graph-coloring heuristic (Brélaz 1979). Two mutations share a group iff their covering tests are pairwise disjoint.
|
|
228
|
+
3. **Exact backtracking coloring** — binary-search for the chromatic number using DSATUR-style backtracking, seeded by the witness clique. Confirms DSATUR was already optimal or finds a strictly smaller partition. No external solver, no runtime dependency — pure TypeScript.
|
|
229
|
+
|
|
230
|
+
Each group is then deployed once and its union of covering tests run once; per-method test outcomes are reverse-mapped back to individual mutations. This reduces the number of Tooling-API class updates and async test-run kickoffs (the network-bound dominant cost) without changing test execution time. Off by default.
|
|
231
|
+
|
|
232
|
+
```sh
|
|
233
|
+
# Enable mutation grouping
|
|
234
|
+
sf apex mutation test run --apex-class MyClass --test-class MyClassTest --mutation-grouping
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Config file equivalent:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"mutationGrouping": true
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
If a batched deploy or test run fails, the affected group automatically falls back to per-mutant evaluation — so worst case is identical to today's behavior plus one wasted batch attempt.
|
|
246
|
+
|
|
220
247
|
##### Diff-Based Mutation Testing with Git
|
|
221
248
|
|
|
222
249
|
You can derive line ranges from `git diff` to focus mutation testing on recently changed code. This is particularly useful in CI pipelines to only test mutations on lines affected by a pull request.
|
|
@@ -337,7 +364,7 @@ USAGE
|
|
|
337
364
|
$ sf apex mutation test run -c <value> -t <value> -o <value> [--json] [--flags-dir <value>] [-r <value>] [-d]
|
|
338
365
|
[--include-mutators <value>... | --exclude-mutators <value>...] [--include-test-methods <value>... |
|
|
339
366
|
--exclude-test-methods <value>...] [--threshold <value>] [-s <value>...] [-l <value>...] [--config-file <value>]
|
|
340
|
-
[--api-version <value>]
|
|
367
|
+
[--mutation-grouping] [--api-version <value>]
|
|
341
368
|
|
|
342
369
|
FLAGS
|
|
343
370
|
-c, --apex-class=<value> (required) Apex class name to mutate
|
|
@@ -356,6 +383,10 @@ FLAGS
|
|
|
356
383
|
--exclude-test-methods=<value>... Test method names to exclude
|
|
357
384
|
--include-mutators=<value>... Mutator names to include (e.g. ArithmeticOperator, BoundaryCondition)
|
|
358
385
|
--include-test-methods=<value>... Test method names to include
|
|
386
|
+
--mutation-grouping Group mutations whose covering tests are disjoint into a single deploy + test
|
|
387
|
+
run. Reduces deployments and async test-run kickoffs at the cost of larger
|
|
388
|
+
blast radius on compile errors. Runs the full pipeline: test-induced clique
|
|
389
|
+
lower bound → DSATUR heuristic → exact backtracking coloring. Off by default.
|
|
359
390
|
--threshold=<value> Minimum mutation score (0-100) required for the command to succeed
|
|
360
391
|
|
|
361
392
|
GLOBAL FLAGS
|
|
@@ -381,7 +412,7 @@ EXAMPLES
|
|
|
381
412
|
$ sf apex mutation test run --apex-class MyClass --test-class MyClassTest --dry-run
|
|
382
413
|
```
|
|
383
414
|
|
|
384
|
-
_See code: [src/commands/apex/mutation/test/run.ts](https://github.com/scolladon/apex-mutation-testing/blob/v1.
|
|
415
|
+
_See code: [src/commands/apex/mutation/test/run.ts](https://github.com/scolladon/apex-mutation-testing/blob/v1.7.1/src/commands/apex/mutation/test/run.ts)_
|
|
385
416
|
<!-- commandsstop -->
|
|
386
417
|
<!-- markdownlint-enable MD040 -->
|
|
387
418
|
|
|
@@ -19,6 +19,7 @@ export default class ApexMutationTest extends SfCommand<ApexMutationTestResult>
|
|
|
19
19
|
'skip-patterns': import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
20
|
lines: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
21
|
'config-file': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
|
+
'mutation-grouping': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
23
|
'target-org': import("@oclif/core/interfaces").OptionFlag<import("@salesforce/core").Org, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
24
|
'api-version': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
25
|
};
|
|
@@ -71,6 +71,9 @@ export default class ApexMutationTest extends SfCommand {
|
|
|
71
71
|
summary: messages.getMessage('flags.config-file.summary'),
|
|
72
72
|
exists: true,
|
|
73
73
|
}),
|
|
74
|
+
'mutation-grouping': Flags.boolean({
|
|
75
|
+
summary: messages.getMessage('flags.mutation-grouping.summary'),
|
|
76
|
+
}),
|
|
74
77
|
'target-org': Flags.requiredOrg(),
|
|
75
78
|
'api-version': Flags.orgApiVersion(),
|
|
76
79
|
};
|
|
@@ -90,6 +93,7 @@ export default class ApexMutationTest extends SfCommand {
|
|
|
90
93
|
skipPatterns: flags['skip-patterns'],
|
|
91
94
|
lines: flags['lines'],
|
|
92
95
|
configFile: flags['config-file'],
|
|
96
|
+
mutationGrouping: flags['mutation-grouping'],
|
|
93
97
|
};
|
|
94
98
|
const configReader = new ConfigReader();
|
|
95
99
|
const resolvedParameters = await configReader.resolve(parameters);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../../src/commands/apex/mutation/test/run.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../../../src/commands/apex/mutation/test/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,5 +4,5 @@ import { BaseListener } from './baseListener.js';
|
|
|
4
4
|
export declare class UnaryOperatorInsertionMutator extends BaseListener {
|
|
5
5
|
constructor(typeRegistry?: TypeRegistry);
|
|
6
6
|
enterPrimaryExpression(ctx: ParserRuleContext): void;
|
|
7
|
-
private
|
|
7
|
+
private isNonAssignableReceiver;
|
|
8
8
|
}
|
|
@@ -1,24 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ArrayExpressionContext, DotExpressionContext, IdPrimaryContext, } from 'apex-parser';
|
|
2
2
|
import { BaseListener } from './baseListener.js';
|
|
3
3
|
export class UnaryOperatorInsertionMutator extends BaseListener {
|
|
4
4
|
constructor(typeRegistry) {
|
|
5
5
|
super(typeRegistry);
|
|
6
6
|
}
|
|
7
7
|
enterPrimaryExpression(ctx) {
|
|
8
|
+
if (this.isNonAssignableReceiver(ctx)) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
8
11
|
if (ctx.childCount !== 1) {
|
|
9
12
|
return;
|
|
10
13
|
}
|
|
11
14
|
const primary = ctx.getChild(0);
|
|
12
|
-
if (!(primary instanceof
|
|
15
|
+
if (!(primary instanceof IdPrimaryContext)) {
|
|
13
16
|
return;
|
|
14
17
|
}
|
|
15
18
|
const text = primary.text;
|
|
16
|
-
if (this.isLiteral(text)) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
if (text === 'this' || text === 'super') {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
19
|
if (this.typeRegistry) {
|
|
23
20
|
const methodName = this.getEnclosingMethodName(ctx);
|
|
24
21
|
if (methodName && !this.typeRegistry.isNumericOperand(methodName, text)) {
|
|
@@ -39,15 +36,13 @@ export class UnaryOperatorInsertionMutator extends BaseListener {
|
|
|
39
36
|
this.createMutation(ctx.start, ctx.stop, text, `--${text}`);
|
|
40
37
|
}
|
|
41
38
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
return true;
|
|
50
|
-
return false;
|
|
39
|
+
// The receiver of a dot (`a.b`) or array (`a[i]`) access is not an assignable
|
|
40
|
+
// target: `a++.b` / `a++[i]` are invalid. The index of `a[i]` is assignable, so
|
|
41
|
+
// only the receiver (first child) of an ArrayExpression is rejected.
|
|
42
|
+
isNonAssignableReceiver(ctx) {
|
|
43
|
+
const parent = ctx.parent;
|
|
44
|
+
return (parent instanceof DotExpressionContext ||
|
|
45
|
+
(parent instanceof ArrayExpressionContext && parent.expression(0) === ctx));
|
|
51
46
|
}
|
|
52
47
|
}
|
|
53
48
|
//# sourceMappingURL=unaryOperatorInsertionMutator.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unaryOperatorInsertionMutator.js","sourceRoot":"","sources":["../../src/mutator/unaryOperatorInsertionMutator.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"unaryOperatorInsertionMutator.js","sourceRoot":"","sources":["../../src/mutator/unaryOperatorInsertionMutator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,MAAM,OAAO,6BAA8B,SAAQ,YAAY;IAC7D,YAAY,YAA2B;QACrC,KAAK,CAAC,YAAY,CAAC,CAAA;IACrB,CAAC;IAED,sBAAsB,CAAC,GAAsB;QAC3C,IAAI,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,EAAE,CAAC;YACtC,OAAM;QACR,CAAC;QAED,IAAI,GAAG,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;YACzB,OAAM;QACR,CAAC;QAED,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QAC/B,IAAI,CAAC,CAAC,OAAO,YAAY,gBAAgB,CAAC,EAAE,CAAC;YAC3C,OAAM;QACR,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;QAEzB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,MAAM,UAAU,GAAG,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAA;YACnD,IAAI,UAAU,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC;gBACxE,OAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;YAC1B,gFAAgF;YAChF,qEAAqE;YACrE,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAA;YAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,CAAA;YAC7D,CAAC;YACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAA;YAC3D,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,IAAI,CAAC,CAAA;YAC7D,CAAC;YACD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,gFAAgF;IAChF,qEAAqE;IAC7D,uBAAuB,CAAC,GAAsB;QACpD,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAA;QACzB,OAAO,CACL,MAAM,YAAY,oBAAoB;YACtC,CAAC,MAAM,YAAY,sBAAsB,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAC3E,CAAA;IACH,CAAC;CACF"}
|
|
@@ -14,6 +14,7 @@ export class ConfigReader {
|
|
|
14
14
|
threshold: parameter.threshold ?? fileConfig?.threshold,
|
|
15
15
|
skipPatterns: parameter.skipPatterns ?? fileConfig?.skipPatterns,
|
|
16
16
|
lines: parameter.lines ?? fileConfig?.lines,
|
|
17
|
+
mutationGrouping: parameter.mutationGrouping ?? fileConfig?.mutationGrouping,
|
|
17
18
|
};
|
|
18
19
|
this.validate(resolved);
|
|
19
20
|
return resolved;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"configReader.js","sourceRoot":"","sources":["../../src/service/configReader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAE3C,OAAO,GAAG,MAAM,KAAK,CAAA;AAMrB,MAAM,mBAAmB,GAAG,wBAAwB,CAAA;
|
|
1
|
+
{"version":3,"file":"configReader.js","sourceRoot":"","sources":["../../src/service/configReader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const buildAdjacency: (tests: ReadonlyArray<Set<string>>) => number[][];
|
|
2
|
+
export declare const tryKColoring: (adjacency: ReadonlyArray<ReadonlyArray<number>>, n: number, k: number, witness: ReadonlyArray<number>) => number[] | null;
|
|
3
|
+
export type SolveColoringInput = {
|
|
4
|
+
adjacency: ReadonlyArray<ReadonlyArray<number>>;
|
|
5
|
+
n: number;
|
|
6
|
+
lowerBound: number;
|
|
7
|
+
dsaturColors: number;
|
|
8
|
+
witness: ReadonlyArray<number>;
|
|
9
|
+
dsaturColoring: ReadonlyArray<number>;
|
|
10
|
+
};
|
|
11
|
+
export type SolveColoringResult = {
|
|
12
|
+
coloring: ReadonlyArray<number>;
|
|
13
|
+
lowerBound: number;
|
|
14
|
+
optimal: boolean;
|
|
15
|
+
};
|
|
16
|
+
type ExactDecision = {
|
|
17
|
+
useGroups: 'exact';
|
|
18
|
+
suffix: string;
|
|
19
|
+
} | {
|
|
20
|
+
useGroups: 'dsatur';
|
|
21
|
+
suffix: string;
|
|
22
|
+
};
|
|
23
|
+
export declare const decideExactOutcome: (exact: SolveColoringResult, dsaturColors: number) => ExactDecision;
|
|
24
|
+
export declare const solveColoring: (input: SolveColoringInput) => SolveColoringResult;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// Exact graph k-coloring via DSATUR-style backtracking. Pure TypeScript,
|
|
2
|
+
// no external SAT solver — at our scale (n ≤ 200) the witness clique
|
|
3
|
+
// from D2 already fixes the most-constrained vertices, so the backtracking
|
|
4
|
+
// search converges fast on real Apex graphs.
|
|
5
|
+
// Build the conflict-graph adjacency list. Vertex i and j are adjacent iff
|
|
6
|
+
// `tests(i) ∩ tests(j) ≠ ∅`. Same definition as in mutationGrouper; lives
|
|
7
|
+
// here so the exact-coloring driver and the DSATUR driver share one source
|
|
8
|
+
// of truth.
|
|
9
|
+
export const buildAdjacency = (tests) => {
|
|
10
|
+
const n = tests.length;
|
|
11
|
+
const adjacency = Array.from({ length: n }, () => []);
|
|
12
|
+
for (let i = 0; i < n; ++i) {
|
|
13
|
+
for (let j = i + 1; j < n; ++j) {
|
|
14
|
+
if (intersects(tests[i], tests[j])) {
|
|
15
|
+
adjacency[i].push(j);
|
|
16
|
+
adjacency[j].push(i);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return adjacency;
|
|
21
|
+
};
|
|
22
|
+
const intersects = (a, b) => {
|
|
23
|
+
const [small, large] = a.size <= b.size ? [a, b] : [b, a];
|
|
24
|
+
for (const t of small) {
|
|
25
|
+
if (large.has(t))
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
};
|
|
30
|
+
// Decide whether the graph admits a valid k-coloring; return one if it does,
|
|
31
|
+
// `null` otherwise. Pre-colors the witness clique (whose vertices must
|
|
32
|
+
// receive distinct colors in any valid coloring), then runs DSATUR-style
|
|
33
|
+
// backtracking on the remaining vertices: at each step, pick the most
|
|
34
|
+
// constrained uncolored vertex (highest saturation, then highest degree,
|
|
35
|
+
// then lowest input index) and try the smallest available color first.
|
|
36
|
+
export const tryKColoring = (adjacency, n, k, witness) => {
|
|
37
|
+
if (k < witness.length)
|
|
38
|
+
return null;
|
|
39
|
+
const color = new Array(n).fill(-1);
|
|
40
|
+
for (let i = 0; i < witness.length; ++i)
|
|
41
|
+
color[witness[i]] = i;
|
|
42
|
+
const degree = adjacency.map(neighbors => neighbors.length);
|
|
43
|
+
return backtrack(adjacency, n, k, color, degree);
|
|
44
|
+
};
|
|
45
|
+
const backtrack = (adjacency, n, k, color, degree) => {
|
|
46
|
+
const v = pickMostConstrained(adjacency, color, degree);
|
|
47
|
+
if (v === -1)
|
|
48
|
+
return color.slice();
|
|
49
|
+
const used = neighborColors(adjacency[v], color);
|
|
50
|
+
if (used.size >= k)
|
|
51
|
+
return null;
|
|
52
|
+
for (let c = 0; c < k; ++c) {
|
|
53
|
+
if (used.has(c))
|
|
54
|
+
continue;
|
|
55
|
+
color[v] = c;
|
|
56
|
+
// Forward checking: skip the recurse if assigning c to v would strand
|
|
57
|
+
// some uncolored neighbor (no color left for it). Catches the dead end
|
|
58
|
+
// one level earlier, dodging an entire `pickMostConstrained` scan.
|
|
59
|
+
if (!wouldStrandNeighbor(adjacency, color, v, k)) {
|
|
60
|
+
const result = backtrack(adjacency, n, k, color, degree);
|
|
61
|
+
if (result !== null)
|
|
62
|
+
return result;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
color[v] = -1;
|
|
66
|
+
return null;
|
|
67
|
+
};
|
|
68
|
+
// True iff some uncolored neighbor of `v` now has zero available colors —
|
|
69
|
+
// i.e. every color in [0, k) appears on one of its colored neighbors.
|
|
70
|
+
const wouldStrandNeighbor = (adjacency, color, v, k) => {
|
|
71
|
+
for (const u of adjacency[v]) {
|
|
72
|
+
if (color[u] !== -1)
|
|
73
|
+
continue;
|
|
74
|
+
if (neighborColors(adjacency[u], color).size >= k)
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return false;
|
|
78
|
+
};
|
|
79
|
+
// DSATUR vertex selection: highest saturation (number of distinct neighbor
|
|
80
|
+
// colors), tiebreak on degree, tiebreak on input index. Strict `>`
|
|
81
|
+
// comparisons keep the lowest unprocessed index winning ties — same
|
|
82
|
+
// determinism contract as `mutationGrouper.pickNextVertex`.
|
|
83
|
+
const pickMostConstrained = (adjacency, color, degree) => {
|
|
84
|
+
let pick = -1;
|
|
85
|
+
let pickSaturation = -1;
|
|
86
|
+
for (let v = 0; v < color.length; ++v) {
|
|
87
|
+
if (color[v] !== -1)
|
|
88
|
+
continue;
|
|
89
|
+
const saturation = neighborColors(adjacency[v], color).size;
|
|
90
|
+
if (pick === -1 ||
|
|
91
|
+
saturation > pickSaturation ||
|
|
92
|
+
(saturation === pickSaturation && degree[v] > degree[pick])) {
|
|
93
|
+
pick = v;
|
|
94
|
+
pickSaturation = saturation;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return pick;
|
|
98
|
+
};
|
|
99
|
+
const neighborColors = (neighbors, color) => {
|
|
100
|
+
const used = new Set();
|
|
101
|
+
for (const u of neighbors) {
|
|
102
|
+
if (color[u] !== -1)
|
|
103
|
+
used.add(color[u]);
|
|
104
|
+
}
|
|
105
|
+
return used;
|
|
106
|
+
};
|
|
107
|
+
export const decideExactOutcome = (exact, dsaturColors) => {
|
|
108
|
+
const exactColors = exact.coloring.reduce((m, c) => (c > m ? c : m), -1) + 1;
|
|
109
|
+
if (exactColors < dsaturColors) {
|
|
110
|
+
return {
|
|
111
|
+
useGroups: 'exact',
|
|
112
|
+
suffix: ` — exact: improved by ${dsaturColors - exactColors} deploy(s)`,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return { useGroups: 'dsatur', suffix: ' — exact: confirmed optimal' };
|
|
116
|
+
};
|
|
117
|
+
// Binary search on k = chromatic number, using `tryKColoring` to certify
|
|
118
|
+
// or improve the DSATUR result. Runs every iteration to completion. The
|
|
119
|
+
// loop exits when lo == hi (provably optimal). Result is never worse than
|
|
120
|
+
// DSATUR alone.
|
|
121
|
+
export const solveColoring = (input) => {
|
|
122
|
+
const { adjacency, n, dsaturColors, witness, dsaturColoring } = input;
|
|
123
|
+
const initialLowerBound = input.lowerBound;
|
|
124
|
+
if (initialLowerBound < witness.length) {
|
|
125
|
+
throw new Error(`solveColoring: lowerBound=${initialLowerBound} is below witness size ${witness.length}`);
|
|
126
|
+
}
|
|
127
|
+
let lo = initialLowerBound;
|
|
128
|
+
let hi = dsaturColors;
|
|
129
|
+
let best = dsaturColoring.slice();
|
|
130
|
+
while (lo < hi) {
|
|
131
|
+
const k = Math.floor((lo + hi) / 2);
|
|
132
|
+
const coloring = tryKColoring(adjacency, n, k, witness);
|
|
133
|
+
if (coloring !== null) {
|
|
134
|
+
best = coloring;
|
|
135
|
+
hi = k;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
lo = k + 1;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return { coloring: best, lowerBound: lo, optimal: lo === hi };
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=exactColoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exactColoring.js","sourceRoot":"","sources":["../../src/service/exactColoring.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Messages } from '@salesforce/core';
|
|
2
|
+
import { Progress } from '@salesforce/sf-plugins-core';
|
|
3
|
+
import type { CommonTokenStream } from 'apex-parser';
|
|
4
|
+
import { ApexClassRepository } from '../adapter/apexClassRepository.js';
|
|
5
|
+
import { ApexTestRunner } from '../adapter/apexTestRunner.js';
|
|
6
|
+
import { ApexClass } from '../type/ApexClass.js';
|
|
7
|
+
import { ApexMutationTestResult } from '../type/ApexMutationTestResult.js';
|
|
8
|
+
import { MutantGenerator } from './mutantGenerator.js';
|
|
9
|
+
import { MutationGroup } from './mutationGrouper.js';
|
|
10
|
+
export declare class GroupExecutor {
|
|
11
|
+
private readonly apexClass;
|
|
12
|
+
private readonly apexClassName;
|
|
13
|
+
private readonly apexTestClassName;
|
|
14
|
+
private readonly apexClassContent;
|
|
15
|
+
private readonly tokenStream;
|
|
16
|
+
private readonly testMethodsPerLine;
|
|
17
|
+
private readonly mutantGenerator;
|
|
18
|
+
private readonly apexTestRunner;
|
|
19
|
+
private readonly apexClassRepository;
|
|
20
|
+
private readonly progress;
|
|
21
|
+
private readonly messages;
|
|
22
|
+
constructor(apexClass: ApexClass, apexClassName: string, apexTestClassName: string, apexClassContent: string, tokenStream: CommonTokenStream, testMethodsPerLine: Map<number, Set<string>>, mutantGenerator: MutantGenerator, apexTestRunner: ApexTestRunner, apexClassRepository: ApexClassRepository, progress: Progress, messages: Messages<string>);
|
|
23
|
+
evaluate(group: MutationGroup, completedSoFar: number, loopStartTime: number, totalMutations: number): Promise<ApexMutationTestResult['mutants']>;
|
|
24
|
+
private announceGroup;
|
|
25
|
+
private evaluateGroup;
|
|
26
|
+
private hasCoverageGap;
|
|
27
|
+
private buildGroupProgressMessage;
|
|
28
|
+
private buildMutantResult;
|
|
29
|
+
}
|