58 lines
3.0 KiB
TypeScript
58 lines
3.0 KiB
TypeScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { createCamJob } from '../src/facade/cam'
|
|
import { CAM_PIPELINE_ORDER, camoticsSourceEvidence, prepareCamPipeline, submitCamPipelineToLinuxcnc } from '../src/facade/camPipeline'
|
|
import { OPEN_CAM_LIB_ARTIFACT_SHA256, OPEN_CAM_LIB_SOURCE_REVISION, type OpenCamLibDropCutterInput } from '../src/facade/camNativeSimulation'
|
|
|
|
const job = () => {
|
|
const cam = createCamJob('pipeline', 'CAD/OCL/CAMotics/LinuxCNC')
|
|
cam.addTool({ id: 'T1', name: 'end mill', diameter: 2, length: 20 })
|
|
cam.addOperation({ id: 'profile', kind: 'profile', toolId: 'T1', depth: 1, feed: 100 })
|
|
cam.generatePath('profile')
|
|
return cam
|
|
}
|
|
|
|
const openCamLibRunner = async (input: OpenCamLibDropCutterInput) => ({
|
|
backend: 'upstream-opencamlib-wasm' as const,
|
|
sourceRevision: OPEN_CAM_LIB_SOURCE_REVISION,
|
|
artifactSha256: OPEN_CAM_LIB_ARTIFACT_SHA256,
|
|
algorithm: 'path-drop-cutter' as const,
|
|
triangleCount: input.triangles.length,
|
|
points: input.path.map((point) => [...point] as [number, number, number]),
|
|
})
|
|
|
|
test('pipeline evidence pins CAMotics source and canonical LinuxCNC policy', () => {
|
|
assert.deepEqual(CAM_PIPELINE_ORDER, ['CAD', 'OCL', 'CAMotics', 'GCODE', 'LinuxCNC WASM'])
|
|
const evidence = camoticsSourceEvidence()
|
|
assert.equal(evidence.backend, 'camotics-source')
|
|
assert.equal(evidence.generator, 'camotics-source-stage')
|
|
assert.equal(evidence.workspaceNativeCli, 'verified-sidecar')
|
|
assert.equal(evidence.browserNativeExecutable, false)
|
|
assert.equal(evidence.parserAuthority, 'linuxcnc-wasm')
|
|
assert.equal(evidence.camoticsParsesCanonicalGcode, false)
|
|
assert.equal(evidence.sourceRevision.length, 40)
|
|
})
|
|
|
|
test('LinuxCNC WASM cannot be called before the OCL and G-code stages are prepared', async () => {
|
|
const prepared = await prepareCamPipeline(job(), 'profile', { openCamLib: { runner: openCamLibRunner } })
|
|
assert.equal(prepared.stage, 'GCODE')
|
|
assert.equal(prepared.openCamLib.backend, 'upstream-opencamlib-wasm')
|
|
assert.equal(prepared.openCamLib.inputPoints, 5)
|
|
assert.equal(prepared.openCamLib.outputPoints, 5)
|
|
const submitted = await submitCamPipelineToLinuxcnc(prepared, {
|
|
submit: async (program) => ({ backend: 'linuxcnc-wasm', status: 'dry-run', programSha256: String(program.length) }),
|
|
})
|
|
assert.equal(submitted.stage, 'LinuxCNC WASM')
|
|
assert.equal(submitted.linuxcnc?.status, 'dry-run')
|
|
assert.match(submitted.gcode, /G90/)
|
|
assert.match(submitted.camoticsMotionGcode, /G1 X/)
|
|
})
|
|
|
|
test('pipeline rejects non-LinuxCNC posts before any machine submission', async () => {
|
|
await assert.rejects(() => prepareCamPipeline(job(), 'profile', { postprocessor: 'grbl', openCamLib: { runner: openCamLibRunner } }), /requires the linuxcnc postprocessor/)
|
|
})
|
|
|
|
test('pipeline rejects an unpinned OCL result instead of bypassing the native stage', async () => {
|
|
await assert.rejects(() => prepareCamPipeline(job(), 'profile', { openCamLib: { runner: async (input) => ({ ...await openCamLibRunner(input), sourceRevision: '0'.repeat(40) }) } }), /pinned upstream WASM identity/)
|
|
})
|