参考所有分组,完成尽量多的内容。禁止顺手扩功能 smoke
结论:按 LinuxCNC source policy 将 TOOL_TABLE 恢复为 source coverage only,撤回生成 API/browser switchkins cases,并增加 checker/native 守护;表校验、native、source-link 均通过。
This commit is contained in:
@@ -2556,6 +2556,144 @@ JS
|
||||
fi
|
||||
}
|
||||
|
||||
validate_tool_table_source_coverage_only() {
|
||||
local table_file=$1
|
||||
local cpp_file=$2
|
||||
local json_file=$3
|
||||
local api_file=$4
|
||||
local wasm_core_file=$5
|
||||
local types_file=$6
|
||||
local label=$7
|
||||
if command -v python3 >/dev/null 2>&1; then
|
||||
if ! python3 - "$table_file" "$cpp_file" "$json_file" "$api_file" "$wasm_core_file" "$types_file" "$label" <<'PY'
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
table_file, cpp_file, json_file, api_file, wasm_core_file, types_file, label = sys.argv[1:]
|
||||
table_row_re = re.compile(
|
||||
r'^\s*\{("(?:(?:\\.)|[^"\\])*"),\s*'
|
||||
r'(-?\d+),\s*(-?\d+),\s*(-?\d+)\},?\s*$'
|
||||
)
|
||||
case_row_re = re.compile(
|
||||
r'^\s*\{("(?:(?:\\.)|[^"\\])*"),\s*'
|
||||
r'("(?:(?:\\.)|[^"\\])*"),\s*'
|
||||
r'(-?\d+),\s*(-?\d+),\s*(-?\d+)\},?\s*$'
|
||||
)
|
||||
|
||||
bad_aliases = []
|
||||
with open(table_file, encoding="utf-8") as handle:
|
||||
for line_number, line in enumerate(handle, 1):
|
||||
match = table_row_re.match(line)
|
||||
if match:
|
||||
alias = json.loads(match.group(1)).lower()
|
||||
if alias.endswith(".tbl") or "/tool" in alias or "tool_table" in alias or "tooltable" in alias:
|
||||
bad_aliases.append((line_number, alias))
|
||||
|
||||
bad_cases = []
|
||||
with open(cpp_file, encoding="utf-8") as handle:
|
||||
for line_number, line in enumerate(handle, 1):
|
||||
match = case_row_re.match(line)
|
||||
if match:
|
||||
field = json.loads(match.group(1)).lower()
|
||||
value = json.loads(match.group(2)).lower()
|
||||
if "tool" in field or value.endswith(".tbl"):
|
||||
bad_cases.append((line_number, field, value))
|
||||
|
||||
with open(json_file, encoding="utf-8") as handle:
|
||||
for index, entry in enumerate(json.load(handle)):
|
||||
field = entry["field"].lower()
|
||||
value = entry["value"].lower()
|
||||
if "tool" in field or value.endswith(".tbl"):
|
||||
bad_cases.append((index, field, value))
|
||||
|
||||
with open(api_file, encoding="utf-8") as handle:
|
||||
api_text = handle.read()
|
||||
with open(wasm_core_file, encoding="utf-8") as handle:
|
||||
wasm_text = handle.read()
|
||||
with open(types_file, encoding="utf-8") as handle:
|
||||
types_text = handle.read()
|
||||
|
||||
bad_bridge_tokens = []
|
||||
for token, text in {
|
||||
"api": api_text,
|
||||
"wasm": wasm_text,
|
||||
"types": types_text,
|
||||
}.items():
|
||||
if re.search(r'\btoolTable\b|\btooltable\b|\btool_table\b|\bTOOL_TABLE\b', text):
|
||||
bad_bridge_tokens.append(token)
|
||||
|
||||
if bad_aliases:
|
||||
raise SystemExit(f"{label} generated TOOL_TABLE alias(es), but TOOL_TABLE is source coverage only: {bad_aliases}")
|
||||
if bad_cases:
|
||||
raise SystemExit(f"{label} generated TOOL_TABLE case(s), but TOOL_TABLE is source coverage only: {bad_cases}")
|
||||
if bad_bridge_tokens:
|
||||
raise SystemExit(f"{label} exposes TOOL_TABLE through switchkins API/web bridge: {bad_bridge_tokens}")
|
||||
PY
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
elif command -v node >/dev/null 2>&1; then
|
||||
if ! node - "$table_file" "$cpp_file" "$json_file" "$api_file" "$wasm_core_file" "$types_file" "$label" <<'JS'
|
||||
const fs = require("fs");
|
||||
const [tableFile, cppFile, jsonFile, apiFile, wasmCoreFile, typesFile, label] = process.argv.slice(2);
|
||||
const tableRowRe = /^\s*\{("(?:(?:\\.)|[^"\\])*"),\s*(-?\d+),\s*(-?\d+),\s*(-?\d+)\},?\s*$/;
|
||||
const caseRowRe = /^\s*\{("(?:(?:\\.)|[^"\\])*"),\s*("(?:(?:\\.)|[^"\\])*"),\s*(-?\d+),\s*(-?\d+),\s*(-?\d+)\},?\s*$/;
|
||||
const badAliases = [];
|
||||
fs.readFileSync(tableFile, "utf8").split(/\r?\n/).forEach((line, index) => {
|
||||
const match = tableRowRe.exec(line);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
const alias = JSON.parse(match[1]).toLowerCase();
|
||||
if (alias.endsWith(".tbl") || alias.includes("/tool") || alias.includes("tool_table") || alias.includes("tooltable")) {
|
||||
badAliases.push([index + 1, alias]);
|
||||
}
|
||||
});
|
||||
const badCases = [];
|
||||
fs.readFileSync(cppFile, "utf8").split(/\r?\n/).forEach((line, index) => {
|
||||
const match = caseRowRe.exec(line);
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
const field = JSON.parse(match[1]).toLowerCase();
|
||||
const value = JSON.parse(match[2]).toLowerCase();
|
||||
if (field.includes("tool") || value.endsWith(".tbl")) {
|
||||
badCases.push([index + 1, field, value]);
|
||||
}
|
||||
});
|
||||
JSON.parse(fs.readFileSync(jsonFile, "utf8")).forEach((entry, index) => {
|
||||
const field = entry.field.toLowerCase();
|
||||
const value = entry.value.toLowerCase();
|
||||
if (field.includes("tool") || value.endsWith(".tbl")) {
|
||||
badCases.push([index, field, value]);
|
||||
}
|
||||
});
|
||||
const bridgeTokenRe = /\btoolTable\b|\btooltable\b|\btool_table\b|\bTOOL_TABLE\b/;
|
||||
const badBridgeTokens = [
|
||||
["api", fs.readFileSync(apiFile, "utf8")],
|
||||
["wasm", fs.readFileSync(wasmCoreFile, "utf8")],
|
||||
["types", fs.readFileSync(typesFile, "utf8")],
|
||||
].filter(([_name, text]) => bridgeTokenRe.test(text)).map(([name]) => name);
|
||||
if (badAliases.length > 0) {
|
||||
throw new Error(`${label} generated TOOL_TABLE alias(es), but TOOL_TABLE is source coverage only: ${JSON.stringify(badAliases)}`);
|
||||
}
|
||||
if (badCases.length > 0) {
|
||||
throw new Error(`${label} generated TOOL_TABLE case(s), but TOOL_TABLE is source coverage only: ${JSON.stringify(badCases)}`);
|
||||
}
|
||||
if (badBridgeTokens.length > 0) {
|
||||
throw new Error(`${label} exposes TOOL_TABLE through switchkins API/web bridge: ${badBridgeTokens.join(",")}`);
|
||||
}
|
||||
JS
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "missing python3 or node for switchkins TOOL_TABLE source-only validation" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
for generated_file in \
|
||||
linuxcnc_switchkins_remap_table.inc \
|
||||
linuxcnc_switchkins_remap_config_cases.inc \
|
||||
@@ -2576,6 +2714,14 @@ validate_web_switchkins_case_fields \
|
||||
web/src/wasm-core.js \
|
||||
web/src/index.ts \
|
||||
"generated"
|
||||
validate_tool_table_source_coverage_only \
|
||||
"$generated_dir/linuxcnc_switchkins_remap_table.inc" \
|
||||
"$generated_dir/linuxcnc_switchkins_remap_config_cases.inc" \
|
||||
"$generated_dir/linuxcnc_switchkins_remap_config_cases.json" \
|
||||
core/src/cnc_sim_api.cpp \
|
||||
web/src/wasm-core.js \
|
||||
web/src/index.ts \
|
||||
"generated"
|
||||
|
||||
validate_generated_header \
|
||||
"$generated_dir/linuxcnc_switchkins_remap_table.inc" \
|
||||
@@ -2596,22 +2742,22 @@ validate_generated_header \
|
||||
validate_generated_source_notes \
|
||||
"$generated_dir/linuxcnc_switchkins_remap_table.inc" \
|
||||
"table" \
|
||||
"// Source: LinuxCNC INI MACHINE/KINEMATICS/HALFILE/POSTGUI_HALFILE/TOOL_TABLE/SUBROUTINE_PATH/REMAP entries and" \
|
||||
"// Source: LinuxCNC INI MACHINE/KINEMATICS/HALFILE/POSTGUI_HALFILE/SUBROUTINE_PATH/REMAP entries and" \
|
||||
"// adjacent remap_subs/{428,429,430}remap.ngc #<kinstype> assignments."
|
||||
validate_generated_source_notes \
|
||||
core/src/linuxcnc_switchkins_remap_table.inc \
|
||||
"tracked table" \
|
||||
"// Source: LinuxCNC INI MACHINE/KINEMATICS/HALFILE/POSTGUI_HALFILE/TOOL_TABLE/SUBROUTINE_PATH/REMAP entries and" \
|
||||
"// Source: LinuxCNC INI MACHINE/KINEMATICS/HALFILE/POSTGUI_HALFILE/SUBROUTINE_PATH/REMAP entries and" \
|
||||
"// adjacent remap_subs/{428,429,430}remap.ngc #<kinstype> assignments."
|
||||
validate_generated_source_notes \
|
||||
"$generated_dir/linuxcnc_switchkins_remap_config_cases.inc" \
|
||||
"config cases" \
|
||||
"// Source: LinuxCNC INI config path, MACHINE, KINEMATICS, non-LIB HALFILE/POSTGUI_HALFILE, TOOL_TABLE," \
|
||||
"// Source: LinuxCNC INI config path, MACHINE, KINEMATICS, non-LIB HALFILE/POSTGUI_HALFILE," \
|
||||
"// SUBROUTINE_PATH-resolved remap_subs entries, and adjacent M428/M429/M430 #<kinstype> assignments."
|
||||
validate_generated_source_notes \
|
||||
core/tests/linuxcnc_switchkins_remap_config_cases.inc \
|
||||
"tracked config cases" \
|
||||
"// Source: LinuxCNC INI config path, MACHINE, KINEMATICS, non-LIB HALFILE/POSTGUI_HALFILE, TOOL_TABLE," \
|
||||
"// Source: LinuxCNC INI config path, MACHINE, KINEMATICS, non-LIB HALFILE/POSTGUI_HALFILE," \
|
||||
"// SUBROUTINE_PATH-resolved remap_subs entries, and adjacent M428/M429/M430 #<kinstype> assignments."
|
||||
|
||||
validate_json "$generated_dir/linuxcnc_switchkins_remap_config_cases.json" "generated linuxcnc_switchkins_remap_config_cases.json"
|
||||
|
||||
Reference in New Issue
Block a user