// M9 and the real worker, in Chromium (Playwright). The packages are bundled // with esbuild as an editor would bundle them. // // - M9: every FILIUS example of the corpus (but the one with modems, which // the core has not got yet), run 30 s with a few lines typed, gives the // same capture and windows in Chromium as in Node. // - LocalSimHost in a real Worker: started, pinged, the frames come back. import { readdirSync, readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; import { expect, test } from '@playwright/test'; import { build } from 'esbuild'; import { traceText } from './traceDigest.js'; const here = dirname(fileURLToPath(import.meta.url)); const examples = join(here, '../../../corpus/java-examples'); /** Remote links (Modem) are not in the core yet: this example's run stops at its first frame to the modem. */ const NOT_YET = new Set(['modem_beispiel.fls']); async function bundle(entry: string): Promise { const result = await build({ entryPoints: [join(here, entry)], bundle: true, format: 'iife', platform: 'browser', write: false, logLevel: 'silent' }); return result.outputFiles[0]!.text; } test.describe.configure({ mode: 'serial' }); test('M9: the same trace in Node and in Chromium', async ({ page }) => { test.setTimeout(240_000); await page.setContent('M9'); await page.addScriptTag({ content: await bundle('m9Entry.ts') }); for (const name of readdirSync(examples).filter((file) => file.endsWith('.fls') && !NOT_YET.has(file))) { const archive = new Uint8Array(readFileSync(join(examples, name))); const inNode = traceText(archive); // Every run has traffic: frames on the cards and lines in a window. expect(inNode.includes('"protocol":"ARP"') && inNode.includes('"kind":"text"'), name).toBe(true); const inBrowser = await page.evaluate((bytes) => (globalThis as unknown as { filiusM9: { traceText: (archive: Uint8Array) => string } }).filiusM9.traceText(new Uint8Array(bytes)), [...archive]); expect(inBrowser.length, name).toBe(inNode.length); expect(inBrowser === inNode, name).toBe(true); } }); test('LocalSimHost runs the room in a real worker', async ({ page }) => { await page.setContent('LocalSimHost'); await page.addScriptTag({ content: await bundle('localSimHostEntry.ts') }); const archive = [...new Uint8Array(readFileSync(join(examples, 'internetwork_komplett.fls')))]; const workerCode = await bundle('../src/worker.ts'); const result = await page.evaluate( async ({ bytes, code }) => { const api = (globalThis as unknown as { filiusLocal: { run: (archive: Uint8Array, workerUrl: string) => Promise<{ icmpRows: number; mode: string }> } }).filiusLocal; return api.run(new Uint8Array(bytes), URL.createObjectURL(new Blob([code], { type: 'text/javascript' }))); }, { bytes: archive, code: workerCode }, ); expect(result.mode).toBe('simulation'); expect(result.icmpRows).toBeGreaterThanOrEqual(8); });