supercov 4.22.0 → 4.24.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/docs/cli.md +11 -7
- package/docs/supported-suites.md +98 -0
- package/docs/workspace-isolation.md +3 -2
- package/package.json +10 -10
- package/runtime/javascript/playwright.mjs +2 -2
- package/runtime/javascript/runtime.mjs +22 -19
package/docs/cli.md
CHANGED
|
@@ -742,15 +742,18 @@ Merge creates a new run. The inputs must describe the same source,
|
|
|
742
742
|
configuration, toolchain, schema, and coverage denominator. Supercov rejects an
|
|
743
743
|
incompatible merge rather than publishing a misleading aggregate.
|
|
744
744
|
|
|
745
|
-
With no run named, `merge` takes the runs recorded on the source as it is now
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
745
|
+
With no run named, `merge` takes the runs recorded on the source as it is now,
|
|
746
|
+
leaving out runs that are themselves a merge. It prints the runs it took. This
|
|
747
|
+
is what a script uses after measuring its suites, one after another or side by
|
|
748
|
+
side, without knowing what each run was called. Asked again with nothing new,
|
|
749
|
+
it names the merge already made.
|
|
750
750
|
|
|
751
751
|
A test that is in two of the runs is one test in the merge. If it failed in
|
|
752
|
-
either, it is failed, which is why a command
|
|
753
|
-
|
|
752
|
+
either, it is failed, which is why a command measured again in the same
|
|
753
|
+
project replaces its earlier runs there and is not merged with them. Runs of
|
|
754
|
+
one command measured on different machines and copied into one
|
|
755
|
+
`.supercov/runs` replace none of each other: each is a share of the suite, and
|
|
756
|
+
all are merged.
|
|
754
757
|
|
|
755
758
|
The runs may differ in their tests, the helpers beside them, and the test
|
|
756
759
|
runners' settings, as long as nothing that changed reaches what an earlier
|
|
@@ -921,6 +924,7 @@ terminal or offline environment after the package has been downloaded.
|
|
|
921
924
|
| Variable | Use |
|
|
922
925
|
| --- | --- |
|
|
923
926
|
| `SUPERCOV_SOURCE_ROOTS` | Comma-separated directories or files that hold your own code, in any language; everything else is left out |
|
|
927
|
+
| `SUPERCOV_TEST_ROOTS` | For an Ant build whose `<batchtest>` directories cannot be read from its files: comma-separated directories that hold its tests |
|
|
924
928
|
| `SUPERCOV_TEST_KIND` | Label the wrapped command as a test level such as `unit` or `e2e` |
|
|
925
929
|
| `SUPERCOV_SOURCE_TOOLS` | Comma-separated names of tools the test command runs that read source as text, such as a linter or a spell checker, besides Biome, oxlint, dprint, cspell and knip. Each is run on your source as you wrote it instead of on the instrumented copy |
|
|
926
930
|
| `SUPERCOV_RUN_ID` | Set by Supercov, not by you: in every process a measured command starts, the run's id, so a test or harness can tell it is measured |
|
package/docs/supported-suites.md
CHANGED
|
@@ -710,6 +710,37 @@ copy before its container starts, so an image left over from an earlier run
|
|
|
710
710
|
is never used. An image built from an earlier copy, by a command outside the
|
|
711
711
|
run, is left as it is, and the run says to build it in the test command.
|
|
712
712
|
|
|
713
|
+
A container the project is mounted into runs the copy's code whatever its
|
|
714
|
+
image, as `.:/workspace` in a compose file does: Supercov runs the command
|
|
715
|
+
in the copy, so the mount is of the copy. It gets the run's settings with
|
|
716
|
+
each path into the copy moved to where the container sees it, and the
|
|
717
|
+
project's `node_modules`, which the copy's packages link to, mounted
|
|
718
|
+
read-only at its own path. A mount of one directory of the project
|
|
719
|
+
(`./src:/app/src`) is not the copy, and is left alone.
|
|
720
|
+
|
|
721
|
+
The tests can run in such a container too. A command `docker exec` (or
|
|
722
|
+
`docker compose exec`) starts in it, `npx playwright test` say, gets the
|
|
723
|
+
test command's settings, moved the same way, with `NODE_OPTIONS` added to
|
|
724
|
+
the container's own. Playwright then runs under Supercov's preload and
|
|
725
|
+
generated configuration, as it does beside Supercov, and each test is
|
|
726
|
+
credited with what it ran:
|
|
727
|
+
|
|
728
|
+
```yaml
|
|
729
|
+
services:
|
|
730
|
+
tests:
|
|
731
|
+
image: mcr.microsoft.com/playwright:v1.56.0-noble
|
|
732
|
+
volumes: [".:/workspace"]
|
|
733
|
+
working_dir: /workspace
|
|
734
|
+
command: sleep infinity
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
```sh
|
|
738
|
+
npx supercov -- sh -c "docker compose up -d && docker compose exec tests npx playwright test"
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
When containers were given the run's settings and no test or coverage came
|
|
742
|
+
back from them, the run says so: what ran there is missing, not zero.
|
|
743
|
+
|
|
713
744
|
- Images pulled from a registry (`image:` with no `build:`, `postgres:16`)
|
|
714
745
|
run code nobody instrumented, and are left as they are.
|
|
715
746
|
- testcontainers' reaper, Ryuk, is pointed at the daemon's own socket
|
|
@@ -736,6 +767,9 @@ npx supercov -- npx playwright test
|
|
|
736
767
|
| Spock | Exact per feature, under the names Spock itself reports | — |
|
|
737
768
|
| TestNG | Exact per test, each data-provider invocation its own | — |
|
|
738
769
|
| JUnit 4 alone | Exact per test, through Vintage — see below | Maven or Gradle |
|
|
770
|
+
| JUnit 4 under Ant's `<junit>` | Exact per test, under the names Ant's XML report uses | Ant 1.10 — see below |
|
|
771
|
+
| Any platform engine under Ant's `<junitlauncher>` | Exact per test, through the platform listener | Ant 1.10 — see below |
|
|
772
|
+
| TestNG under Ant's `<testng>` | Exact per test, through the TestNG listener | TestNG 6.x with its Ant task — see below |
|
|
739
773
|
|
|
740
774
|
Multi-module builds are measured module by module: each compiles its own source
|
|
741
775
|
set and forks its own JVM, so each gets a runtime and records evidence of its
|
|
@@ -798,6 +832,70 @@ npx supercov -- ./gradlew test
|
|
|
798
832
|
npx supercov -- ./mvnw verify
|
|
799
833
|
```
|
|
800
834
|
|
|
835
|
+
### Ant and Ivy
|
|
836
|
+
|
|
837
|
+
A project with a `build.xml` (and no Maven or Gradle build) is an Ant build.
|
|
838
|
+
Ant has no layout convention, so Supercov reads the build: it follows the
|
|
839
|
+
`<import>` chain with the properties it defines, takes the directories each
|
|
840
|
+
`<batchtest>` or `<testclasses>` scans as the tests — or, where it scans
|
|
841
|
+
compiled classes, the sources the `<javac>` writing them compiles — and what
|
|
842
|
+
its other `<javac>` tasks compile as the code they test, leaving out the
|
|
843
|
+
directories the build writes into. Java elsewhere, such as the sources a test
|
|
844
|
+
compiles as its input, is left alone. Where a `<javac>` compiles from a path
|
|
845
|
+
the build makes only at run time, every other `src` directory holding Java is
|
|
846
|
+
taken as product code too.
|
|
847
|
+
When the build names its tests where that cannot be read — a path a custom
|
|
848
|
+
task builds at run time — say where they are:
|
|
849
|
+
|
|
850
|
+
```sh
|
|
851
|
+
SUPERCOV_TEST_ROOTS=test/src npx supercov -- ant test
|
|
852
|
+
```
|
|
853
|
+
|
|
854
|
+
`SUPERCOV_SOURCE_ROOTS` narrows the product code the same way as for any
|
|
855
|
+
project.
|
|
856
|
+
|
|
857
|
+
Ant's `<junit>` task runs JUnit 4 itself, not on the JUnit Platform, so in the
|
|
858
|
+
copy each `<junit>` task gets a result formatter of Supercov's next to its own
|
|
859
|
+
formatters. The task loads it in every JVM it forks — one per test class by
|
|
860
|
+
default — and it tells the runtime when each test starts and ends. Each JVM
|
|
861
|
+
writes its evidence at the end of its suite and on shutdown, so a JVM the
|
|
862
|
+
task stops for running past its timeout still leaves what it recorded, and
|
|
863
|
+
the run merges every one. The formatter is compiled by the copy's build just
|
|
864
|
+
before the task, against the task's own classpath and Ant's runtime. Tests
|
|
865
|
+
keep the names Ant's XML reports give them, `Class#method`; a test a suite
|
|
866
|
+
runs is named within it, `Suite#Class#method`, and a test two tasks or
|
|
867
|
+
filesets both run is numbered in the second (`[2]`). A test the task stops
|
|
868
|
+
for its timeout is recorded as failed, with what it ran until then. A build
|
|
869
|
+
that names no tests where they can be read keeps the `src/main` and
|
|
870
|
+
`src/test` convention.
|
|
871
|
+
|
|
872
|
+
Ant's `<junitlauncher>` runs tests on the JUnit Platform, so it gets the same
|
|
873
|
+
platform listener Maven and Gradle builds get, as a `<listener>` of the task,
|
|
874
|
+
compiled the same way against the task's classpath. TestNG's `<testng>` task
|
|
875
|
+
gets the TestNG listener in its own `listeners` attribute, beside any the
|
|
876
|
+
build names.
|
|
877
|
+
|
|
878
|
+
Many Ant builds import a shared harness from beside the project —
|
|
879
|
+
`<import file="../../../tools/master/build/common/common-build.xml"/>` — and
|
|
880
|
+
the `<junit>` task lives there. The copy is laid out at the project's place
|
|
881
|
+
within the closest directory holding it and everything its build imports,
|
|
882
|
+
with links standing for the rest, so `../` reaches what it reaches in the
|
|
883
|
+
checkout. A file outside the project that holds a `<junit>` task — the
|
|
884
|
+
harness, or a wrapper script's own build file beside it — is changed in the
|
|
885
|
+
copy's own version of that file; the original and the rest of the harness
|
|
886
|
+
are only read. Small files and directories beside the project are copied
|
|
887
|
+
rather than linked, so a wrapper script that writes beside itself writes into
|
|
888
|
+
the copy; anything larger than 4 MB stays a link.
|
|
889
|
+
|
|
890
|
+
Only the project's own sources are measured: modules resolved as jars, Ivy's
|
|
891
|
+
included, are not instrumented. Code that is not Java or Kotlin — XSLT,
|
|
892
|
+
sitemaps, scripts run by the JVM — is outside what the figure covers.
|
|
893
|
+
|
|
894
|
+
```sh
|
|
895
|
+
npx supercov -- ant test
|
|
896
|
+
npx supercov -- ../../../run-single-test.sh . ALL
|
|
897
|
+
```
|
|
898
|
+
|
|
801
899
|
## Containers, VMs, and remote execution
|
|
802
900
|
|
|
803
901
|
Supercov can collect from supported processes launched through a container, VM,
|
|
@@ -200,8 +200,9 @@ its settings with paths moved to the guest's mount, and the guest's coverage is
|
|
|
200
200
|
credited to the test that launched it. A guest started any other way, with none
|
|
201
201
|
of those settings, still runs the instrumented code: it reads the run's
|
|
202
202
|
settings from the mounted workspace itself, and its coverage counts for the run
|
|
203
|
-
as background coverage, credited to no test. The run summary's `
|
|
204
|
-
|
|
203
|
+
as background coverage, credited to no test. The run summary's `Unattributed`
|
|
204
|
+
line counts processes whose coverage has no named test identity. Local processes
|
|
205
|
+
can also appear here; this count does not establish container or VM execution.
|
|
205
206
|
|
|
206
207
|
Dependencies stay out of the instrumented copy. The root `node_modules` is
|
|
207
208
|
linked entry by entry to the project's own, so an environment that mounts the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "supercov",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.24.0",
|
|
4
4
|
"description": "Coverage, security and code quality for coding agents",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"coverage",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"eval:skill": "claude plugin eval plugins/supercov --scaffold --trust-plugin --no-publish --model claude-sonnet-5 --judge-model claude-haiku-4-5 --threshold 0.66 --tag behavior trigger --allow-tools Bash Edit Write --max-cost-usd 15",
|
|
83
83
|
"eval:skill-triggers": "claude plugin eval plugins/supercov --scaffold --trust-plugin --no-publish --model claude-sonnet-5 --judge-model claude-haiku-4-5 --threshold 0.66 --tag trigger --ablation none --max-cost-usd 5",
|
|
84
84
|
"test:engine": "cargo fmt --all -- --check && cargo clippy --workspace --all-targets -- -D warnings && cargo test --workspace && npm run test:runtime && npm run test:rust-assets && npm run test:engine-integrations",
|
|
85
|
-
"test:engine-integrations": "cargo build -p supercov && node scripts/html-report-integration.mjs && node scripts/rust-process-supervision.mjs && node scripts/rust-direct-node-integration.mjs && node scripts/rust-public-run-integration.mjs && node scripts/rust-embedded-runtime-integration.mjs && node scripts/rust-direct-vitest-integration.mjs && node scripts/rust-direct-jest-integration.mjs && node scripts/mocha-failure-output.mjs && node scripts/failure-output.mjs node ava tap && node scripts/side-by-side.mjs node && node scripts/merge-across.mjs && node scripts/import-line-evidence.mjs && node scripts/mock-reach.mjs && node scripts/rust-direct-playwright-integration.mjs && node scripts/rust-custom-browser-playwright-integration.mjs && node scripts/cross-origin-requests.mjs && node scripts/leaving-page.mjs && node scripts/shared-page.mjs && node scripts/context-headers.mjs && node scripts/context-cookies.mjs && node scripts/hidden-request-emit.mjs && node scripts/js-syntax-zoo.mjs && node scripts/ruby-syntax-zoo.mjs && node scripts/rust-syntax-zoo.mjs && node scripts/python-syntax-zoo.mjs && node scripts/go-syntax-zoo.mjs && node scripts/java-syntax-zoo.mjs && node scripts/background-by-time.mjs && node scripts/python-server-playwright.mjs && node scripts/ruby-server-playwright.mjs && node scripts/go-server-playwright.mjs && node scripts/jvm-server-playwright.mjs && node scripts/docker-server-playwright.mjs && node scripts/docker-clients-playwright.mjs && node scripts/rust-classic-browser-integration.mjs && node scripts/exec-handover.mjs && node scripts/rust-region-container.mjs && node scripts/rust-top-packages-integration.mjs && node scripts/rust-generic-esbuild-integration.mjs && node scripts/rust-generic-tsc-integration.mjs && node scripts/rust-generic-build-matrix.mjs && node scripts/rust-vite-playwright-integration.mjs && node scripts/workspace-crash-integration.mjs",
|
|
85
|
+
"test:engine-integrations": "cargo build -p supercov && node scripts/html-report-integration.mjs && node scripts/rust-process-supervision.mjs && node scripts/rust-direct-node-integration.mjs && node scripts/rust-public-run-integration.mjs && node scripts/rust-embedded-runtime-integration.mjs && node scripts/rust-direct-vitest-integration.mjs && node scripts/rust-direct-jest-integration.mjs && node scripts/mocha-failure-output.mjs && node scripts/failure-output.mjs node ava tap && node scripts/side-by-side.mjs node && node scripts/merge-across.mjs && node scripts/import-line-evidence.mjs && node scripts/mock-reach.mjs && node scripts/rust-direct-playwright-integration.mjs && node scripts/rust-custom-browser-playwright-integration.mjs && node scripts/cross-origin-requests.mjs && node scripts/leaving-page.mjs && node scripts/shared-page.mjs && node scripts/context-headers.mjs && node scripts/context-cookies.mjs && node scripts/hidden-request-emit.mjs && node scripts/js-syntax-zoo.mjs && node scripts/ruby-syntax-zoo.mjs && node scripts/rust-syntax-zoo.mjs && node scripts/python-syntax-zoo.mjs && node scripts/go-syntax-zoo.mjs && node scripts/java-syntax-zoo.mjs && node scripts/background-by-time.mjs && node scripts/python-server-playwright.mjs && node scripts/ruby-server-playwright.mjs && node scripts/go-server-playwright.mjs && node scripts/jvm-server-playwright.mjs && node scripts/docker-server-playwright.mjs && node scripts/docker-clients-playwright.mjs && node scripts/docker-exec-playwright.mjs && node scripts/rust-classic-browser-integration.mjs && node scripts/exec-handover.mjs && node scripts/rust-region-container.mjs && node scripts/rust-top-packages-integration.mjs && node scripts/rust-generic-esbuild-integration.mjs && node scripts/rust-generic-tsc-integration.mjs && node scripts/rust-generic-build-matrix.mjs && node scripts/rust-vite-playwright-integration.mjs && node scripts/workspace-crash-integration.mjs",
|
|
86
86
|
"test:platform": "cargo test --workspace && cargo build -p supercov && node scripts/rust-process-supervision.mjs && node scripts/workspace-crash-integration.mjs",
|
|
87
87
|
"test:native-package": "cargo build --release -p supercov && node scripts/native-package-integration.mjs && node scripts/native-release-set-integration.mjs",
|
|
88
88
|
"test:pypi-wheel": "node scripts/pypi-wheel-integration.mjs",
|
|
@@ -122,14 +122,14 @@
|
|
|
122
122
|
"test:windows-tls": "node scripts/windows-tls-test.mjs"
|
|
123
123
|
},
|
|
124
124
|
"optionalDependencies": {
|
|
125
|
-
"@supercov/cli-darwin-arm64": "4.
|
|
126
|
-
"@supercov/cli-darwin-x64": "4.
|
|
127
|
-
"@supercov/cli-linux-arm64-gnu": "4.
|
|
128
|
-
"@supercov/cli-linux-arm64-musl": "4.
|
|
129
|
-
"@supercov/cli-linux-x64-gnu": "4.
|
|
130
|
-
"@supercov/cli-linux-x64-musl": "4.
|
|
131
|
-
"@supercov/cli-win32-arm64": "4.
|
|
132
|
-
"@supercov/cli-win32-x64": "4.
|
|
125
|
+
"@supercov/cli-darwin-arm64": "4.24.0",
|
|
126
|
+
"@supercov/cli-darwin-x64": "4.24.0",
|
|
127
|
+
"@supercov/cli-linux-arm64-gnu": "4.24.0",
|
|
128
|
+
"@supercov/cli-linux-arm64-musl": "4.24.0",
|
|
129
|
+
"@supercov/cli-linux-x64-gnu": "4.24.0",
|
|
130
|
+
"@supercov/cli-linux-x64-musl": "4.24.0",
|
|
131
|
+
"@supercov/cli-win32-arm64": "4.24.0",
|
|
132
|
+
"@supercov/cli-win32-x64": "4.24.0"
|
|
133
133
|
},
|
|
134
134
|
"peerDependencies": {
|
|
135
135
|
"@playwright/test": ">=1.55.0",
|
|
@@ -973,7 +973,7 @@ function mergeSnapshots(snapshots) {
|
|
|
973
973
|
for (const event of snapshot?.events ?? [])
|
|
974
974
|
events.set(JSON.stringify(event), event);
|
|
975
975
|
for (const decision of snapshot?.decisions ?? []) {
|
|
976
|
-
const entry = vectorsOf(decisions, decision.
|
|
976
|
+
const entry = vectorsOf(decisions, decision.id, { id: decision.id });
|
|
977
977
|
for (const vector of decision.vectors ?? [])
|
|
978
978
|
entry.seen.set(JSON.stringify(vector), vector);
|
|
979
979
|
}
|
|
@@ -984,7 +984,7 @@ function mergeSnapshots(snapshots) {
|
|
|
984
984
|
}
|
|
985
985
|
}
|
|
986
986
|
return {
|
|
987
|
-
decisions: [...decisions.values()].map(({ seen,
|
|
987
|
+
decisions: [...decisions.values()].map(({ seen, id }) => ({ id, vectors: [...seen.values()] })),
|
|
988
988
|
hits: [...hits],
|
|
989
989
|
events: [...events.values()],
|
|
990
990
|
logicals: [...logicals.values()].map(({ seen, id }) => ({ id, vectors: [...seen.values()] })),
|
|
@@ -185,8 +185,8 @@ function createState() {
|
|
|
185
185
|
try {
|
|
186
186
|
const stored = JSON.parse((_a8 = localStorage.getItem(storageKey)) != null ? _a8 : "{}");
|
|
187
187
|
for (const snapshot of (_b = stored.decisions) != null ? _b : []) {
|
|
188
|
-
state2.decisions.set(snapshot.
|
|
189
|
-
|
|
188
|
+
state2.decisions.set(snapshot.id, {
|
|
189
|
+
id: snapshot.id,
|
|
190
190
|
vectors: new Map(snapshot.vectors.map((vector) => [vectorKey(vector), vector]))
|
|
191
191
|
});
|
|
192
192
|
}
|
|
@@ -304,7 +304,7 @@ runtimeGlobal.__SUPERCOV_ACTIVATE_PROBE_CONTEXT__ = (browserTestId, browserPhase
|
|
|
304
304
|
};
|
|
305
305
|
function decisionSnapshot() {
|
|
306
306
|
return [...state.decisions.values()].map((decision) => ({
|
|
307
|
-
|
|
307
|
+
id: decision.id,
|
|
308
308
|
vectors: [...decision.vectors.values()]
|
|
309
309
|
}));
|
|
310
310
|
}
|
|
@@ -470,7 +470,7 @@ function attemptKey(scope) {
|
|
|
470
470
|
}
|
|
471
471
|
function serverRecordKey(record) {
|
|
472
472
|
var _a8;
|
|
473
|
-
const suffix = record.type === "decision" ? `${record.
|
|
473
|
+
const suffix = record.type === "decision" ? `${record.id}:${vectorKey(record.vector)}` : record.id;
|
|
474
474
|
// Each request that names no test keeps its own first hits: the report
|
|
475
475
|
// credits them to the test running when it came, and a later request's
|
|
476
476
|
// work belongs to whichever test was running then.
|
|
@@ -982,7 +982,7 @@ function appendServer(record) {
|
|
|
982
982
|
if (record.type === "decision") {
|
|
983
983
|
recordBrowserEvent(__spreadProps(__spreadValues({
|
|
984
984
|
type: "decision",
|
|
985
|
-
id: record.
|
|
985
|
+
id: record.id,
|
|
986
986
|
vector: record.vector,
|
|
987
987
|
timestampMs
|
|
988
988
|
}, record.phaseId ? { phaseId: record.phaseId } : {}), {
|
|
@@ -1801,11 +1801,14 @@ function recordCoverageHit(id) {
|
|
|
1801
1801
|
function registerProbeV2(definition) {
|
|
1802
1802
|
var _a8, _b;
|
|
1803
1803
|
const file = {
|
|
1804
|
+
// Each decision's id and its number of conditions: the module carries
|
|
1805
|
+
// no source text, which the manifest holds.
|
|
1804
1806
|
decisions: definition.decisions,
|
|
1807
|
+
decisionWidths: definition.decisionWidths,
|
|
1805
1808
|
pointIds: definition.pointIds,
|
|
1806
1809
|
clock: state.probeV2Clock,
|
|
1807
1810
|
hitEpochs: new Uint32Array(definition.pointIds.length),
|
|
1808
|
-
decisionEpochs: definition.
|
|
1811
|
+
decisionEpochs: definition.decisionWidths.map((width) => width <= 6 ? new Uint32Array(2 * 3 ** width) : /* @__PURE__ */ new Map()),
|
|
1809
1812
|
decisionVectorCounts: definition.decisions.map((_, index) => {
|
|
1810
1813
|
var _a9, _b2;
|
|
1811
1814
|
return (_b2 = (_a9 = definition.decisionVectorCounts) == null ? void 0 : _a9[index]) != null ? _b2 : 0;
|
|
@@ -1898,8 +1901,8 @@ function mcdcEndV2(file, decisionIndex, encoded, value) {
|
|
|
1898
1901
|
}
|
|
1899
1902
|
function recordMcdcEndV2(file, decisionIndex, encoded, value) {
|
|
1900
1903
|
var _a8, _b;
|
|
1901
|
-
const
|
|
1902
|
-
if (!
|
|
1904
|
+
const id = file.decisions[decisionIndex];
|
|
1905
|
+
if (!id || !Number.isSafeInteger(encoded) || encoded < 0)
|
|
1903
1906
|
return value;
|
|
1904
1907
|
const outcome = Boolean(value);
|
|
1905
1908
|
const vectorIndex = encoded * 2 + (outcome ? 1 : 0);
|
|
@@ -1934,10 +1937,10 @@ function recordMcdcEndV2(file, decisionIndex, encoded, value) {
|
|
|
1934
1937
|
if (observedCount >= expectedCount)
|
|
1935
1938
|
file.decisionCompleteEpochs[decisionIndex] = epoch;
|
|
1936
1939
|
}
|
|
1937
|
-
if (!state.decisions.has(
|
|
1938
|
-
state.decisions.set(
|
|
1939
|
-
const vector = decodeProbeV2Vector(
|
|
1940
|
-
return vector ? mcdcEnd({
|
|
1940
|
+
if (!state.decisions.has(id))
|
|
1941
|
+
state.decisions.set(id, { id, vectors: /* @__PURE__ */ new Map() });
|
|
1942
|
+
const vector = decodeProbeV2Vector(file.decisionWidths[decisionIndex], encoded, outcome);
|
|
1943
|
+
return vector ? mcdcEnd({ id, values: vector.values }, value) : value;
|
|
1941
1944
|
} finally {
|
|
1942
1945
|
if (fallbackEpoch)
|
|
1943
1946
|
file.clock.epoch = previousEpoch;
|
|
@@ -2224,13 +2227,13 @@ function loopEntered(frame) {
|
|
|
2224
2227
|
function loopEnd(frame) {
|
|
2225
2228
|
if (!frame.entered) coverageHit(frame.zeroId);
|
|
2226
2229
|
}
|
|
2227
|
-
function mcdcBegin(id,
|
|
2230
|
+
function mcdcBegin(id, width) {
|
|
2228
2231
|
if (!state.decisions.has(id)) {
|
|
2229
|
-
state.decisions.set(id, {
|
|
2232
|
+
state.decisions.set(id, { id, vectors: /* @__PURE__ */ new Map() });
|
|
2230
2233
|
}
|
|
2231
2234
|
return {
|
|
2232
|
-
|
|
2233
|
-
values: Array.from({ length:
|
|
2235
|
+
id,
|
|
2236
|
+
values: Array.from({ length: width }, () => null)
|
|
2234
2237
|
};
|
|
2235
2238
|
}
|
|
2236
2239
|
function mcdcCondition(frame, index, value) {
|
|
@@ -2238,7 +2241,7 @@ function mcdcCondition(frame, index, value) {
|
|
|
2238
2241
|
return value;
|
|
2239
2242
|
}
|
|
2240
2243
|
function mcdcEnd(frame, value) {
|
|
2241
|
-
const decision = state.decisions.get(frame.
|
|
2244
|
+
const decision = state.decisions.get(frame.id);
|
|
2242
2245
|
if (!decision)
|
|
2243
2246
|
return value;
|
|
2244
2247
|
const vector = { values: frame.values, outcome: Boolean(value) };
|
|
@@ -2249,7 +2252,7 @@ function mcdcEnd(frame, value) {
|
|
|
2249
2252
|
if (isBrowser) {
|
|
2250
2253
|
if (recordBrowserEvent(__spreadProps(__spreadValues({
|
|
2251
2254
|
type: "decision",
|
|
2252
|
-
id: decision.
|
|
2255
|
+
id: decision.id,
|
|
2253
2256
|
vector,
|
|
2254
2257
|
timestampMs
|
|
2255
2258
|
}, phaseId ? { phaseId } : {}), {
|
|
@@ -2259,7 +2262,7 @@ function mcdcEnd(frame, value) {
|
|
|
2259
2262
|
} else {
|
|
2260
2263
|
appendServer(__spreadValues({
|
|
2261
2264
|
type: "decision",
|
|
2262
|
-
|
|
2265
|
+
id: decision.id,
|
|
2263
2266
|
vector,
|
|
2264
2267
|
timestampMs
|
|
2265
2268
|
}, phaseId ? { phaseId } : {}));
|