mirror of
https://github.com/deepseek-ai/deepseek-harness.git
synced 2026-08-29 04:26:38 +00:00
test(webworker-runtime): keep the corpus gate as a Node import sweep
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* Full-corpus import gate: every built bundle in the workspace —
|
||||
* `packages/<group>/<package>/lib/index.js` and `vendor/<package>/lib/index.js`
|
||||
* — must be importable by Node's ESM loader. A bundle that stops importing (a
|
||||
* stray `.css` import, an emitted module Node cannot parse, a dependency that
|
||||
* throws at module scope) is reported by name.
|
||||
*
|
||||
* Baseline exemptions are a pinned list, not a count: an unlisted import
|
||||
* failure is a real finding (a bundle that stopped being importable), and it
|
||||
* must not hide inside a total. A listed file that becomes importable also
|
||||
* fails, so the list cannot rot.
|
||||
*
|
||||
* Cost: this walks the whole build output and imports every bundle serially in
|
||||
* one process, so it takes minutes on loaded runners and needs
|
||||
* `pnpm run build:lib:host` to have run. It is a heavyweight suite, not part
|
||||
* of a default aggregator run.
|
||||
*
|
||||
* Run: tsx tests/compile/transform-corpus-check.ts [files...]
|
||||
* With no arguments it discovers the corpus itself.
|
||||
*/
|
||||
import { readdirSync, statSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { fileURLToPath, pathToFileURL } from 'node:url'
|
||||
|
||||
const repositoryRoot = fileURLToPath(new URL('../../../../../', import.meta.url))
|
||||
|
||||
/**
|
||||
* Files Node's ESM loader cannot import in this repository. None is a finding:
|
||||
* each is listed with the reason the import fails, and the run refuses a
|
||||
* listed file that imports cleanly so the list stays current in both
|
||||
* directions. The koffi entry depends on corpus order: sandbox-windows-acl
|
||||
* imports the win32-process package earlier in the serial sweep (a distinct
|
||||
* module instance under its node_modules URL), so win32-process's own file-URL
|
||||
* import re-registers koffi's type names and fails as the second load.
|
||||
*/
|
||||
const BASELINE_EXEMPT: ReadonlyMap<string, string> = new Map([
|
||||
['packages/client/ui-primitives/lib/index.js', 'imports .css, which bare Node cannot load'],
|
||||
['packages/client/web/lib/index.js', 'imports .css, which bare Node cannot load'],
|
||||
['packages/subprocess/win32-process/lib/index.js', 'koffi type-name collision on a second load'],
|
||||
['packages/test-support/client-runtime/lib/index.js', "needs vitest's internal state"],
|
||||
])
|
||||
|
||||
let failures = 0
|
||||
const report: string[] = []
|
||||
const log = (line: string): void => {
|
||||
report.push(line)
|
||||
process.stdout.write(`${line}\n`)
|
||||
}
|
||||
const fail = (line: string): void => {
|
||||
failures += 1
|
||||
log(line)
|
||||
}
|
||||
|
||||
/** @returns Built bundles under a two-level package directory, in stable order. */
|
||||
function discover(): string[] {
|
||||
const found: string[] = []
|
||||
/** @returns Sorted subdirectory names, or none when the path is not a readable directory. */
|
||||
const subdirectories = (path: string): string[] => {
|
||||
try {
|
||||
return readdirSync(path, { withFileTypes: true })
|
||||
.filter(entry => entry.isDirectory())
|
||||
.map(entry => entry.name)
|
||||
.sort()
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
}
|
||||
for (const group of ['packages', 'vendor']) {
|
||||
const groupDirectory = join(repositoryRoot, group)
|
||||
for (const entry of subdirectories(groupDirectory)) {
|
||||
// `packages/<group>/<package>/lib/index.js`, `vendor/<package>/lib/index.js`.
|
||||
const candidates = group === 'vendor'
|
||||
? [join(groupDirectory, entry, 'lib', 'index.js')]
|
||||
: subdirectories(join(groupDirectory, entry))
|
||||
.map(child => join(groupDirectory, entry, child, 'lib', 'index.js'))
|
||||
for (const candidate of candidates) {
|
||||
try {
|
||||
if (statSync(candidate).isFile()) found.push(candidate)
|
||||
} catch {
|
||||
// No bundle for this package: it may not build a runtime artifact.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns Path relative to the repository root, for stable diagnostics.
|
||||
* Always POSIX-separated: the exemption table keys on one form, and a win32
|
||||
* walk would otherwise miss every entry.
|
||||
*/
|
||||
const relative = (path: string): string => path.slice(repositoryRoot.length).replaceAll('\\', '/')
|
||||
|
||||
const files = process.argv.slice(2).length > 0
|
||||
? process.argv.slice(2).map(path => (path.startsWith('/') ? path : join(process.cwd(), path)))
|
||||
: discover()
|
||||
|
||||
if (files.length === 0) {
|
||||
process.stdout.write('transform-corpus-check: no built bundles found; run `pnpm run build:lib:host` first\n')
|
||||
process.exitCode = 1
|
||||
} else {
|
||||
const verdicts = { ok: 0, exempt: 0, unexpectedBaseline: 0 }
|
||||
|
||||
for (const file of files) {
|
||||
const key = relative(file)
|
||||
const exemption = BASELINE_EXEMPT.get(key)
|
||||
try {
|
||||
await import(pathToFileURL(file).href)
|
||||
} catch (reason) {
|
||||
if (exemption === undefined) {
|
||||
// A bundle that stopped being importable is a real finding, so it
|
||||
// fails rather than joining a tolerated total.
|
||||
fail(`- UNEXPECTED BASELINE FAILURE ${key}: ${(reason as Error).message.split('\n')[0]}`)
|
||||
verdicts.unexpectedBaseline += 1
|
||||
} else {
|
||||
verdicts.exempt += 1
|
||||
}
|
||||
continue
|
||||
}
|
||||
if (exemption !== undefined) {
|
||||
// The exemption list must stay honest in the other direction too: a file
|
||||
// that became importable should leave the list.
|
||||
fail(`- STALE EXEMPTION ${key}: imports fine now (${exemption}); remove it from BASELINE_EXEMPT`)
|
||||
continue
|
||||
}
|
||||
verdicts.ok += 1
|
||||
}
|
||||
|
||||
log('')
|
||||
log(`files=${String(files.length)} ok=${String(verdicts.ok)} baselineExempt=${String(verdicts.exempt)} `
|
||||
+ `unexpectedBaselineFailure=${String(verdicts.unexpectedBaseline)}`)
|
||||
|
||||
process.stdout.write(failures === 0
|
||||
? `\ntransform-corpus-check: ${String(verdicts.ok)} bundles import under Node, `
|
||||
+ `${String(verdicts.exempt)} exempt\n`
|
||||
: `\ntransform-corpus-check: ${String(failures)} finding(s)\n`)
|
||||
process.exitCode = failures === 0 ? 0 : 1
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Runs the full-corpus import gate (`transform-corpus-check.ts`) in the
|
||||
* launcher it is written for, and reports its findings as this suite's failure.
|
||||
*
|
||||
* Spawned rather than imported, because the gate's oracle is NODE's ESM loader:
|
||||
* whether a built bundle imports is judged by `await import(file)` there.
|
||||
* Vitest replaces that loader with vite's module runner, which imports files
|
||||
* Node cannot — a `.css` import resolves, and koffi loads a second time — so an
|
||||
* in-process run measures a different loader and reports the pinned baseline
|
||||
* exemptions as stale. A gate whose verdict depends on how it was launched is
|
||||
* not a gate.
|
||||
*
|
||||
* The corpus is the build output, so this skips on a tree that has none.
|
||||
*/
|
||||
import { spawnSync } from 'node:child_process'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { expect, test } from 'vitest'
|
||||
|
||||
const runner = fileURLToPath(new URL('./transform-corpus-check.ts', import.meta.url))
|
||||
|
||||
test('every built bundle imports under Node', (context) => {
|
||||
const finished = spawnSync(process.execPath, ['--import', 'tsx/esm', runner], { encoding: 'utf8' })
|
||||
const output = `${finished.stdout}${finished.stderr}`
|
||||
if (output.includes('no built bundles found')) {
|
||||
context.skip('the workspace has no build output to sweep')
|
||||
return
|
||||
}
|
||||
// The runner prefixes every finding with '- ', so a failure reads as the
|
||||
// findings themselves rather than as a diff of its whole report.
|
||||
expect(output.split('\n').filter(line => line.startsWith('- ')).join('\n')).toBe('')
|
||||
expect(finished.status, output).toBe(0)
|
||||
}, 900_000)
|
||||
@@ -36,7 +36,10 @@ export const coverageExemptHeavySuites: readonly CoverageExemptSuite[] = [
|
||||
},
|
||||
// The webworker-runtime package is outside the coverage requirement by
|
||||
// decision: vitest.config.ts threshold-excludes its src, so every suite
|
||||
// runs uninstrumented.
|
||||
// runs uninstrumented. This tree includes the full-corpus import gate, a
|
||||
// single 900s-budget case that spawns a child sweep over every built
|
||||
// bundle; inside an instrumented partition it exceeds the Windows
|
||||
// partition budget under load.
|
||||
{
|
||||
filter: 'packages/experimental/webworker-runtime/tests/',
|
||||
exclude: 'packages/experimental/webworker-runtime/tests/**',
|
||||
@@ -46,15 +49,6 @@ export const coverageExemptHeavySuites: readonly CoverageExemptSuite[] = [
|
||||
{ filter: 'scripts/oxlint-contract.spec.ts', exclude: 'scripts/oxlint-contract.spec.ts' },
|
||||
{ filter: 'scripts/change-scope.spec.ts', exclude: 'scripts/change-scope.spec.ts' },
|
||||
{ filter: 'scripts/translation-pairing-merge.spec.ts', exclude: 'scripts/translation-pairing-merge.spec.ts' },
|
||||
// Spawns the full-corpus transform gate in a child process (Node's ESM
|
||||
// loader is its oracle), so no measured file executes in-process; the
|
||||
// package src is threshold-excluded in vitest.config.ts. A single
|
||||
// 900s-budget case; running it inside an instrumented partition exceeds
|
||||
// the Windows partition budget under load.
|
||||
{
|
||||
filter: 'packages/experimental/webworker-runtime/tests/compile/transform-corpus.spec.ts',
|
||||
exclude: 'packages/experimental/webworker-runtime/tests/compile/transform-corpus.spec.ts',
|
||||
},
|
||||
// Built-artifact proof. Packer/runtime src is threshold-excluded, and the
|
||||
// native Windows aggregate makes this uninstrumented gate wait for build so
|
||||
// the suite never observes a partially emitted workspace closure.
|
||||
|
||||
Reference in New Issue
Block a user