import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { readFileSync, statSync } from "node:fs"; import { dirname, resolve } from "node:path"; import { fileURLToPath } from "node:url"; import { loadPyodide } from "../../app/node_modules/pyodide/pyodide.mjs"; import { createLinuxCncPythonRemapPyodideProvider } from "../../../wasm-port/runtime/sdk/src/python-remap-pyodide-provider.js"; import { createLinuxCncPythonRemapRuntimePort } from "../../../wasm-port/runtime/sdk/src/python-remap-runtime-port.js"; const webRoot = resolve(dirname(fileURLToPath(import.meta.url)), "../.."); const linuxCncRoot = resolve(webRoot, "../linuxcnc/configs/sim"); const provider = createLinuxCncPythonRemapPyodideProvider({ loadPyodide, sourceLoader: (path) => readFile(resolve(linuxCncRoot, path), "utf8"), }); const port = createLinuxCncPythonRemapRuntimePort({ runtimeMode: "pyodide-cpython-wasm", runtimeAdapter: provider, }); const start = await port.start(); assert.equal(start.runtimeExecutionReady, true); assert.equal(start.executionEnabled, true); assert.equal(start.promotionAllowed, true); const result = await port.runLifecyclePlan(); assert.equal(result.validation.ready, true); assert.equal(result.validation.firstYield, 2); assert.equal(result.executionEnabled, true); assert.equal(result.promotionAllowed, true); const diagnostics = port.exportDiagnostics(); assert.equal(diagnostics.runtimeMode, "pyodide-cpython-wasm"); assert.equal(diagnostics.lifecycleTranscriptReady, true); assert.equal(diagnostics.executionEnabled, true); assert.equal(diagnostics.promotionAllowed, true); await port.close(); const boundaryTsv = readFileSync( resolve(webRoot, "../wasm-port/build/wasm/sim-configs-inventory/python-remap-boundary-summary.tsv"), "utf8", ).trim().split(/\r?\n/); const boundaryHeaders = boundaryTsv.shift().split("\t"); const boundaryRows = boundaryTsv.map((line) => { const values = line.split("\t"); return Object.fromEntries(boundaryHeaders.map((key, index) => [key, values[index] ?? ""])); }); assert.equal(boundaryRows.length, 53); const allSourceFiles = [...new Set(boundaryRows.flatMap((row) => row.python_modules.split(",")).filter((path) => path && path !== "-"))].sort(); const bulkProvider = createLinuxCncPythonRemapPyodideProvider({ loadPyodide, sourceLoader: (path) => { const sourcePath = path.startsWith("axis/nc_files/") ? resolve(webRoot, "../linuxcnc/nc_files", path.slice("axis/nc_files/".length)) : resolve(linuxCncRoot, path); return readFile(sourcePath, "utf8"); }, }); await bulkProvider.start({ sourceFiles: allSourceFiles }); const sourceValidation = await bulkProvider.validateStagedSources(); assert.equal(sourceValidation.ready, true); assert.equal(sourceValidation.sourceCount, allSourceFiles.length); for (const sourceFile of allSourceFiles) { const distPath = sourceFile.startsWith("axis/nc_files/") ? resolve(webRoot, "app/dist/linuxcnc/nc_files", sourceFile.slice("axis/nc_files/".length)) : resolve(webRoot, "app/dist/linuxcnc/configs/sim", sourceFile); assert.equal(statSync(distPath).isFile(), true, `${sourceFile}: missing static Python remap source`); } await bulkProvider.close(); console.log("python_remap_pyodide_node_runtime=ok"); console.log("python_remap_queuebuster_generator=ok"); console.log(`python_remap_inventory_rows=${boundaryRows.length}`); console.log(`python_remap_unique_python_sources=${allSourceFiles.length}`); console.log("python_remap_pyodide_bulk_source_validation=ok");