From 173018162e1651941542eb7aab7f21bc26ef59a1 Mon Sep 17 00:00:00 2001 From: wangdequan Date: Sun, 7 Jun 2026 05:54:44 +0800 Subject: [PATCH] wasm-port: add native parameter file harness --- .../linuxcnc_parameter_file_harness.cpp | 128 ++++++++++++++++++ .../tests/native/verify_native_probes.sh | 23 ++++ wasm-port/tools/build_native_probes.sh | 28 ++++ 3 files changed, 179 insertions(+) create mode 100644 wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_parameter_file_harness.cpp diff --git a/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_parameter_file_harness.cpp b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_parameter_file_harness.cpp new file mode 100644 index 0000000..bddab61 --- /dev/null +++ b/wasm-port/runtime/core/linuxcnc_wrap/linuxcnc_parameter_file_harness.cpp @@ -0,0 +1,128 @@ +#define private public +#include "emc/rs274ngc/rs274ngc_interp.hh" +#undef private + +#include +#include +#include +#include +#include +#include + +namespace { + +std::filesystem::path make_temp_dir() +{ + std::string pattern = "/tmp/linuxcnc-params-XXXXXX"; + char *path = mkdtemp(pattern.data()); + if (path == nullptr) { + std::perror("mkdtemp"); + std::exit(2); + } + return path; +} + +void write_file(const std::filesystem::path &path, const std::string &content) +{ + std::ofstream out(path); + if (!out) { + std::cerr << "failed to write " << path << "\n"; + std::exit(2); + } + out << content; +} + +std::string read_file(const std::filesystem::path &path) +{ + std::ifstream in(path); + if (!in) { + std::cerr << "failed to read " << path << "\n"; + std::exit(2); + } + return std::string(std::istreambuf_iterator(in), + std::istreambuf_iterator()); +} + +bool contains(const std::string &haystack, const std::string &needle) +{ + return haystack.find(needle) != std::string::npos; +} + +void print_error_text(Interp &interp, const char *prefix, int status) +{ + char error_buf[LINELEN] = {0}; + interp.error_text(status, error_buf, sizeof(error_buf)); + std::cout << prefix << error_buf << "\n"; +} + +} // namespace + +int main() +{ + const auto temp_dir = make_temp_dir(); + const auto parameter_file = temp_dir / "rs274ngc.var"; + const auto out_of_order_file = temp_dir / "out-of-order.var"; + const auto missing_required_file = temp_dir / "missing-required.var"; + const auto missing_file = temp_dir / "does-not-exist.var"; + + write_file(parameter_file, + "5161 10.5\n" + "5162 20.25\n" + "5220 1\n" + "5221 2.25\n" + "5399 44\n" + "<_named_param> 123\n"); + + write_file(out_of_order_file, + "5220 1\n" + "5161 2\n"); + + write_file(missing_required_file, + "5161 3.5\n" + "5220 1\n"); + + Interp interp; + int rc = interp.restore_parameters(parameter_file.c_str()); + std::cout << "restore_existing=" << rc << "\n"; + std::cout << "parameter_5161=" << interp._setup.parameters[5161] << "\n"; + std::cout << "parameter_5162=" << interp._setup.parameters[5162] << "\n"; + std::cout << "parameter_5220=" << interp._setup.parameters[5220] << "\n"; + std::cout << "parameter_5221=" << interp._setup.parameters[5221] << "\n"; + std::cout << "parameter_5399=" << interp._setup.parameters[5399] << "\n"; + + rc = interp.restore_parameters(missing_file.c_str()); + std::cout << "restore_missing_file=" << rc << "\n"; + + rc = interp.restore_parameters(out_of_order_file.c_str()); + std::cout << "restore_out_of_order=" << rc << "\n"; + if (rc > INTERP_MIN_ERROR) { + print_error_text(interp, "restore_out_of_order_error=", rc); + } + + Interp missing_required_interp; + rc = missing_required_interp.restore_parameters(missing_required_file.c_str()); + std::cout << "restore_missing_required=" << rc << "\n"; + std::cout << "missing_required_5161=" << missing_required_interp._setup.parameters[5161] << "\n"; + std::cout << "missing_required_5162=" << missing_required_interp._setup.parameters[5162] << "\n"; + + interp._setup.parameters[5161] = 12.34; + interp._setup.parameters[5162] = 56.78; + interp._setup.parameters[5220] = 1.0; + interp._setup.parameters[5221] = 9.87; + interp._setup.parameters[5399] = 66.6; + + rc = interp.save_parameters(parameter_file.c_str(), interp._setup.parameters); + std::cout << "save_parameters=" << rc << "\n"; + + const std::string saved = read_file(parameter_file); + const std::string backup = read_file(parameter_file.string() + RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX); + std::cout << "saved_has_5161=" << contains(saved, "5161\t12.340000") << "\n"; + std::cout << "saved_has_5162=" << contains(saved, "5162\t56.780000") << "\n"; + std::cout << "saved_has_5221=" << contains(saved, "5221\t9.870000") << "\n"; + std::cout << "saved_has_5399=" << contains(saved, "5399\t66.600000") << "\n"; + std::cout << "saved_has_named_param=" << contains(saved, "_named_param") << "\n"; + std::cout << "backup_has_original_5161=" << contains(backup, "5161 10.5") << "\n"; + + std::filesystem::remove_all(temp_dir); + return 0; +} diff --git a/wasm-port/tests/native/verify_native_probes.sh b/wasm-port/tests/native/verify_native_probes.sh index de550e1..c389233 100755 --- a/wasm-port/tests/native/verify_native_probes.sh +++ b/wasm-port/tests/native/verify_native_probes.sh @@ -36,6 +36,8 @@ check_exitcode linuxcnc_namedparam_harness check_exitcode linuxcnc_namedparam_harness.run check_exitcode linuxcnc_interp_minimal_harness check_exitcode linuxcnc_interp_minimal_harness.run +check_exitcode linuxcnc_parameter_file_harness +check_exitcode linuxcnc_parameter_file_harness.run check_exitcode linuxcnc_rs274_compile_probe check_exitcode linuxcnc_interp_convert_source_probe @@ -59,6 +61,27 @@ grep -Fq "_hal[standalone.param-u64]: rc=0 found=1 value=9e+09" "$NAMEDPARAM_STD grep -Fq "_hal[standalone.disconnected-float]: rc=0 found=1 value=12.5" "$NAMEDPARAM_STDOUT" grep -Fq "_hal[standalone.missing]: rc=0 found=0 value=0" "$NAMEDPARAM_STDOUT" +PARAMETER_FILE_STDOUT="$BUILD_DIR/linuxcnc_parameter_file_harness.run.stdout.log" +grep -Fq "restore_existing=0" "$PARAMETER_FILE_STDOUT" +grep -Fq "parameter_5161=10.5" "$PARAMETER_FILE_STDOUT" +grep -Fq "parameter_5162=20.25" "$PARAMETER_FILE_STDOUT" +grep -Fq "parameter_5220=1" "$PARAMETER_FILE_STDOUT" +grep -Fq "parameter_5221=2.25" "$PARAMETER_FILE_STDOUT" +grep -Fq "parameter_5399=44" "$PARAMETER_FILE_STDOUT" +grep -Fq "restore_missing_file=0" "$PARAMETER_FILE_STDOUT" +grep -Fq "restore_out_of_order=5" "$PARAMETER_FILE_STDOUT" +grep -Fq "restore_out_of_order_error=Parameter file out of order" "$PARAMETER_FILE_STDOUT" +grep -Fq "restore_missing_required=0" "$PARAMETER_FILE_STDOUT" +grep -Fq "missing_required_5161=3.5" "$PARAMETER_FILE_STDOUT" +grep -Fq "missing_required_5162=0" "$PARAMETER_FILE_STDOUT" +grep -Fq "save_parameters=0" "$PARAMETER_FILE_STDOUT" +grep -Fq "saved_has_5161=1" "$PARAMETER_FILE_STDOUT" +grep -Fq "saved_has_5162=1" "$PARAMETER_FILE_STDOUT" +grep -Fq "saved_has_5221=1" "$PARAMETER_FILE_STDOUT" +grep -Fq "saved_has_5399=1" "$PARAMETER_FILE_STDOUT" +grep -Fq "saved_has_named_param=0" "$PARAMETER_FILE_STDOUT" +grep -Fq "backup_has_original_5161=1" "$PARAMETER_FILE_STDOUT" + check_fixture_output() { local fixture="$1" local expected="$2" diff --git a/wasm-port/tools/build_native_probes.sh b/wasm-port/tools/build_native_probes.sh index 576109f..746fb45 100755 --- a/wasm-port/tools/build_native_probes.sh +++ b/wasm-port/tools/build_native_probes.sh @@ -287,6 +287,11 @@ MINIMAL_SOURCES=( "$WRAP_DIR/linuxcnc_interp_minimal_harness.cpp" ) +PARAMETER_FILE_SOURCES=( + "${INTERP_CORE_SOURCES[@]}" + "$WRAP_DIR/linuxcnc_parameter_file_harness.cpp" +) + build_binary_target \ linuxcnc_ini_probe \ "$BUILD_DIR/linuxcnc_ini_probe" \ @@ -348,6 +353,29 @@ else "$BUILD_DIR/linuxcnc_interp_minimal_harness.run.stderr.log" fi +build_binary_target \ + linuxcnc_parameter_file_harness \ + "$BUILD_DIR/linuxcnc_parameter_file_harness" \ + MINIMAL_FLAGS \ + PARAMETER_FILE_SOURCES \ + MINIMAL_LINK_FLAGS \ + -lfmt + +if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_parameter_file_harness.exitcode")" == "0" ]]; then + set +e + "$BUILD_DIR/linuxcnc_parameter_file_harness" \ + >"$BUILD_DIR/linuxcnc_parameter_file_harness.run.stdout.log" \ + 2>"$BUILD_DIR/linuxcnc_parameter_file_harness.run.stderr.log" + PARAMETER_FILE_RUN_RC=$? + set -e + echo "$PARAMETER_FILE_RUN_RC" > "$BUILD_DIR/linuxcnc_parameter_file_harness.run.exitcode" +else + rm -f \ + "$BUILD_DIR/linuxcnc_parameter_file_harness.run.exitcode" \ + "$BUILD_DIR/linuxcnc_parameter_file_harness.run.stdout.log" \ + "$BUILD_DIR/linuxcnc_parameter_file_harness.run.stderr.log" +fi + build_object_target \ linuxcnc_rs274_compile_probe \ "$BUILD_DIR/linuxcnc_rs274_compile_probe.o" \