408 lines
12 KiB
JavaScript
408 lines
12 KiB
JavaScript
import { readFileSync } from "node:fs";
|
|
import { fileURLToPath } from "node:url";
|
|
import { dirname, resolve } from "node:path";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { createLinuxCncInterpSdk } from "../../../runtime/sdk/src/index.js";
|
|
import {
|
|
INTERP_ERROR_FIXTURES,
|
|
INTERP_FILE_FIXTURES,
|
|
INTERP_INI_FIXTURE,
|
|
INTERP_MDI_FIXTURES,
|
|
INTERP_POSITION_PARAMS_FILE_FIXTURE,
|
|
} from "../../fixtures/interp-fixture-matrix.mjs";
|
|
|
|
function verifyExpectedOutput(fixtureName, output, expectedText) {
|
|
const expectedLines = expectedText.split("\n").filter(Boolean);
|
|
|
|
for (const expectedLine of expectedLines) {
|
|
if (expectedLine.startsWith("absent=")) {
|
|
const forbidden = expectedLine.slice("absent=".length);
|
|
assert.equal(
|
|
output.includes(forbidden),
|
|
false,
|
|
`${fixtureName}: unexpected ${forbidden}`,
|
|
);
|
|
continue;
|
|
}
|
|
|
|
assert.equal(
|
|
output.includes(expectedLine),
|
|
true,
|
|
`${fixtureName}: ${expectedLine}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
function verifyExpectedFileError(fixtureName, output, expectedText) {
|
|
assert.equal(
|
|
output.includes("file_open=0"),
|
|
true,
|
|
`${fixtureName}: file open`,
|
|
);
|
|
|
|
const expectedLines = expectedText.split("\n").filter(Boolean);
|
|
for (const expectedLine of expectedLines) {
|
|
if (expectedLine.startsWith("absent=")) {
|
|
const forbidden = expectedLine.slice("absent=".length);
|
|
assert.equal(
|
|
output.includes(forbidden),
|
|
false,
|
|
`${fixtureName}: unexpected ${forbidden}`,
|
|
);
|
|
continue;
|
|
}
|
|
|
|
if (expectedLine.startsWith("error_text=")) {
|
|
const message = expectedLine.slice("error_text=".length);
|
|
assert.equal(
|
|
output.includes(`file_error_text=${message}`),
|
|
true,
|
|
`${fixtureName}: ${message}`,
|
|
);
|
|
continue;
|
|
}
|
|
|
|
if (expectedLine.startsWith("canon_event=")) {
|
|
assert.equal(
|
|
output.includes(expectedLine),
|
|
true,
|
|
`${fixtureName}: ${expectedLine}`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = dirname(__filename);
|
|
const rootDir = resolve(__dirname, "../../..");
|
|
const wasmPath = resolve(rootDir, "build/wasm/core/linuxcnc_interp.wasm");
|
|
|
|
const interp = await createLinuxCncInterpSdk({
|
|
wasmBinary: readFileSync(wasmPath),
|
|
print() {},
|
|
printErr(message) {
|
|
console.error(message);
|
|
},
|
|
});
|
|
|
|
verifyExpectedOutput(
|
|
"probe_init_and_synch",
|
|
interp.probeInitAndSynch(),
|
|
[
|
|
"init=0",
|
|
"setup.length_units=2",
|
|
"setup.origin_index=1",
|
|
"setup.distance_mode=0",
|
|
"setup.feed_mode=0",
|
|
"setup.motion_mode=800",
|
|
"canon_event=INIT_CANON",
|
|
"canon_event=USE_LENGTH_UNITS units=2",
|
|
"canon_event=SET_G5X_OFFSET index=1",
|
|
"canon_event=SET_G92_OFFSET x=0 y=0 z=0",
|
|
"canon_event=SET_XY_ROTATION rotation=0",
|
|
"canon_event=SET_FEED_REFERENCE reference=2",
|
|
"inch_init=0",
|
|
"inch_setup.length_units=1",
|
|
"inch_external_length_units=0.0393701",
|
|
"inch_canon_event=USE_LENGTH_UNITS units=1",
|
|
"synch=0",
|
|
"synch.current_pocket=2",
|
|
"synch.selected_pocket=2",
|
|
"synch.tool_0=2",
|
|
"synch.tool_2=2",
|
|
].join("\n"),
|
|
);
|
|
|
|
verifyExpectedOutput(
|
|
"probe_indexer",
|
|
interp.probeIndexer(),
|
|
[
|
|
"execute=0",
|
|
"post_a=90",
|
|
"canon_event=SET_MOTION_CONTROL_MODE mode=2 tolerance=0",
|
|
"canon_event=UNLOCK_ROTARY line=1 joint=0",
|
|
"canon_event=STRAIGHT_TRAVERSE line=1 x=0 y=0 z=0 a=90 b=0 c=0 u=0 v=0 w=0",
|
|
"canon_event=LOCK_ROTARY line=1 joint=0",
|
|
"canon_event=SET_MOTION_CONTROL_MODE mode=1 tolerance=0",
|
|
"canon_event=SET_NAIVECAM_TOLERANCE tolerance=0",
|
|
"canon_event=UPDATE_TAG line=1",
|
|
].join("\n"),
|
|
);
|
|
|
|
for (const fixtureName of INTERP_MDI_FIXTURES) {
|
|
const programText = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/gcode/${fixtureName}.ngc`),
|
|
"utf8",
|
|
);
|
|
const expectedEvents = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/canon/${fixtureName}.events`),
|
|
"utf8",
|
|
).trimEnd();
|
|
|
|
verifyExpectedOutput(fixtureName, interp.runProgram(programText), expectedEvents);
|
|
}
|
|
|
|
const namedParamIniPath = "/work/namedparams.ini";
|
|
interp.writeTextFile(
|
|
namedParamIniPath,
|
|
readFileSync(resolve(rootDir, "tests/fixtures/ini/namedparams.ini"), "utf8"),
|
|
);
|
|
const namedParamProgramText = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/gcode/${INTERP_INI_FIXTURE}.ngc`),
|
|
"utf8",
|
|
);
|
|
const namedParamExpected = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/canon/${INTERP_INI_FIXTURE}.events`),
|
|
"utf8",
|
|
).trimEnd();
|
|
verifyExpectedOutput(
|
|
INTERP_INI_FIXTURE,
|
|
interp.runProgramWithIni(namedParamProgramText, namedParamIniPath),
|
|
namedParamExpected,
|
|
);
|
|
|
|
for (const fixtureName of INTERP_ERROR_FIXTURES) {
|
|
const programText = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/gcode_errors/${fixtureName}.ngc`),
|
|
"utf8",
|
|
);
|
|
const expectedOutput = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/canon_errors/${fixtureName}.expected`),
|
|
"utf8",
|
|
).trimEnd();
|
|
|
|
verifyExpectedOutput(fixtureName, interp.runProgram(programText), expectedOutput);
|
|
}
|
|
|
|
for (const fixtureName of INTERP_ERROR_FIXTURES) {
|
|
const programPath = `/work/${fixtureName}-error.ngc`;
|
|
const programText = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/gcode_errors/${fixtureName}.ngc`),
|
|
"utf8",
|
|
);
|
|
const expectedOutput = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/canon_errors/${fixtureName}.expected`),
|
|
"utf8",
|
|
).trimEnd();
|
|
|
|
interp.writeTextFile(programPath, programText);
|
|
verifyExpectedFileError(fixtureName, interp.runFile(programPath), expectedOutput);
|
|
}
|
|
|
|
for (const fixtureName of INTERP_FILE_FIXTURES) {
|
|
const programPath = `/work/${fixtureName}.ngc`;
|
|
const programText = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/gcode/${fixtureName}.ngc`),
|
|
"utf8",
|
|
);
|
|
const expectedEvents = readFileSync(
|
|
resolve(rootDir, `tests/fixtures/canon/${fixtureName}.events`),
|
|
"utf8",
|
|
).trimEnd();
|
|
|
|
interp.writeTextFile(programPath, programText);
|
|
verifyExpectedOutput(fixtureName, interp.runFile(programPath), expectedEvents);
|
|
}
|
|
|
|
const namedParamFilePath = `/work/${INTERP_INI_FIXTURE}.ngc`;
|
|
interp.writeTextFile(namedParamFilePath, namedParamProgramText);
|
|
verifyExpectedOutput(
|
|
"namedparam_semantics_file",
|
|
interp.runFileWithIni(namedParamFilePath, namedParamIniPath),
|
|
namedParamExpected,
|
|
);
|
|
|
|
const positionParamsFilePath = "/work/position_params.ngc";
|
|
interp.writeTextFile(
|
|
positionParamsFilePath,
|
|
readFileSync(
|
|
resolve(rootDir, `tests/fixtures/gcode/${INTERP_POSITION_PARAMS_FILE_FIXTURE}.ngc`),
|
|
"utf8",
|
|
),
|
|
);
|
|
verifyExpectedOutput(
|
|
`${INTERP_POSITION_PARAMS_FILE_FIXTURE}_file`,
|
|
interp.runFile(positionParamsFilePath),
|
|
readFileSync(
|
|
resolve(
|
|
rootDir,
|
|
`tests/fixtures/canon_file/${INTERP_POSITION_PARAMS_FILE_FIXTURE}.events`,
|
|
),
|
|
"utf8",
|
|
).trimEnd(),
|
|
);
|
|
|
|
const parameterFilePath = "/work/rs274ngc.var";
|
|
interp.writeTextFile(
|
|
parameterFilePath,
|
|
[
|
|
"5161 10.5",
|
|
"5162 20.25",
|
|
"5220 1",
|
|
"5221 2.25",
|
|
"5399 44",
|
|
"<_named_param> 123",
|
|
"",
|
|
].join("\n"),
|
|
);
|
|
verifyExpectedOutput(
|
|
"restore_parameters",
|
|
interp.restoreParameters(parameterFilePath),
|
|
[
|
|
"restore_parameters=0",
|
|
"parameter_5161=10.5",
|
|
"parameter_5162=20.25",
|
|
"parameter_5220=1",
|
|
"parameter_5221=2.25",
|
|
"parameter_5399=44",
|
|
].join("\n"),
|
|
);
|
|
verifyExpectedOutput(
|
|
"restore_parameters_missing_file",
|
|
interp.restoreParameters("/work/missing.var"),
|
|
"restore_parameters=0",
|
|
);
|
|
|
|
const outOfOrderParameterFilePath = "/work/out-of-order.var";
|
|
interp.writeTextFile(outOfOrderParameterFilePath, "5220 1\n5161 2\n");
|
|
verifyExpectedOutput(
|
|
"restore_parameters_out_of_order",
|
|
interp.restoreParameters(outOfOrderParameterFilePath),
|
|
[
|
|
"restore_parameters=5",
|
|
"restore_error_text=Parameter file out of order",
|
|
].join("\n"),
|
|
);
|
|
|
|
verifyExpectedOutput(
|
|
"save_parameters",
|
|
interp.saveParameters(parameterFilePath, {
|
|
5161: 12.34,
|
|
5162: 56.78,
|
|
5220: 1.0,
|
|
5221: 9.87,
|
|
5399: 66.6,
|
|
}),
|
|
[
|
|
"save_parameters=0",
|
|
"parameter_5161=12.34",
|
|
"parameter_5162=56.78",
|
|
"parameter_5220=1",
|
|
"parameter_5221=9.87",
|
|
"parameter_5399=66.6",
|
|
].join("\n"),
|
|
);
|
|
const savedParameterFile = interp.readTextFile(parameterFilePath);
|
|
const backupParameterFile = interp.readTextFile(`${parameterFilePath}.bak`);
|
|
assert.equal(savedParameterFile.includes("5161\t12.340000"), true);
|
|
assert.equal(savedParameterFile.includes("5162\t56.780000"), true);
|
|
assert.equal(savedParameterFile.includes("5221\t9.870000"), true);
|
|
assert.equal(savedParameterFile.includes("5399\t66.600000"), true);
|
|
assert.equal(savedParameterFile.includes("_named_param"), false);
|
|
assert.equal(backupParameterFile.includes("5161 10.5"), true);
|
|
|
|
const toolTablePath = "/work/tool.tbl";
|
|
interp.writeTextFile(
|
|
toolTablePath,
|
|
[
|
|
"T2 P7 Z3.125 D1.5 I12 J34 Q4 ;finish tool",
|
|
"T5 P9 X1 Y2 Z3 ;rough tool",
|
|
"",
|
|
].join("\n"),
|
|
);
|
|
verifyExpectedOutput(
|
|
"load_tool_table",
|
|
interp.loadToolTable(toolTablePath),
|
|
[
|
|
"tooldata_load=0",
|
|
"tooldata_last_index=2",
|
|
"tool_0.toolno=-1",
|
|
"tool_1.toolno=2",
|
|
"tool_1.pocketno=7",
|
|
"tool_1.z=3.125",
|
|
"tool_1.diameter=1.5",
|
|
"tool_1.frontangle=12",
|
|
"tool_1.backangle=34",
|
|
"tool_1.orientation=4",
|
|
"tool_1.comment=finish tool",
|
|
"tool_2.toolno=5",
|
|
"tool_2.pocketno=9",
|
|
"tool_2.z=3",
|
|
"tool_2.comment=rough tool",
|
|
"tool_index_for_tool_2=1",
|
|
].join("\n"),
|
|
);
|
|
verifyExpectedOutput(
|
|
"save_tool_table",
|
|
interp.saveToolTable(toolTablePath),
|
|
[
|
|
"tooldata_save=0",
|
|
"tool_1.toolno=2",
|
|
"tool_2.toolno=5",
|
|
].join("\n"),
|
|
);
|
|
const savedToolTable = interp.readTextFile(toolTablePath);
|
|
assert.equal(savedToolTable.includes("T2"), true);
|
|
assert.equal(savedToolTable.includes("P7"), true);
|
|
assert.equal(savedToolTable.includes("D+1.500000"), true);
|
|
assert.equal(savedToolTable.includes("Z+3.125000"), true);
|
|
assert.equal(savedToolTable.includes("I+12.000000"), true);
|
|
assert.equal(savedToolTable.includes("J+34.000000"), true);
|
|
assert.equal(savedToolTable.includes("Q4"), true);
|
|
assert.equal(savedToolTable.includes(";finish tool"), true);
|
|
assert.equal(savedToolTable.includes("T5"), true);
|
|
assert.equal(savedToolTable.includes("P9"), true);
|
|
assert.equal(savedToolTable.includes(";rough tool"), true);
|
|
|
|
const randomToolTablePath = "/work/random-tool.tbl";
|
|
interp.writeTextFile(
|
|
randomToolTablePath,
|
|
[
|
|
"T2 P7 Z3.125 D1.5 I12 J34 Q4 ;random finish tool",
|
|
"T5 P9 X1 Y2 Z3 ;random rough tool",
|
|
"",
|
|
].join("\n"),
|
|
);
|
|
verifyExpectedOutput(
|
|
"load_tool_table_random",
|
|
interp.loadToolTable(randomToolTablePath, { randomToolChanger: true }),
|
|
[
|
|
"tooldata_random_toolchanger=1",
|
|
"tooldata_load=0",
|
|
"tooldata_last_index=9",
|
|
"tool_1.toolno=-1",
|
|
"tool_2.toolno=-1",
|
|
"tool_pocket_7.toolno=2",
|
|
"tool_pocket_7.pocketno=7",
|
|
"tool_pocket_7.z=3.125",
|
|
"tool_pocket_7.diameter=1.5",
|
|
"tool_pocket_7.frontangle=12",
|
|
"tool_pocket_7.backangle=34",
|
|
"tool_pocket_7.orientation=4",
|
|
"tool_pocket_7.comment=random finish tool",
|
|
"tool_pocket_9.toolno=5",
|
|
"tool_pocket_9.pocketno=9",
|
|
"tool_pocket_9.z=3",
|
|
"tool_pocket_9.comment=random rough tool",
|
|
"tool_index_for_tool_2=7",
|
|
].join("\n"),
|
|
);
|
|
verifyExpectedOutput(
|
|
"save_tool_table_random",
|
|
interp.saveToolTable(randomToolTablePath),
|
|
[
|
|
"tooldata_save=0",
|
|
"tool_pocket_7.toolno=2",
|
|
"tool_pocket_9.toolno=5",
|
|
].join("\n"),
|
|
);
|
|
const savedRandomToolTable = interp.readTextFile(randomToolTablePath);
|
|
assert.equal(savedRandomToolTable.includes("T2"), true);
|
|
assert.equal(savedRandomToolTable.includes("P7"), true);
|
|
assert.equal(savedRandomToolTable.includes(";random finish tool"), true);
|
|
assert.equal(savedRandomToolTable.includes("T5"), true);
|
|
assert.equal(savedRandomToolTable.includes("P9"), true);
|
|
assert.equal(savedRandomToolTable.includes(";random rough tool"), true);
|
|
console.log("interp_wasm_node_smoke=ok");
|