Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ jobs:
# Owns the rev derivation, the rev-keyed tools cache, the
# install, and the pins gate; `just conformance`'s _ct-tools
# recognizes the stamped install and does not repeat it.
uses: polymorph-components/polymorph-test/actions/setup@2436bb9fd233ec514f10de613556a7a61bbb8476
uses: polymorph-components/polymorph-test/actions/setup@b4026866e481ead0738742e3b380601b605e5350
with:
js-locks: |
conformance/driver-ct/jco/package-lock.json
Expand All @@ -122,7 +122,7 @@ jobs:
- run: just gha::conformance-checks
- name: Publish the conformance matrix
if: always() && hashFiles('conformance/driver-ct/results/*.jsonl') != ''
uses: polymorph-components/polymorph-test/actions/aggregate@2436bb9fd233ec514f10de613556a7a61bbb8476
uses: polymorph-components/polymorph-test/actions/aggregate@b4026866e481ead0738742e3b380601b605e5350
with:
lock: conformance/guest-ct/tests.lock
manifest: conformance/driver-ct/targets.toml
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
/conformance/driver-ct/results/
/conformance/driver-ct/jco/node_modules/
/conformance/driver-ct/jco/generated/
conformance/driver-ct/deltic/node_modules/
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ futures = { version = "0.3", default-features = false, features = ["std", "async
# --cargo-toml Cargo.toml --package-json
# conformance/driver-ct/jco/package.json --workflow
# .github/workflows/ci.yml`, then the follow-ups it prints.
component-test-sdk = { git = "https://github.com/polymorph-components/polymorph-test", rev = "2436bb9fd233ec514f10de613556a7a61bbb8476" }
component-test-sdk = { git = "https://github.com/polymorph-components/polymorph-test", rev = "b4026866e481ead0738742e3b380601b605e5350" }

aead = { version = "0.6", default-features = false, features = ["alloc"] }
aes = { version = "0.9", features = ["zeroize"] }
Expand Down
7 changes: 7 additions & 0 deletions conformance/driver-ct/deltic/deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

73 changes: 48 additions & 25 deletions conformance/driver-ct/deltic/fetch-translator.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
// Fetch (and cache) the deltic translator-shim wasm for the pinned release.
// Fetch (and cache) pinned deltic release assets.
//
// deltic is a runtime linker: components are translated by a wasm build of
// its translator, shipped as a release asset so consumers need no Rust
// toolchain. This script downloads that asset once into target/deltic/,
// verifies it against the pinned sha256, and prints the cached path on
// stdout (the `conformance-ct::run-deltic*` recipes capture it).
// toolchain; the browser leg additionally loads `deltic-embedder.mjs` (one
// platform-neutral ES module: embedder API + Translator + runner glue +
// wasi shims). This script downloads the selected asset once into
// target/deltic/, verifies it against the pinned sha256, and prints the
// cached path on stdout (the `conformance-ct::run-deltic*` recipes capture
// it).
//
// THE PIN lives here (TAG + TRANSLATOR_SHA256) and in the sibling
// fetch-translator.ts [--asset translator|embedder] (default: translator)
//
// THE PIN lives here (TAG + per-asset sha256) and in the sibling
// deno.json's import-map URLs. `assertPinConsistency` fails loud if the
// two drift. Bumping: update TAG here and in deno.json, update
// TRANSLATOR_SHA256 from the release's SHA256SUMS, delete deno.lock, and
// re-run `deno cache run.ts fetch-translator.ts` in this directory to
// two drift. Bumping: update TAG here and in deno.json, update the shas
// from the release's SHA256SUMS, delete deno.lock, and re-run
// `deno cache run.ts fetch-translator.ts` in this directory to
// regenerate it (commit the diff).

const TAG = "pre-83fff30";
const TRANSLATOR_SHA256 =
"6d02b363785593595a789d083cda0aebb1de790726718ccf543198354fa3870c";
const ASSET = "deltic-translator-shim.wasm";
const ASSETS: Record<string, { file: string; sha256: string }> = {
translator: {
file: "deltic-translator-shim.wasm",
sha256: "6d02b363785593595a789d083cda0aebb1de790726718ccf543198354fa3870c",
},
embedder: {
file: "deltic-embedder.mjs",
sha256: "b9ceb33c78abdaa4311f681c1388b14a3471f8a17ebd2dbf2dddd4a596df72c3",
},
};

const HERE = new URL(".", import.meta.url);
const REPO_ROOT = new URL("../../../", HERE);
const CACHE_DIR = new URL(`target/deltic/${TAG}/`, REPO_ROOT);
const CACHED = new URL(ASSET, CACHE_DIR);
const RELEASE_URL =
`https://github.com/lann/deltic/releases/download/${TAG}/${ASSET}`;

async function sha256Hex(bytes: Uint8Array): Promise<string> {
const digest = await crypto.subtle.digest(
Expand Down Expand Up @@ -55,32 +64,46 @@ async function assertPinConsistency(): Promise<void> {
async function main() {
await assertPinConsistency();

const flag = Deno.args.indexOf("--asset");
const name = flag === -1 ? "translator" : Deno.args[flag + 1];
const asset = ASSETS[name];
if (!asset) {
throw new Error(
`unknown asset ${JSON.stringify(name)}; expected one of: ${
Object.keys(ASSETS).join(", ")
}`,
);
}
const cached = new URL(asset.file, CACHE_DIR);

try {
const bytes = await Deno.readFile(CACHED);
if (await sha256Hex(bytes) === TRANSLATOR_SHA256) {
console.log(CACHED.pathname);
const bytes = await Deno.readFile(cached);
if (await sha256Hex(bytes) === asset.sha256) {
console.log(cached.pathname);
return;
}
console.error(`cached ${ASSET} has a stale digest; re-fetching`);
console.error(`cached ${asset.file} has a stale digest; re-fetching`);
} catch {
// not cached yet
}

console.error(`fetching ${RELEASE_URL} …`);
const resp = await fetch(RELEASE_URL);
const releaseUrl =
`https://github.com/lann/deltic/releases/download/${TAG}/${asset.file}`;
console.error(`fetching ${releaseUrl} …`);
const resp = await fetch(releaseUrl);
if (!resp.ok) {
throw new Error(`GET ${RELEASE_URL}: ${resp.status} ${resp.statusText}`);
throw new Error(`GET ${releaseUrl}: ${resp.status} ${resp.statusText}`);
}
const bytes = new Uint8Array(await resp.arrayBuffer());
const got = await sha256Hex(bytes);
if (got !== TRANSLATOR_SHA256) {
if (got !== asset.sha256) {
throw new Error(
`sha256 mismatch for ${ASSET}@${TAG}:\n want ${TRANSLATOR_SHA256}\n got ${got}`,
`sha256 mismatch for ${asset.file}@${TAG}:\n want ${asset.sha256}\n got ${got}`,
);
}
await Deno.mkdir(CACHE_DIR, { recursive: true });
await Deno.writeFile(CACHED, bytes);
console.log(CACHED.pathname);
await Deno.writeFile(cached, bytes);
console.log(cached.pathname);
}

await main();
32 changes: 32 additions & 0 deletions conformance/driver-ct/deltic/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions conformance/driver-ct/deltic/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@polymorph/tls-conformance-deltic-browser",
"private": true,
"type": "module",
"description": "Node driver for the deltic-browser conformance rows: the composed artifacts runtime-linked inside headless Chromium through the upstream page driver and deltic worker.",
"dependencies": {
"@polymorph/component-test-js": "github:polymorph-components/polymorph-test#b4026866e481ead0738742e3b380601b605e5350",
"playwright-core": "1.62.1"
}
}
98 changes: 98 additions & 0 deletions conformance/driver-ct/deltic/run-browser.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// The deltic-browser leg: both composed artifacts run runtime-linked
// inside headless Chromium — the page, worker pool, stall watchdog, and
// Chrome ladder all live in @polymorph/component-test-js, and the
// upstream DELTIC worker (js/runner-deltic/browser-worker.mjs) loads the
// pinned deltic-embedder.mjs release asset and links the suite in the
// browser: no transpile step, no generated tree. This file is the frame:
// asset URL wiring, target configuration, and results-file writing —
// the browser sibling of ../deltic/run.ts exactly as ../jco/run-browser.mjs
// is the browser sibling of ../jco/run-node.mjs.
//
// The artifacts import only wasi 0.2 and test-context, so there is no
// SUT host module on this leg and the stock upstream worker serves it
// unmodified (wasiShims + test-context are inside the bundle).
//
// Gates in CI (the Actions runner image ships Chrome); locally it runs
// under CONFORMANCE_BROWSER=1 (`just conformance-ct::all`) or directly
// via `just conformance-ct::run-deltic-browser`. The justfile recipe
// fetches the sha256-pinned release assets first (fetch-translator.ts
// --asset translator|embedder), cached under target/deltic/<tag>/ and
// served to the page from the repository-root server.
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { parseArgs } from "node:util";

import {
buildHarnessPage,
findChrome,
MOUNT,
runPageHarness,
} from "@polymorph/component-test-js/browser-driver";
import { writeResultsFile } from "@polymorph/component-test-js/node-runner";

const DELTIC_DIR = dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = join(DELTIC_DIR, "..", "..", "..");
// Must agree with fetch-translator.ts's TAG (assets are served from its
// cache directory).
const TAG = "pre-83fff30";
const ASSETS = `/target/deltic/${TAG}`;
const CASE_TIMEOUT_MS = 60_000;
const STALL_TIMEOUT_MS = 90_000;

const { values } = parseArgs({
options: {
out: { type: "string", default: join(DELTIC_DIR, "..", "results") },
},
});

const common = {
suite: "conformance-guest-ct",
bundleUrl: `${ASSETS}/deltic-embedder.mjs`,
translatorUrl: `${ASSETS}/deltic-translator-shim.wasm`,
caseTimeoutMs: CASE_TIMEOUT_MS,
};
const SUITES = [
{
...common,
target: "deltic-browser",
suiteUrl: "/target/conformance/suite-plain.wasm",
missing: ["delegated-signer"],
},
{
...common,
target: "deltic-browser-delegated",
suiteUrl: "/target/conformance/suite-delegated.wasm",
missing: [],
},
];

const playwright = await import("playwright-core");
const outcome = await runPageHarness({
playwright,
engine: "chromium",
executablePath: await findChrome(),
repoRoot: REPO_ROOT,
html: buildHarnessPage({
title: "polymorph:tls conformance (deltic-browser)",
config: {
jobs: 1,
workerUrl: `${MOUNT}/js/runner-deltic/browser-worker.mjs`,
suites: SUITES,
},
}),
stallTimeoutMs: STALL_TIMEOUT_MS,
});

let failed = 0;
for (const { target } of SUITES) {
const run = outcome[target];
if (!run) throw new Error(`the page reported no run for target ${target}`);
const outPath = await writeResultsFile({ dir: values.out, target, lines: run.lines });
const c = run.counts;
process.stderr.write(
`${target}: ${c.passed} passed, ${c.failed} failed, ${c.skipped} skipped, ` +
`${c.na} not applicable, ${c.total} total (wrote ${outPath})\n`,
);
failed += c.failed;
}
process.exit(failed === 0 ? 0 : 1);
Loading
Loading