继续推进:浏览器批量验证LinuxCNC配置入口

结论:浏览器 WASM smoke 已读取 LinuxCNC 生成的 64 个 switchkins 配置用例,覆盖 config/MACHINE/KINEMATICS/HALFILE 入口;native 与 source-link 验证通过。
This commit is contained in:
cnc
2026-05-30 10:19:32 +08:00
parent c2d1aa6fe3
commit 1498d9830d
6 changed files with 134 additions and 4 deletions

View File

@@ -8,10 +8,14 @@ manifest=${1:-linuxcnc-kinematics-source-files.txt}
generated_table=$(mktemp "${TMPDIR:-/tmp}/linuxcnc_switchkins_remap_table.XXXXXX.inc") generated_table=$(mktemp "${TMPDIR:-/tmp}/linuxcnc_switchkins_remap_table.XXXXXX.inc")
generated_cases=$(mktemp "${TMPDIR:-/tmp}/linuxcnc_switchkins_remap_config_cases.XXXXXX.inc") generated_cases=$(mktemp "${TMPDIR:-/tmp}/linuxcnc_switchkins_remap_config_cases.XXXXXX.inc")
trap 'rm -f "$generated_table" "$generated_cases"' EXIT generated_json_cases=$(mktemp "${TMPDIR:-/tmp}/linuxcnc_switchkins_remap_config_cases.XXXXXX.json")
trap 'rm -f "$generated_table" "$generated_cases" "$generated_json_cases"' EXIT
LINUXCNC_ROOT="$linuxcnc_root" ./generate-linuxcnc-switchkins-remap-table.sh "$manifest" > "$generated_table" LINUXCNC_ROOT="$linuxcnc_root" ./generate-linuxcnc-switchkins-remap-table.sh "$manifest" > "$generated_table"
diff -u core/src/linuxcnc_switchkins_remap_table.inc "$generated_table" diff -u core/src/linuxcnc_switchkins_remap_table.inc "$generated_table"
LINUXCNC_ROOT="$linuxcnc_root" ./generate-linuxcnc-switchkins-remap-table.sh --config-cases "$manifest" > "$generated_cases" LINUXCNC_ROOT="$linuxcnc_root" ./generate-linuxcnc-switchkins-remap-table.sh --config-cases "$manifest" > "$generated_cases"
diff -u core/tests/linuxcnc_switchkins_remap_config_cases.inc "$generated_cases" diff -u core/tests/linuxcnc_switchkins_remap_config_cases.inc "$generated_cases"
LINUXCNC_ROOT="$linuxcnc_root" ./generate-linuxcnc-switchkins-remap-table.sh --json-cases "$manifest" > "$generated_json_cases"
diff -u web/public/linuxcnc_switchkins_remap_config_cases.json "$generated_json_cases"

View File

