接入 task HAL Web 仿真运行时
This commit is contained in:
234
wasm-port/tests/native/probe_trt_task_hal_runtime.sh
Executable file
234
wasm-port/tests/native/probe_trt_task_hal_runtime.sh
Executable file
@@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
LINUXCNC_ROOT="${LINUXCNC_ROOT:-$ROOT_DIR/../linuxcnc}"
|
||||
MACHINE_DIR="$LINUXCNC_ROOT/configs/sim/axis/vismach/5axis/table-rotary-tilting"
|
||||
INI_FILE="$MACHINE_DIR/xyzac-trt.ini"
|
||||
PROGRAM_FILE="$MACHINE_DIR/demos/xyzac_switchkins.ngc"
|
||||
RUN_DIR="$ROOT_DIR/build/native/trt-task-hal-runtime"
|
||||
LINUXCNC_STDOUT="$RUN_DIR/linuxcnc.stdout.log"
|
||||
LINUXCNC_STDERR="$RUN_DIR/linuxcnc.stderr.log"
|
||||
LINUXCNC_PID=""
|
||||
|
||||
required_commands=(halcmd linuxcnc)
|
||||
missing_commands=()
|
||||
declare -A command_paths=()
|
||||
|
||||
cleanup() {
|
||||
if [[ -n "$LINUXCNC_PID" ]]; then
|
||||
kill -TERM "-$LINUXCNC_PID" 2>/dev/null || kill "$LINUXCNC_PID" 2>/dev/null || true
|
||||
for _ in $(seq 1 20); do
|
||||
if ! kill -0 "$LINUXCNC_PID" 2>/dev/null; then
|
||||
wait "$LINUXCNC_PID" 2>/dev/null || true
|
||||
LINUXCNC_PID=""
|
||||
return
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
kill -KILL "-$LINUXCNC_PID" 2>/dev/null || kill -KILL "$LINUXCNC_PID" 2>/dev/null || true
|
||||
wait "$LINUXCNC_PID" 2>/dev/null || true
|
||||
LINUXCNC_PID=""
|
||||
fi
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
print_kv() {
|
||||
printf '%s=%s\n' "$1" "$2"
|
||||
}
|
||||
|
||||
csv_join() {
|
||||
local IFS=,
|
||||
printf '%s' "$*"
|
||||
}
|
||||
|
||||
command_path() {
|
||||
local command_name="$1"
|
||||
local path
|
||||
path="$(command -v "$command_name" 2>/dev/null || true)"
|
||||
if [[ -n "$path" ]]; then
|
||||
printf '%s\n' "$path"
|
||||
return
|
||||
fi
|
||||
|
||||
case "$command_name" in
|
||||
linuxcnc)
|
||||
[[ -x "$LINUXCNC_ROOT/scripts/$command_name" ]] && printf '%s\n' "$LINUXCNC_ROOT/scripts/$command_name"
|
||||
;;
|
||||
halcmd)
|
||||
[[ -x "$LINUXCNC_ROOT/bin/$command_name" ]] && printf '%s\n' "$LINUXCNC_ROOT/bin/$command_name"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
existing_linuxcnc_runtime_conflicts() {
|
||||
ps -eo pid=,args= | awk '
|
||||
/linuxcncsvr -ini/ || /rtapi_app load/ {
|
||||
if ($0 !~ /awk /) {
|
||||
gsub(/^[[:space:]]+/, "", $0)
|
||||
print
|
||||
}
|
||||
}
|
||||
'
|
||||
}
|
||||
|
||||
source_ready=1
|
||||
for rel in \
|
||||
xyzac-trt.ini \
|
||||
xyzac-trt.tbl \
|
||||
xyzac-trt_cmds.hal \
|
||||
switchkins_postgui.hal \
|
||||
remap_subs/428remap.ngc \
|
||||
remap_subs/429remap.ngc \
|
||||
remap_subs/430remap.ngc \
|
||||
demos/xyzac_switchkins.ngc; do
|
||||
if [[ ! -f "$MACHINE_DIR/$rel" ]]; then
|
||||
source_ready=0
|
||||
print_kv "trt_task_hal_missing_source_${rel//[^A-Za-z0-9]/_}" "$MACHINE_DIR/$rel"
|
||||
fi
|
||||
done
|
||||
|
||||
runtime_requirements=()
|
||||
for command_name in "${required_commands[@]}"; do
|
||||
path="$(command_path "$command_name")"
|
||||
if [[ -n "$path" ]]; then
|
||||
command_paths["$command_name"]="$path"
|
||||
runtime_requirements+=("$command_name:1")
|
||||
print_kv "trt_task_hal_runtime_${command_name}_path" "$path"
|
||||
else
|
||||
runtime_requirements+=("$command_name:0")
|
||||
missing_commands+=("$command_name")
|
||||
fi
|
||||
done
|
||||
|
||||
runtime_ready=0
|
||||
if [[ "${#missing_commands[@]}" -eq 0 ]]; then
|
||||
runtime_ready=1
|
||||
fi
|
||||
|
||||
print_kv trt_task_hal_runtime_requirements "$(csv_join "${runtime_requirements[@]}")"
|
||||
if [[ "${#missing_commands[@]}" -eq 0 ]]; then
|
||||
print_kv trt_task_hal_missing_requirements "-"
|
||||
else
|
||||
print_kv trt_task_hal_missing_requirements "$(csv_join "${missing_commands[@]}")"
|
||||
fi
|
||||
print_kv trt_task_hal_source_proof_ready "$source_ready"
|
||||
print_kv trt_task_hal_runtime_ready "$runtime_ready"
|
||||
print_kv trt_task_hal_execution_enabled 0
|
||||
print_kv trt_task_hal_promotion_allowed 0
|
||||
print_kv nativeTaskReady false
|
||||
print_kv nativeHalSyncReady false
|
||||
|
||||
if [[ "$source_ready" != "1" ]]; then
|
||||
print_kv native_task_hal_probe "blocked"
|
||||
print_kv native_probe_status "blocked_missing_source"
|
||||
print_kv trt_task_hal_runtime_probe_status "blocked_missing_source"
|
||||
print_kv trt_task_hal_runtime_probe_note "missing_trt_source_requirements_keep_task_hal_blocked"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$runtime_ready" != "1" ]]; then
|
||||
print_kv native_task_hal_probe "ok"
|
||||
print_kv native_probe_status "skipped_missing_host_runtime"
|
||||
print_kv trt_task_hal_runtime_probe_status "skipped_missing_host_runtime"
|
||||
print_kv trt_task_hal_runtime_probe_note "missing_host_runtime_requirements_keep_task_hal_blocked"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${ENABLE_TRT_TASK_HAL_RUNTIME_PROBE:-0}" != "1" ]]; then
|
||||
print_kv native_task_hal_probe "ok"
|
||||
print_kv native_probe_status "ready_disabled_by_default"
|
||||
print_kv trt_task_hal_runtime_probe_status "ready_disabled_by_default"
|
||||
print_kv trt_task_hal_runtime_probe_note "set_ENABLE_TRT_TASK_HAL_RUNTIME_PROBE_1_to_run_exclusive_host_runtime_probe"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
existing_runtime_conflicts="$(existing_linuxcnc_runtime_conflicts)"
|
||||
if [[ -n "$existing_runtime_conflicts" ]]; then
|
||||
print_kv trt_task_hal_runtime_ready 0
|
||||
print_kv trt_task_hal_missing_requirements "exclusive_linuxcnc_runtime"
|
||||
print_kv trt_task_hal_existing_runtime_conflicts "$(printf '%s\n' "$existing_runtime_conflicts" | paste -sd ';' -)"
|
||||
print_kv native_task_hal_probe "blocked"
|
||||
print_kv native_probe_status "blocked_existing_linuxcnc_runtime"
|
||||
print_kv trt_task_hal_runtime_probe_status "blocked_existing_linuxcnc_runtime"
|
||||
print_kv trt_task_hal_runtime_probe_note "existing_linuxcnc_runtime_conflict_keep_task_hal_blocked"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
HALCMD_BIN="${command_paths[halcmd]}"
|
||||
LINUXCNC_BIN="${command_paths[linuxcnc]}"
|
||||
|
||||
export PATH="$LINUXCNC_ROOT/bin:$LINUXCNC_ROOT/scripts:$LINUXCNC_ROOT/tcl:$PATH"
|
||||
export LD_LIBRARY_PATH="$LINUXCNC_ROOT/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
||||
export PYTHONPATH="$LINUXCNC_ROOT/lib/python${PYTHONPATH:+:$PYTHONPATH}"
|
||||
export TCLLIBPATH="$LINUXCNC_ROOT/tcl${TCLLIBPATH:+ $TCLLIBPATH}"
|
||||
|
||||
mkdir -p "$RUN_DIR"
|
||||
|
||||
wait_for_hal_pin() {
|
||||
local pin="$1"
|
||||
local limit="${TRT_TASK_HAL_RUNTIME_WAIT_SECONDS:-30}"
|
||||
local end=$((SECONDS + limit))
|
||||
while (( SECONDS < end )); do
|
||||
if "$HALCMD_BIN" getp "$pin" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
sleep 0.25
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
read_hal_pin() {
|
||||
"$HALCMD_BIN" getp "$1" 2>/dev/null | tr -d '[:space:]'
|
||||
}
|
||||
|
||||
expect_hal_pin_exists() {
|
||||
local label="$1"
|
||||
local pin="$2"
|
||||
if "$HALCMD_BIN" getp "$pin" >/dev/null 2>&1; then
|
||||
print_kv "trt_task_hal_${label}_${pin//[^A-Za-z0-9]/_}_exists" 1
|
||||
print_kv "trt_task_hal_${label}_${pin//[^A-Za-z0-9]/_}_value" "$(read_hal_pin "$pin")"
|
||||
return 0
|
||||
fi
|
||||
print_kv "trt_task_hal_${label}_${pin//[^A-Za-z0-9]/_}_exists" 0
|
||||
return 1
|
||||
}
|
||||
|
||||
print_kv trt_task_hal_runtime_probe_ini "$INI_FILE"
|
||||
print_kv trt_task_hal_runtime_probe_program "$PROGRAM_FILE"
|
||||
print_kv trt_task_hal_runtime_probe_linuxcnc_stdout "$LINUXCNC_STDOUT"
|
||||
print_kv trt_task_hal_runtime_probe_linuxcnc_stderr "$LINUXCNC_STDERR"
|
||||
|
||||
setsid "$LINUXCNC_BIN" -r "$INI_FILE" >"$LINUXCNC_STDOUT" 2>"$LINUXCNC_STDERR" &
|
||||
LINUXCNC_PID="$!"
|
||||
|
||||
if ! wait_for_hal_pin motion.switchkins-type || ! wait_for_hal_pin motion.program-line; then
|
||||
print_kv native_task_hal_probe "failed"
|
||||
print_kv native_probe_status "failed"
|
||||
print_kv trt_task_hal_runtime_probe_status "runtime_state_probe_failed"
|
||||
print_kv trt_task_hal_runtime_probe_note "linuxcnc_started_but_required_trt_hal_pins_did_not_appear"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
probe_ok=1
|
||||
expect_hal_pin_exists startup motion.switchkins-type || probe_ok=0
|
||||
expect_hal_pin_exists startup motion.program-line || probe_ok=0
|
||||
expect_hal_pin_exists startup motion.motion-type || probe_ok=0
|
||||
expect_hal_pin_exists startup motion.in-position || probe_ok=0
|
||||
expect_hal_pin_exists startup joint.0.motor-pos-cmd || probe_ok=0
|
||||
expect_hal_pin_exists startup joint.0.motor-pos-fb || probe_ok=0
|
||||
expect_hal_pin_exists startup xyzac-trt-kins.tool-offset || true
|
||||
|
||||
if [[ "$probe_ok" == "1" ]]; then
|
||||
print_kv native_task_hal_probe "ok"
|
||||
print_kv native_probe_status "passed"
|
||||
print_kv trt_task_hal_runtime_probe_status "runtime_state_probe_passed"
|
||||
print_kv trt_task_hal_runtime_probe_note "linuxcnc_owned_trt_task_hal_startup_state_probe_passed_without_promotion"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
print_kv native_task_hal_probe "failed"
|
||||
print_kv native_probe_status "failed"
|
||||
print_kv trt_task_hal_runtime_probe_status "runtime_state_probe_failed"
|
||||
print_kv trt_task_hal_runtime_probe_note "linuxcnc_owned_trt_task_hal_startup_state_probe_failed"
|
||||
exit 1
|
||||
85
wasm-port/tests/native/verify_task_hal_phase0.sh
Executable file
85
wasm-port/tests/native/verify_task_hal_phase0.sh
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
|
||||
BUILD_DIR="$ROOT_DIR/build/task-hal"
|
||||
MANIFEST_STDOUT="$BUILD_DIR/verify_task_hal_source_manifest.stdout.log"
|
||||
PROBE_STDOUT="$BUILD_DIR/probe_trt_task_hal_runtime.stdout.log"
|
||||
|
||||
mkdir -p "$BUILD_DIR"
|
||||
|
||||
"$ROOT_DIR/tools/verify_task_hal_source_manifest.sh" >"$MANIFEST_STDOUT"
|
||||
"$ROOT_DIR/tests/native/probe_trt_task_hal_runtime.sh" >"$PROBE_STDOUT"
|
||||
|
||||
value_from() {
|
||||
local file="$1"
|
||||
local key="$2"
|
||||
awk -F= -v key="$key" '$1 == key { print substr($0, length(key) + 2); found=1 } END { if (!found) exit 1 }' "$file"
|
||||
}
|
||||
|
||||
expect_value() {
|
||||
local file="$1"
|
||||
local key="$2"
|
||||
local expected="$3"
|
||||
local actual
|
||||
actual="$(value_from "$file" "$key")"
|
||||
if [[ "$actual" != "$expected" ]]; then
|
||||
echo "$key expected $expected, got $actual" >&2
|
||||
echo "from $file" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
expect_int_gt() {
|
||||
local file="$1"
|
||||
local key="$2"
|
||||
local minimum="$3"
|
||||
local actual
|
||||
actual="$(value_from "$file" "$key")"
|
||||
if ! [[ "$actual" =~ ^[0-9]+$ ]] || (( actual <= minimum )); then
|
||||
echo "$key expected > $minimum, got $actual" >&2
|
||||
echo "from $file" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
expect_value "$MANIFEST_STDOUT" task_hal_source_manifest_status ok
|
||||
expect_value "$MANIFEST_STDOUT" task_hal_source_manifest_ready 1
|
||||
expect_value "$MANIFEST_STDOUT" task_hal_reference_source_ready 1
|
||||
expect_value "$MANIFEST_STDOUT" task_hal_missing_reference_source_count 0
|
||||
expect_int_gt "$MANIFEST_STDOUT" task_source_count 0
|
||||
expect_int_gt "$MANIFEST_STDOUT" hal_source_count 0
|
||||
expect_int_gt "$MANIFEST_STDOUT" motion_source_count 0
|
||||
expect_int_gt "$MANIFEST_STDOUT" nml_source_count 0
|
||||
expect_value "$MANIFEST_STDOUT" task_hal_runtime_promoted 0
|
||||
expect_value "$MANIFEST_STDOUT" nativeTaskReady false
|
||||
expect_value "$MANIFEST_STDOUT" nativeHalSyncReady false
|
||||
|
||||
expect_value "$PROBE_STDOUT" trt_task_hal_source_proof_ready 1
|
||||
expect_value "$PROBE_STDOUT" trt_task_hal_execution_enabled 0
|
||||
expect_value "$PROBE_STDOUT" trt_task_hal_promotion_allowed 0
|
||||
expect_value "$PROBE_STDOUT" native_task_hal_probe ok
|
||||
expect_value "$PROBE_STDOUT" nativeTaskReady false
|
||||
expect_value "$PROBE_STDOUT" nativeHalSyncReady false
|
||||
|
||||
native_probe_status="$(value_from "$PROBE_STDOUT" native_probe_status)"
|
||||
probe_status="$(value_from "$PROBE_STDOUT" trt_task_hal_runtime_probe_status)"
|
||||
case "$probe_status" in
|
||||
ready_disabled_by_default|skipped_missing_host_runtime|blocked_missing_source)
|
||||
;;
|
||||
*)
|
||||
echo "unexpected non-opt-in TRT task/HAL probe status: $probe_status" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case "$native_probe_status" in
|
||||
ready_disabled_by_default|skipped_missing_host_runtime)
|
||||
;;
|
||||
*)
|
||||
echo "unexpected non-opt-in native probe status: $native_probe_status" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "task_hal_phase0_native_probe_gate=ok"
|
||||
213
wasm-port/tests/wasm/node/verify_hal_runtime.mjs
Normal file
213
wasm-port/tests/wasm/node/verify_hal_runtime.mjs
Normal file
@@ -0,0 +1,213 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import createLinuxCncTaskHalModule from "../../../build/wasm/task-hal/linuxcnc_task_hal.js";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const rootDir = resolve(__dirname, "../../..");
|
||||
const wasmPath = resolve(rootDir, "build/wasm/task-hal/linuxcnc_task_hal.wasm");
|
||||
|
||||
const hal = await createLinuxCncTaskHalModule({
|
||||
wasmBinary: readFileSync(wasmPath),
|
||||
print() {},
|
||||
printErr(message) {
|
||||
console.error(message);
|
||||
},
|
||||
});
|
||||
|
||||
function allocCString(value) {
|
||||
const bytes = hal.lengthBytesUTF8(value) + 1;
|
||||
const ptr = hal._malloc(bytes);
|
||||
hal.stringToUTF8(value, ptr, bytes);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function withCString(value, fn) {
|
||||
const ptr = allocCString(value);
|
||||
try {
|
||||
return fn(ptr);
|
||||
} finally {
|
||||
hal._free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
function readJsonWithBuffer(call) {
|
||||
const bytes = 32768;
|
||||
const ptr = hal._malloc(bytes);
|
||||
try {
|
||||
const rc = call(ptr, bytes);
|
||||
assert.equal(rc, 0);
|
||||
return JSON.parse(hal.UTF8ToString(ptr));
|
||||
} finally {
|
||||
hal._free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
function createPin(name, type, dir = 32) {
|
||||
const ptrAddr = hal._malloc(4);
|
||||
try {
|
||||
const rc = withCString(name, (namePtr) => {
|
||||
switch (type) {
|
||||
case "bit":
|
||||
return hal._hal_pin_bit_new(namePtr, dir, ptrAddr, 1);
|
||||
case "float":
|
||||
return hal._hal_pin_float_new(namePtr, dir, ptrAddr, 1);
|
||||
case "s32":
|
||||
return hal._hal_pin_s32_new(namePtr, dir, ptrAddr, 1);
|
||||
case "u32":
|
||||
return hal._hal_pin_u32_new(namePtr, dir, ptrAddr, 1);
|
||||
default:
|
||||
throw new Error(`unsupported pin type: ${type}`);
|
||||
}
|
||||
});
|
||||
assert.equal(rc, 0, `${name} create`);
|
||||
return hal.getValue(ptrAddr, "i32");
|
||||
} finally {
|
||||
hal._free(ptrAddr);
|
||||
}
|
||||
}
|
||||
|
||||
function setPinFloat(name, value) {
|
||||
withCString(name, (namePtr) => assert.equal(hal._lchal_set_pin_float(namePtr, value), 0));
|
||||
}
|
||||
|
||||
function setPinBit(name, value) {
|
||||
withCString(name, (namePtr) => assert.equal(hal._lchal_set_pin_bit(namePtr, value ? 1 : 0), 0));
|
||||
}
|
||||
|
||||
function getPin(name) {
|
||||
return withCString(name, (namePtr) =>
|
||||
readJsonWithBuffer((outPtr, outLen) => hal._lchal_get_pin_json(namePtr, outPtr, outLen)),
|
||||
);
|
||||
}
|
||||
|
||||
function getP(name) {
|
||||
return withCString(name, (namePtr) => {
|
||||
const bytes = 128;
|
||||
const outPtr = hal._malloc(bytes);
|
||||
try {
|
||||
assert.equal(hal._hal_get_p(namePtr, outPtr, bytes), 0);
|
||||
return hal.UTF8ToString(outPtr);
|
||||
} finally {
|
||||
hal._free(outPtr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadHalFile(path, text) {
|
||||
return withCString(path, (pathPtr) =>
|
||||
withCString(text, (textPtr) => hal._lchal_load_hal_file(pathPtr, textPtr)),
|
||||
);
|
||||
}
|
||||
|
||||
assert.equal(hal._lchal_init_runtime(), 0);
|
||||
assert.notEqual(createPin("motion.analog-out-03", "float"), 0);
|
||||
assert.notEqual(createPin("probe.out", "bit"), 0);
|
||||
assert.notEqual(createPin("probe.in", "bit", 16), 0);
|
||||
assert.notEqual(createPin("motion.program-line", "s32"), 0);
|
||||
assert.notEqual(hal._hal_malloc(16), 0);
|
||||
|
||||
setPinFloat("motion.analog-out-03", 2.5);
|
||||
assert.equal(getPin("motion.analog-out-03").value, 2.5);
|
||||
assert.equal(getP("motion.analog-out-03"), "2.5");
|
||||
|
||||
const paramFloatAddr = hal._malloc(8);
|
||||
const paramS32Addr = hal._malloc(4);
|
||||
try {
|
||||
hal.setValue(paramFloatAddr, 7.25, "double");
|
||||
hal.setValue(paramS32Addr, -12, "i32");
|
||||
withCString("standalone.param-float", (namePtr) =>
|
||||
assert.equal(hal._hal_param_float_new(namePtr, 192, paramFloatAddr, 1), 0),
|
||||
);
|
||||
withCString("standalone.param-s32", (namePtr) =>
|
||||
assert.equal(hal._hal_param_s32_new(namePtr, 192, paramS32Addr, 1), 0),
|
||||
);
|
||||
assert.equal(getP("standalone.param-float"), "7.25");
|
||||
assert.equal(getP("standalone.param-s32"), "-12");
|
||||
} finally {
|
||||
hal._free(paramFloatAddr);
|
||||
hal._free(paramS32Addr);
|
||||
}
|
||||
|
||||
withCString("motion.program-line", (namePtr) => {
|
||||
const typePtr = hal._malloc(4);
|
||||
const valuePtrPtr = hal._malloc(4);
|
||||
const connectedPtr = hal._malloc(1);
|
||||
try {
|
||||
assert.equal(hal._hal_get_pin_value_by_name(namePtr, typePtr, valuePtrPtr, connectedPtr), 0);
|
||||
assert.equal(hal.getValue(typePtr, "i32"), 3);
|
||||
assert.notEqual(hal.getValue(valuePtrPtr, "i32"), 0);
|
||||
} finally {
|
||||
hal._free(typePtr);
|
||||
hal._free(valuePtrPtr);
|
||||
hal._free(connectedPtr);
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(loadHalFile("probe.hal", "net probe-signal probe.out probe.in\n"), 0);
|
||||
setPinBit("probe.out", true);
|
||||
assert.equal(getPin("probe.in").value, true);
|
||||
withCString("probe-signal", (namePtr) => {
|
||||
const typePtr = hal._malloc(4);
|
||||
const valuePtrPtr = hal._malloc(4);
|
||||
const connectedPtr = hal._malloc(1);
|
||||
try {
|
||||
assert.equal(hal._hal_get_signal_value_by_name(namePtr, typePtr, valuePtrPtr, connectedPtr), 0);
|
||||
assert.equal(hal.getValue(typePtr, "i32"), 1);
|
||||
assert.notEqual(hal.getValue(valuePtrPtr, "i32"), 0);
|
||||
} finally {
|
||||
hal._free(typePtr);
|
||||
hal._free(valuePtrPtr);
|
||||
hal._free(connectedPtr);
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(
|
||||
loadHalFile(
|
||||
"threads.hal",
|
||||
[
|
||||
"loadrt trivkins",
|
||||
"addf motion-command-handler servo-thread",
|
||||
"addf motion-controller servo-thread",
|
||||
"",
|
||||
].join("\n"),
|
||||
),
|
||||
0,
|
||||
);
|
||||
assert.equal(hal._lchal_step_threads(1000000, 2), 0);
|
||||
withCString("motion-command-handler", (functPtr) =>
|
||||
withCString("servo-thread", (threadPtr) =>
|
||||
assert.equal(hal._hal_del_funct_from_thread(functPtr, threadPtr), 0),
|
||||
),
|
||||
);
|
||||
assert.equal(hal._hal_stop_threads(), 0);
|
||||
assert.equal(hal._hal_start_threads(), 0);
|
||||
assert.equal(loadHalFile("blocked.hal", "loadusr external-user-m\n"), 2);
|
||||
|
||||
const snapshot = readJsonWithBuffer((outPtr, outLen) => hal._lchal_get_snapshot_json(outPtr, outLen));
|
||||
assert.equal(snapshot.semanticBoundary, "linuxcnc_hal_runtime_phase2_minimal");
|
||||
assert.equal(snapshot.halRuntimeReady, true);
|
||||
assert.equal(snapshot.halSyncReady, false);
|
||||
assert.equal(snapshot.nativeHalSyncReady, false);
|
||||
assert.equal(snapshot.cycle, 2);
|
||||
assert.equal(snapshot.pins["probe.in"].value, true);
|
||||
assert.equal(snapshot.signals["probe-signal"].value, true);
|
||||
assert.equal(snapshot.params["standalone.param-float"].value, 7.25);
|
||||
assert.equal(snapshot.params["standalone.param-s32"].value, -12);
|
||||
assert.equal(snapshot.threads["servo-thread"].functions.length >= 1, true);
|
||||
assert.equal(snapshot.events.includes("blocked:loadusr"), true);
|
||||
assert.equal(
|
||||
snapshot.events.includes("call:servo-thread:motion-controller"),
|
||||
true,
|
||||
);
|
||||
assert.equal(snapshot.events.includes("delf:motion-command-handler:servo-thread"), true);
|
||||
assert.equal(snapshot.events.includes("threads_stop"), true);
|
||||
|
||||
console.log("hal_runtime_registry=ok");
|
||||
console.log("hal_net_signal_propagation=ok");
|
||||
console.log("hal_thread_scheduler=ok");
|
||||
console.log("loadusr_blocked_evidence=ok");
|
||||
console.log("hal_runtime_wasm_node_smoke=ok");
|
||||
30
wasm-port/tests/wasm/node/verify_hal_runtime.sh
Executable file
30
wasm-port/tests/wasm/node/verify_hal_runtime.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
BUILD_DIR="$ROOT_DIR/build/wasm/task-hal"
|
||||
NATIVE_BUILD_DIR="$ROOT_DIR/build/native/hal-runtime"
|
||||
|
||||
if ! command -v emcc >/dev/null 2>&1 && [[ -f "$HOME/emsdk/emsdk_env.sh" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$HOME/emsdk/emsdk_env.sh" >/dev/null
|
||||
fi
|
||||
|
||||
if command -v emcc >/dev/null 2>&1; then
|
||||
if [[ "${SKIP_TASK_HAL_BUILD:-0}" != "1" ]]; then
|
||||
"$ROOT_DIR/tools/build_task_hal_wasm.sh"
|
||||
fi
|
||||
node "$ROOT_DIR/tests/wasm/node/verify_hal_runtime.mjs"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$NATIVE_BUILD_DIR" "$BUILD_DIR"
|
||||
g++ -std=c++20 \
|
||||
-I"$ROOT_DIR/runtime/core/shims" \
|
||||
-I"$ROOT_DIR/runtime/core/linuxcnc_wrap" \
|
||||
"$ROOT_DIR/runtime/core/linuxcnc_wrap/linuxcnc_hal_runtime.cpp" \
|
||||
"$ROOT_DIR/runtime/core/linuxcnc_wrap/linuxcnc_hal_runtime_probe.cpp" \
|
||||
-o "$NATIVE_BUILD_DIR/linuxcnc_hal_runtime_probe"
|
||||
|
||||
"$NATIVE_BUILD_DIR/linuxcnc_hal_runtime_probe"
|
||||
echo "hal_runtime_wasm_node_smoke=skipped_missing_emcc"
|
||||
111
wasm-port/tests/wasm/node/verify_motion_hal_sync.mjs
Normal file
111
wasm-port/tests/wasm/node/verify_motion_hal_sync.mjs
Normal file
@@ -0,0 +1,111 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import createLinuxCncTaskHalModule from "../../../build/wasm/task-hal/linuxcnc_task_hal.js";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const rootDir = resolve(__dirname, "../../..");
|
||||
const wasmPath = resolve(rootDir, "build/wasm/task-hal/linuxcnc_task_hal.wasm");
|
||||
|
||||
const runtime = await createLinuxCncTaskHalModule({
|
||||
wasmBinary: readFileSync(wasmPath),
|
||||
print() {},
|
||||
printErr(message) {
|
||||
console.error(message);
|
||||
},
|
||||
});
|
||||
|
||||
function allocCString(value) {
|
||||
const bytes = runtime.lengthBytesUTF8(value) + 1;
|
||||
const ptr = runtime._malloc(bytes);
|
||||
runtime.stringToUTF8(value, ptr, bytes);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function withCString(value, fn) {
|
||||
const ptr = allocCString(value);
|
||||
try {
|
||||
return fn(ptr);
|
||||
} finally {
|
||||
runtime._free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
function readJson(call) {
|
||||
const bytes = 65536;
|
||||
const ptr = runtime._malloc(bytes);
|
||||
try {
|
||||
const rc = call(ptr, bytes);
|
||||
assert.equal(rc, 0);
|
||||
return JSON.parse(runtime.UTF8ToString(ptr));
|
||||
} finally {
|
||||
runtime._free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
function send(command) {
|
||||
return withCString(JSON.stringify(command), (commandPtr) =>
|
||||
assert.equal(runtime._lcmot_write_command_json(commandPtr), 0),
|
||||
);
|
||||
}
|
||||
|
||||
assert.equal(runtime._lchal_init_runtime(), 0);
|
||||
assert.equal(
|
||||
withCString("xyzac-trt.ini", (pathPtr) =>
|
||||
withCString("[TRAJ]\nCOORDINATES = X Y Z A C\n", (iniPtr) =>
|
||||
runtime._lcmot_init_from_ini(pathPtr, iniPtr),
|
||||
),
|
||||
),
|
||||
0,
|
||||
);
|
||||
|
||||
send({ type: "EMC_TRAJ_LINEAR_MOVE", line: 42, x: 1, y: 2, z: -3, a: 10, c: 20, velocity: 120 });
|
||||
assert.equal(runtime._lcmot_step_servo(1000000, 1), 0);
|
||||
let status = readJson((outPtr, outLen) => runtime._lcmot_read_status_json(outPtr, outLen));
|
||||
let hal = readJson((outPtr, outLen) => runtime._lcmot_read_hal_snapshot_json(outPtr, outLen));
|
||||
|
||||
assert.equal(status.semanticBoundary, "linuxcnc_motion_runtime_phase3_minimal");
|
||||
assert.equal(status.motionRuntimeReady, true);
|
||||
assert.equal(status.nativeHalSyncReady, false);
|
||||
assert.equal(status.motion.programLine, 42);
|
||||
assert.equal(status.motion.inPosition, true);
|
||||
assert.equal(status.axis.x, 1);
|
||||
assert.equal(status.axis.z, -3);
|
||||
assert.equal(hal.pins["motion.program-line"].value, 42);
|
||||
assert.equal(hal.pins["joint.0.motor-pos-cmd"].value, 1);
|
||||
assert.equal(hal.pins["joint.0.motor-pos-fb"].value, 1);
|
||||
|
||||
send({ type: "EMCMOT_SET_AOUT", value: 1 });
|
||||
assert.equal(runtime._lcmot_step_servo(1000000, 1), 0);
|
||||
status = readJson((outPtr, outLen) => runtime._lcmot_read_status_json(outPtr, outLen));
|
||||
hal = readJson((outPtr, outLen) => runtime._lcmot_read_hal_snapshot_json(outPtr, outLen));
|
||||
assert.equal(status.motion.switchkinsType, 1);
|
||||
assert.equal(hal.pins["motion.switchkins-type"].value, 1);
|
||||
assert.equal(hal.pins["motion.analog-out-03"].value, 1);
|
||||
|
||||
send({ type: "EMC_JOG_INCR", axis: "X", distance: 0.5, velocity: 60 });
|
||||
assert.equal(runtime._lcmot_step_servo(1000000, 1), 0);
|
||||
status = readJson((outPtr, outLen) => runtime._lcmot_read_status_json(outPtr, outLen));
|
||||
hal = readJson((outPtr, outLen) => runtime._lcmot_read_hal_snapshot_json(outPtr, outLen));
|
||||
assert.equal(status.axis.x, 1.5);
|
||||
assert.equal(status.motion.teleopMode, 1);
|
||||
assert.equal(hal.pins["axis.0.pos-fb"].value, 1.5);
|
||||
|
||||
send({ type: "EMC_TRAJ_PAUSE" });
|
||||
assert.equal(runtime._lcmot_step_servo(1000000, 1), 0);
|
||||
status = readJson((outPtr, outLen) => runtime._lcmot_read_status_json(outPtr, outLen));
|
||||
assert.equal(status.motion.paused, true);
|
||||
|
||||
send({ type: "EMC_TRAJ_RESUME" });
|
||||
assert.equal(runtime._lcmot_step_servo(1000000, 1), 0);
|
||||
status = readJson((outPtr, outLen) => runtime._lcmot_read_status_json(outPtr, outLen));
|
||||
assert.equal(status.motion.paused, false);
|
||||
|
||||
console.log("motion_hal_servo_cycle=ok");
|
||||
console.log("motion_program_line_hal_sync=ok");
|
||||
console.log("switchkins_type_hal_sync=ok");
|
||||
console.log("jog_motion_status_sync=ok");
|
||||
console.log("motion_hal_sync_smoke=ok");
|
||||
21
wasm-port/tests/wasm/node/verify_motion_hal_sync.sh
Executable file
21
wasm-port/tests/wasm/node/verify_motion_hal_sync.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
|
||||
if ! command -v emcc >/dev/null 2>&1 && [[ -f "$HOME/emsdk/emsdk_env.sh" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$HOME/emsdk/emsdk_env.sh" >/dev/null
|
||||
fi
|
||||
|
||||
if ! command -v emcc >/dev/null 2>&1; then
|
||||
echo "motion_hal_sync_smoke=skipped_missing_emcc"
|
||||
echo "nativeHalSyncReady=false"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${SKIP_TASK_HAL_BUILD:-0}" != "1" ]]; then
|
||||
"$ROOT_DIR/tools/build_task_hal_wasm.sh"
|
||||
fi
|
||||
|
||||
node "$ROOT_DIR/tests/wasm/node/verify_motion_hal_sync.mjs"
|
||||
56
wasm-port/tests/wasm/node/verify_task_hal_sdk.mjs
Normal file
56
wasm-port/tests/wasm/node/verify_task_hal_sdk.mjs
Normal file
@@ -0,0 +1,56 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { createLinuxCncTaskHalSdk } from "../../../runtime/sdk/src/linuxcnc-task-hal.js";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const rootDir = resolve(__dirname, "../../..");
|
||||
const wasmPath = resolve(rootDir, "build/wasm/task-hal/linuxcnc_task_hal.wasm");
|
||||
|
||||
const sdk = await createLinuxCncTaskHalSdk({
|
||||
wasmBinary: readFileSync(wasmPath),
|
||||
print() {},
|
||||
printErr(message) {
|
||||
console.error(message);
|
||||
},
|
||||
});
|
||||
|
||||
const readiness = sdk.readiness();
|
||||
assert.equal(readiness.taskRuntimeReady, true);
|
||||
assert.equal(readiness.motionRuntimeReady, true);
|
||||
assert.equal(readiness.halRuntimeReady, true);
|
||||
assert.equal(readiness.nativeTaskReady, false);
|
||||
assert.equal(readiness.nativeHalSyncReady, false);
|
||||
|
||||
sdk.initSession({
|
||||
iniPath: "xyzac-trt.ini",
|
||||
iniText: "[TRAJ]\nCOORDINATES = X Y Z A C\n",
|
||||
});
|
||||
assert.equal(sdk.stageFile("programs/sdk-task-hal.ngc", "G0 X3 Y0 Z-1\n"), 0);
|
||||
assert.equal(sdk.openProgram("programs/sdk-task-hal.ngc"), 0);
|
||||
assert.equal(sdk.sendCommand({ type: "EMC_TASK_SET_STATE", state: "ON" }), 0);
|
||||
assert.equal(sdk.sendCommand({ type: "EMC_TASK_SET_MODE", mode: "AUTO" }), 0);
|
||||
assert.equal(sdk.sendCommand({ type: "EMC_TASK_PLAN_RUN", line: 0 }), 0);
|
||||
assert.equal(sdk.runCycles({ taskCycles: 1 }), 0);
|
||||
|
||||
let status = sdk.readStatus();
|
||||
assert.equal(status.semanticBoundary, "linuxcnc_task_motion_hal_wasm_phase4_minimal");
|
||||
assert.equal(status.taskRuntimeReady, true);
|
||||
assert.equal(status.motionStatus.motion.programLine, 1);
|
||||
assert.equal(status.motionStatus.axis.x, 3);
|
||||
assert.equal(status.halSnapshot.pins["motion.program-line"].value, 1);
|
||||
|
||||
assert.equal(sdk.sendCommand({ type: "EMC_TASK_PLAN_EXECUTE", mdi: "M429" }), 0);
|
||||
assert.equal(sdk.runCycles({ taskCycles: 1 }), 0);
|
||||
status = sdk.readStatus();
|
||||
assert.equal(status.motionStatus.motion.switchkinsType, 0);
|
||||
|
||||
const events = sdk.readEvents().events;
|
||||
assert.equal(events.includes("task_plan_run"), true);
|
||||
assert.equal(events.includes("task_mdi_switchkins:M429"), true);
|
||||
|
||||
console.log("linuxcnc_task_hal_sdk=ok");
|
||||
console.log("task_hal_sdk_status_snapshot=ok");
|
||||
22
wasm-port/tests/wasm/node/verify_task_hal_sdk.sh
Executable file
22
wasm-port/tests/wasm/node/verify_task_hal_sdk.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
|
||||
if ! command -v emcc >/dev/null 2>&1 && [[ -f "$HOME/emsdk/emsdk_env.sh" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$HOME/emsdk/emsdk_env.sh" >/dev/null
|
||||
fi
|
||||
|
||||
if ! command -v emcc >/dev/null 2>&1; then
|
||||
echo "linuxcnc_task_hal_sdk=skipped_missing_emcc"
|
||||
echo "nativeTaskReady=false"
|
||||
echo "nativeHalSyncReady=false"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${SKIP_TASK_HAL_BUILD:-0}" != "1" ]]; then
|
||||
"$ROOT_DIR/tools/build_task_hal_wasm.sh"
|
||||
fi
|
||||
|
||||
node "$ROOT_DIR/tests/wasm/node/verify_task_hal_sdk.mjs"
|
||||
148
wasm-port/tests/wasm/node/verify_task_hal_wasm.mjs
Normal file
148
wasm-port/tests/wasm/node/verify_task_hal_wasm.mjs
Normal file
@@ -0,0 +1,148 @@
|
||||
import { readFileSync } from "node:fs";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { dirname, resolve } from "node:path";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import createLinuxCncTaskHalModule from "../../../build/wasm/task-hal/linuxcnc_task_hal.js";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
const rootDir = resolve(__dirname, "../../..");
|
||||
const wasmPath = resolve(rootDir, "build/wasm/task-hal/linuxcnc_task_hal.wasm");
|
||||
|
||||
const runtime = await createLinuxCncTaskHalModule({
|
||||
wasmBinary: readFileSync(wasmPath),
|
||||
print() {},
|
||||
printErr(message) {
|
||||
console.error(message);
|
||||
},
|
||||
});
|
||||
|
||||
function allocCString(value) {
|
||||
const bytes = runtime.lengthBytesUTF8(value) + 1;
|
||||
const ptr = runtime._malloc(bytes);
|
||||
runtime.stringToUTF8(value, ptr, bytes);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
function withCString(value, fn) {
|
||||
const ptr = allocCString(value);
|
||||
try {
|
||||
return fn(ptr);
|
||||
} finally {
|
||||
runtime._free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
function readJson(call) {
|
||||
const bytes = 131072;
|
||||
const ptr = runtime._malloc(bytes);
|
||||
try {
|
||||
const rc = call(ptr, bytes);
|
||||
assert.equal(rc, 0);
|
||||
return JSON.parse(runtime.UTF8ToString(ptr));
|
||||
} finally {
|
||||
runtime._free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
function send(command) {
|
||||
return withCString(JSON.stringify(command), (commandPtr) =>
|
||||
assert.equal(runtime._lctask_send_command_json(commandPtr), 0, command.type),
|
||||
);
|
||||
}
|
||||
|
||||
function status() {
|
||||
return readJson((outPtr, outLen) => runtime._lctask_read_status_json(outPtr, outLen));
|
||||
}
|
||||
|
||||
function events() {
|
||||
return readJson((outPtr, outLen) => runtime._lctask_read_events_json(outPtr, outLen)).events;
|
||||
}
|
||||
|
||||
const session = {
|
||||
iniPath: "xyzac-trt.ini",
|
||||
iniText: "[TRAJ]\nCOORDINATES = X Y Z A C\n",
|
||||
};
|
||||
|
||||
assert.equal(
|
||||
withCString(JSON.stringify(session), (sessionPtr) => runtime._lctask_init_session(sessionPtr)),
|
||||
0,
|
||||
);
|
||||
|
||||
const program = ["G0 X1 Y2 Z-3 A10 C20", "G1 X2 Y3 Z-4 A11 C21"].join("\n");
|
||||
assert.equal(
|
||||
withCString("programs/task-hal-smoke.ngc", (pathPtr) =>
|
||||
withCString(program, (textPtr) => runtime._lctask_stage_file(pathPtr, textPtr)),
|
||||
),
|
||||
0,
|
||||
);
|
||||
assert.equal(
|
||||
withCString("programs/task-hal-smoke.ngc", (pathPtr) => runtime._lctask_open_program(pathPtr)),
|
||||
0,
|
||||
);
|
||||
|
||||
send({ type: "EMC_TASK_SET_STATE", state: "ON" });
|
||||
send({ type: "EMC_TASK_SET_MODE", mode: "AUTO" });
|
||||
send({ type: "EMC_TASK_PLAN_RUN", line: 0 });
|
||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 2), 0);
|
||||
|
||||
let snapshot = status();
|
||||
assert.equal(snapshot.semanticBoundary, "linuxcnc_task_motion_hal_wasm_phase4_minimal");
|
||||
assert.equal(snapshot.taskRuntimeReady, true);
|
||||
assert.equal(snapshot.taskStatusFromLinuxCncRuntime, true);
|
||||
assert.equal(snapshot.taskCommandsDriveMotionRuntime, true);
|
||||
assert.equal(snapshot.nativeTaskReady, false);
|
||||
assert.equal(snapshot.nativeHalSyncReady, false);
|
||||
assert.equal(snapshot.task.state, "ON");
|
||||
assert.equal(snapshot.task.mode, "AUTO");
|
||||
assert.equal(snapshot.task.openedLineCount, 2);
|
||||
assert.equal(snapshot.task.nextProgramLine, 2);
|
||||
assert.equal(snapshot.motionStatus.motion.programLine, 2);
|
||||
assert.equal(snapshot.motionStatus.axis.x, 2);
|
||||
assert.equal(snapshot.motionStatus.axis.z, -4);
|
||||
assert.equal(snapshot.halSnapshot.pins["motion.program-line"].value, 2);
|
||||
assert.equal(snapshot.halSnapshot.pins["joint.0.motor-pos-cmd"].value, 2);
|
||||
|
||||
send({ type: "EMC_TASK_PLAN_PAUSE" });
|
||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||
snapshot = status();
|
||||
assert.equal(snapshot.task.interpState, "PAUSED");
|
||||
assert.equal(snapshot.motionStatus.motion.paused, true);
|
||||
|
||||
send({ type: "EMC_TASK_PLAN_RESUME" });
|
||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||
snapshot = status();
|
||||
assert.equal(snapshot.motionStatus.motion.paused, false);
|
||||
|
||||
send({ type: "EMC_TASK_PLAN_EXECUTE", mdi: "M428" });
|
||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||
snapshot = status();
|
||||
assert.equal(snapshot.motionStatus.motion.switchkinsType, 1);
|
||||
assert.equal(snapshot.halSnapshot.pins["motion.switchkins-type"].value, 1);
|
||||
|
||||
send({ type: "EMC_JOG_INCR", axis: "X", distance: 0.25, velocity: 60 });
|
||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||
snapshot = status();
|
||||
assert.equal(snapshot.motionStatus.axis.x, 2.25);
|
||||
assert.equal(snapshot.motionStatus.motion.teleopMode, 1);
|
||||
|
||||
send({ type: "EMC_TASK_ABORT" });
|
||||
assert.equal(runtime._lctask_run_cycles(10000000, 1000000, 1), 0);
|
||||
snapshot = status();
|
||||
assert.equal(snapshot.task.execState, "DONE");
|
||||
assert.equal(snapshot.motionStatus.motion.aborted, true);
|
||||
|
||||
const eventLog = events();
|
||||
assert.equal(eventLog.includes("task_session_motion_init"), true);
|
||||
assert.equal(eventLog.includes("task_plan_run"), true);
|
||||
assert.equal(eventLog.includes("task_plan_pause"), true);
|
||||
assert.equal(eventLog.includes("task_plan_resume"), true);
|
||||
assert.equal(eventLog.includes("task_mdi_switchkins:M428"), true);
|
||||
assert.equal(eventLog.includes("task_jog_incr"), true);
|
||||
assert.equal(eventLog.includes("task_abort"), true);
|
||||
|
||||
console.log("linuxcnc_task_runtime_smoke=ok");
|
||||
console.log("task_status_from_linuxcnc_runtime=ok");
|
||||
console.log("task_commands_drive_motion_runtime=ok");
|
||||
console.log("mdi_jog_task_motion_hal_sync=ok");
|
||||
22
wasm-port/tests/wasm/node/verify_task_hal_wasm.sh
Executable file
22
wasm-port/tests/wasm/node/verify_task_hal_wasm.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
|
||||
|
||||
if ! command -v emcc >/dev/null 2>&1 && [[ -f "$HOME/emsdk/emsdk_env.sh" ]]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$HOME/emsdk/emsdk_env.sh" >/dev/null
|
||||
fi
|
||||
|
||||
if ! command -v emcc >/dev/null 2>&1; then
|
||||
echo "linuxcnc_task_runtime_smoke=skipped_missing_emcc"
|
||||
echo "nativeTaskReady=false"
|
||||
echo "nativeHalSyncReady=false"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${SKIP_TASK_HAL_BUILD:-0}" != "1" ]]; then
|
||||
"$ROOT_DIR/tools/build_task_hal_wasm.sh"
|
||||
fi
|
||||
|
||||
node "$ROOT_DIR/tests/wasm/node/verify_task_hal_wasm.mjs"
|
||||
Reference in New Issue
Block a user