@specific.dev/spectest 0.81.1 → 0.82.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/src/daemon.ts CHANGED
@@ -49,6 +49,8 @@ import {
49
49
  } from "./harness/coverage.js";
50
50
  import { configureBrowserCoverage } from "./browser-coverage.js";
51
51
  import {
52
+ NODE_COVERAGE_MARKERS_SUBDIR,
53
+ NODE_COVERAGE_SCRIPTS_SUBDIR,
52
54
  applyCoverageAdapters,
53
55
  coverageAdapters,
54
56
  coverageReportsMode,
@@ -974,10 +976,15 @@ async function ensureCoverage(svc: NamedService): Promise<string[]> {
974
976
  if (svc.coverage === undefined) return [];
975
977
  validateCoverage(svc.name, svc.coverage);
976
978
  const host = coverageHostDir(WORKSPACE, svc.name);
977
- await fs.mkdir(host, { recursive: true });
978
- await fs.chmod(host, 0o777);
979
- // Nothing else is mounted: no conversion runs in the container (the
980
- // c8 tools mount went with SDK 0.80).
979
+ // World-writable, the subdirectories the node() hook writes into too:
980
+ // the container's processes run as whatever user the image says, and
981
+ // a directory the first of them created would be closed to the next.
982
+ for (const d of [host, path.join(host, NODE_COVERAGE_SCRIPTS_SUBDIR), path.join(host, NODE_COVERAGE_MARKERS_SUBDIR)]) {
983
+ await fs.mkdir(d, { recursive: true });
984
+ await fs.chmod(d, 0o777);
985
+ }
986
+ // Nothing else is mounted: nothing runs in the container for coverage
987
+ // beyond the hook in the process itself.
981
988
  return [`--volume=${host}:${COVERAGE_CONTAINER_DIR}`];
982
989
  }
983
990
 
@@ -4052,21 +4059,6 @@ function coverageCaptureContext(
4052
4059
  await fs.rename(tmp, file);
4053
4060
  written.add(path.relative(reportDir, file));
4054
4061
  },
4055
- async readContainerFile(containerPath: string) {
4056
- // `docker cp` rather than `exec cat`: a source map can be tens of
4057
- // MB, and the exec path buffers stdout as a string. The copy lands
4058
- // in the VM's tmp, never in the coverage directory (it would ship).
4059
- const tmp = path.join(tmpdir(), `spectest-cov-${svc.name}-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`);
4060
- try {
4061
- const r = await docker(["cp", `${svc.name}:${containerPath}`, tmp], COVERAGE_CAPTURE_TIMEOUT_MS);
4062
- if (r.code !== 0) return null;
4063
- return await fs.readFile(tmp);
4064
- } catch {
4065
- return null;
4066
- } finally {
4067
- await fs.rm(tmp, { force: true, recursive: true }).catch(() => {});
4068
- }
4069
- },
4070
4062
  };
4071
4063
  }
4072
4064
 
@@ -3,7 +3,8 @@
3
3
  // A service that opts in (`coverage: true | { command }`) gets a writable
4
4
  // directory bind-mounted at `/spectest/coverage/` in its container. The
5
5
  // service's own tool, or its coverage adapters, write reports there —
6
- // lcov, or the V8 coverage JSON that `NODE_V8_COVERAGE` writes. The daemon reads the
6
+ // lcov, the V8 coverage JSON shape (what `coverage.node()`'s hook or
7
+ // `NODE_V8_COVERAGE` write), or a node() script record. The daemon reads the
7
8
  // directory from the VM side (no `docker exec` to fetch) after bring-up
8
9
  // and after each test, and ships the reports **verbatim** to the control
9
10
  // plane as a gzipped bundle. Nothing is interpreted here beyond the one
@@ -115,9 +116,17 @@ export function isV8CoverageJson(text: string): boolean {
115
116
  return /^\s*\{/.test(text) && /"result"\s*:\s*\[/.test(text);
116
117
  }
117
118
 
118
- /** True when `text` is a report spectest stores: lcov or V8 JSON. */
119
+ /** True when `text` is a script record the `node()` hook writes
120
+ * (`scripts/<id>.json`: `{ "spectestScript": { url, lineLengths,
121
+ * functions, sourceMap } }`), the static side of its dumps. */
122
+ export function isSpectestScriptRecord(text: string): boolean {
123
+ return /^\s*\{\s*"spectestScript"\s*:/.test(text);
124
+ }
125
+
126
+ /** True when `text` is a report spectest stores: lcov, V8 JSON, or a
127
+ * node() script record. */
119
128
  export function isWellFormedReport(text: string): boolean {
120
- return isLcovShaped(text) || isV8CoverageJson(text);
129
+ return isLcovShaped(text) || isV8CoverageJson(text) || isSpectestScriptRecord(text);
121
130
  }
122
131
 
123
132
  /** True when a well-formed report names no source file at all (an lcov