@@ -8,6 +8,9 @@ mode=table
if [[ "${1:-}" == "--config-cases" ]]; then if [[ "${1:-}" == "--config-cases" ]]; then
mode=config-cases mode=config-cases
shift shift
elif [[ "${1:-}" == "--json-cases" ]]; then
mode=json-cases
shift
fi fi
manifest=${1:-linuxcnc-kinematics-source-files.txt} manifest=${1:-linuxcnc-kinematics-source-files.txt}
@@ -131,6 +134,7 @@ declare -A seen_aliases=()
declare -A seen_cases=() declare -A seen_cases=()
entries=() entries=()
case_entries=() case_entries=()
json_case_entries=()
add_alias() { add_alias() {
local alias=$1 local alias=$1
@@ -166,9 +170,12 @@ add_case() {
[[ -z "${seen_cases[$key]:-}" ]] || return 0 [[ -z "${seen_cases[$key]:-}" ]] || return 0
seen_cases[$key]=1 seen_cases[$key]=1
field=$(cpp_string "$field") local cpp_field
value=$(cpp_string "$value") local cpp_value
case_entries+=(" {\"$field\", \"$value\", $m428, $m429, $m430},") cpp_field=$(cpp_string "$field")
cpp_value=$(cpp_string "$value")
case_entries+=(" {\"$cpp_field\", \"$cpp_value\", $m428, $m429, $m430},")
json_case_entries+=("{\"field\":\"$cpp_field\",\"value\":\"$cpp_value\",\"m428\":$m428,\"m429\":$m429,\"m430\":$m430}")
} }
add_machine_aliases() { add_machine_aliases() {
@@ -298,6 +305,16 @@ elif [[ "$mode" == config-cases ]]; then
EOF EOF
printf '%s\n' "${case_entries[@]}" printf '%s\n' "${case_entries[@]}"
elif [[ "$mode" == json-cases ]]; then
printf '[\n'
for i in "${!json_case_entries[@]}"; do
suffix=,
if [[ "$i" == "$((${#json_case_entries[@]} - 1))" ]]; then
suffix=
fi
printf ' %s%s\n' "${json_case_entries[$i]}" "$suffix"
done
printf ']\n'
else else
echo "unknown switchkins remap table generator mode: $mode" >&2 echo "unknown switchkins remap table generator mode: $mode" >&2
exit 1 exit 1

View File

@@ -0,0 +1,66 @@
[
{"field":"config","value":"configs/sim/axis/vismach/5axis/bridgemill/5axis.ini","m428":0,"m429":1,"m430":2},
{"field":"machine","value":"Sim-5Axis Bridge Mill (xyzbcw)","m428":0,"m429":1,"m430":2},
{"field":"kinematics","value":"5axiskins coordinates=xyzbcwy","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"5axisgui.hal","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"5axisgui","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"5axisgui.hal","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"5axisgui","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/5axis/table-dual-rotary/xyzab-tdr.ini","m428":1,"m429":0,"m430":-1},
{"field":"machine","value":"sim-xyzab-tdr-kins (switchkins)","m428":1,"m429":0,"m430":-1},
{"field":"kinematics","value":"xyzab_tdr_kins","m428":1,"m429":0,"m430":-1},
{"field":"config","value":"configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini","m428":1,"m429":0,"m430":2},
{"field":"machine","value":"sim-xyzac-trt-kins (switchkins)","m428":1,"m429":0,"m430":2},
{"field":"kinematics","value":"xyzac-trt-kins sparm=identityfirst","m428":1,"m429":0,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzbc-trt.ini","m428":1,"m429":0,"m430":2},
{"field":"machine","value":"sim-xyzbc-trt-kins (switchkins)","m428":1,"m429":0,"m430":2},
{"field":"kinematics","value":"xyzbc-trt-kins sparm=identityfirst","m428":1,"m429":0,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzacb-trsrn_twp/xyzacb-trsrn.ini","m428":0,"m429":1,"m430":2},
{"field":"machine","value":"xyzacb-trsrn (switchkins)","m428":0,"m429":1,"m430":2},
{"field":"kinematics","value":"xyzacb_trsrn","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/5axis/table-rotary_spindle-rotary-nutating/xyzbca-trsrn_twp/xyzbca-trsrn.ini","m428":0,"m429":1,"m430":2},
{"field":"machine","value":"xyzbca-trsrn (switchkins)","m428":0,"m429":1,"m430":2},
{"field":"kinematics","value":"xyzbca_trsrn","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/hexapod-sim/hexapod.ini","m428":0,"m429":1,"m430":2},
{"field":"machine","value":"hexapod (switchkins)","m428":0,"m429":1,"m430":2},
{"field":"kinematics","value":"genhexkins","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"kinematics.hal","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"kinematics","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"kinematics.hal","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"kinematics","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/melfa-sim/melfa.ini","m428":0,"m429":1,"m430":2},
{"field":"machine","value":"melfa (mm)","m428":0,"m429":1,"m430":2},
{"field":"kinematics","value":"genserkins","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"melfa_dh.hal","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"melfa_dh","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"melfa_dh.hal","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"melfa_dh","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/millturn/millturn.ini","m428":0,"m429":1,"m430":-1},
{"field":"machine","value":"millturn (mm)","m428":0,"m429":1,"m430":-1},
{"field":"kinematics","value":"millturn","m428":0,"m429":1,"m430":-1},
{"field":"halfile","value":"millturn.hal","m428":0,"m429":1,"m430":-1},
{"field":"halfile","value":"millturn","m428":0,"m429":1,"m430":-1},
{"field":"hal_file","value":"millturn.hal","m428":0,"m429":1,"m430":-1},
{"field":"hal_file","value":"millturn","m428":0,"m429":1,"m430":-1},
{"field":"config","value":"configs/sim/axis/vismach/puma/puma.ini","m428":0,"m429":1,"m430":2},
{"field":"machine","value":"PUMA (pumakins,switchkins)","m428":0,"m429":1,"m430":2},
{"field":"kinematics","value":"pumakins","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"puma_dh.hal","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"puma_dh","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"puma_dh.hal","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"puma_dh","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/puma/puma_cube.ini","m428":0,"m429":1,"m430":2},
{"field":"machine","value":"puma_cube.ini (pumakins)","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/puma/puma560.ini","m428":0,"m429":1,"m430":2},
{"field":"machine","value":"puma560 (switchkins) (inch)","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"puma560_dh.hal","m428":0,"m429":1,"m430":2},
{"field":"halfile","value":"puma560_dh","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"puma560_dh.hal","m428":0,"m429":1,"m430":2},
{"field":"hal_file","value":"puma560_dh","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/puma/puma560_uvw.ini","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/axis/vismach/scara/scara.ini","m428":0,"m429":1,"m430":2},
{"field":"machine","value":"SCARA (genserkins,switchkins)","m428":0,"m429":1,"m430":2},
{"field":"kinematics","value":"scarakins coordinates=xyzcab","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/qtaxis/non-trivial/scara/scara.ini","m428":0,"m429":1,"m430":2},
{"field":"config","value":"configs/sim/qtvcp_screens/non-trivial/scara/scara.ini","m428":0,"m429":1,"m430":2}
]

View File

@@ -80,6 +80,12 @@ export type CncParseOptions = {
block_delete?: boolean; block_delete?: boolean;
switchkins?: string; switchkins?: string;
remap?: string; remap?: string;
machine?: string;
config?: string;
configPath?: string;
config_path?: string;
halfile?: string;
hal_file?: string;
kinematics?: string; kinematics?: string;
trt?: "xyzbc" | "xyzac" | string; trt?: "xyzbc" | "xyzac" | string;
pivotLength?: number; pivotLength?: number;

View File

@@ -113,6 +113,12 @@ export async function createWasmSimulator(moduleOptions = {}) {
...(options.block_delete !== undefined ? { block_delete: options.block_delete } : {}), ...(options.block_delete !== undefined ? { block_delete: options.block_delete } : {}),
...(options.switchkins ? { switchkins: options.switchkins } : {}), ...(options.switchkins ? { switchkins: options.switchkins } : {}),
...(options.remap ? { remap: options.remap } : {}), ...(options.remap ? { remap: options.remap } : {}),
...(options.machine ? { machine: options.machine } : {}),
...(options.config ? { config: options.config } : {}),
...(options.configPath ? { configPath: options.configPath } : {}),
...(options.config_path ? { config_path: options.config_path } : {}),
...(options.halfile ? { halfile: options.halfile } : {}),
...(options.hal_file ? { hal_file: options.hal_file } : {}),
...(options.kinematics ? { kinematics: options.kinematics } : {}), ...(options.kinematics ? { kinematics: options.kinematics } : {}),
...(options.trt ? { trt: options.trt } : {}), ...(options.trt ? { trt: options.trt } : {}),
...(options.pivotLength !== undefined ? { pivotLength: options.pivotLength } : {}), ...(options.pivotLength !== undefined ? { pivotLength: options.pivotLength } : {}),

View File

@@ -44,6 +44,37 @@
throw new Error(`missing LinuxCNC WASM browser M${427 + line} switchkins type ${kinstype}`); throw new Error(`missing LinuxCNC WASM browser M${427 + line} switchkins type ${kinstype}`);
} }
} }
const configCaseResponse = await fetch("/public/linuxcnc_switchkins_remap_config_cases.json");
if (!configCaseResponse.ok) {
throw new Error(`failed to load LinuxCNC switchkins config cases: ${configCaseResponse.status}`);
}
const configCases = await configCaseResponse.json();
if (!Array.isArray(configCases) || configCases.length === 0) {
throw new Error("missing LinuxCNC switchkins config cases");
}
for (const configCase of configCases) {
const options = {
backend: "linuxcnc-rs274",
[configCase.field]: configCase.value,
};
const program = configCase.m430 >= 0 ? "M428\nM429\nM430\n" : "M428\nM429\n";
const configEvents = simulator.parse(program, "linuxcnc", options);
for (const [line, kinstype] of [
[1, configCase.m428],
[2, configCase.m429],
...(configCase.m430 >= 0 ? [[3, configCase.m430]] : []),
]) {
const sawSwitch = configEvents.some(
(event) => event.type === "kinematics-switch" && event.line === line && event.reserved === kinstype,
);
if (!sawSwitch) {
throw new Error(
`missing LinuxCNC WASM browser generated ${configCase.field}=${configCase.value} line ${line} switchkins type ${kinstype}`,
);
}
}
}
result.textContent = "browser wasm smoke passed"; result.textContent = "browser wasm smoke passed";
} finally { } finally {
simulator.dispose(); simulator.dispose();