From 20459525f3623388fea31049b5c6c7239042e3c1 Mon Sep 17 00:00:00 2001 From: Amir Husayn Panahifar Date: Thu, 15 Oct 2026 14:29:19 +0330 Subject: [PATCH] test: add end-to-end integration script --- scripts/integration-test.sh | 96 +++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100755 scripts/integration-test.sh diff --git a/scripts/integration-test.sh b/scripts/integration-test.sh new file mode 100755 index 0000000..26cf242 --- /dev/null +++ b/scripts/integration-test.sh @@ -0,0 +1,96 @@ +#!/usr/bin/env bash +# +# prx integration test. +# +# Exercises the real nftables and policy-routing layer on the local host: +# on -> assert rules exist -> on again (idempotent) -> off -> assert clean. +# +# The proxy engine is skipped (--skip-engine) so this does not require sing-box. +# Run it with root, e.g.: +# +# sudo -E PRX_BIN="$PWD/bin/prx" ./scripts/integration-test.sh +# +set -euo pipefail + +BIN="${PRX_BIN:-$(pwd)/bin/prx}" + +if [[ ! -x "$BIN" ]]; then + echo "prx binary not found at $BIN (build it first: make build)" >&2 + exit 1 +fi +if [[ "${EUID}" -ne 0 ]]; then + echo "this test needs root; re-run with sudo -E $0" >&2 + exit 1 +fi + +TMP="$(mktemp -d)" +CONFIG="$TMP/config.json" +STATE="$TMP/state.json" + +cat >"$CONFIG" </dev/null 2>&1 || true + rm -rf "$TMP" +} +trap cleanup EXIT + +pass() { echo " ok: $1"; } +fail() { echo " FAIL: $1" >&2; exit 1; } + +rule_count() { + ip rule show | grep -c "fwmark 0x100" || true +} + +echo "--- enabling (skip engine) ---" +"${PRX[@]}" on --skip-engine + +echo "--- assertions after on ---" +nft list table inet prx >/dev/null 2>&1 || fail "nftables table inet prx missing" +pass "nftables table inet prx present" + +ip rule show | grep -q "fwmark 0x100 lookup 100" || fail "policy rule missing" +pass "policy rule present" + +ip route show table 100 | grep -q "^default via" || fail "table 100 has no default route" +pass "table 100 default route present" + +[[ "$(rule_count)" -eq 1 ]] || fail "expected exactly one mark rule, got $(rule_count)" +pass "exactly one mark rule" + +echo "--- enabling again (idempotency) ---" +"${PRX[@]}" on --skip-engine +[[ "$(rule_count)" -eq 1 ]] || fail "duplicate rule after second on ($(rule_count))" +pass "no duplicate rule after second on" + +nft list table inet prx | grep -c "meta mark set" >/dev/null || fail "nft rules missing" +pass "nft rules intact after re-apply" + +echo "--- status ---" +"${PRX[@]}" status + +echo "--- disabling ---" +"${PRX[@]}" off + +echo "--- assertions after off ---" +if nft list table inet prx >/dev/null 2>&1; then + fail "nftables table inet prx still present after off" +fi +pass "nftables table removed" + +[[ "$(rule_count)" -eq 0 ]] || fail "policy rule still present after off" +pass "policy rule removed" + +echo "--- disabling again (idempotency) ---" +"${PRX[@]}" off +pass "second off succeeded" + +echo +echo "ALL INTEGRATION CHECKS PASSED"