mirror of
https://github.com/kuhyx/testsAndMisc.git
synced 2026-11-11 20:34:02 +01:00
First phone_focus_mode split, so it sets the pattern. The nine iptables and tethering-offload functions move to a SIBLING file, not a lib/ member: deploy.sh copies a hardcoded per-file list into REMOTE_DIR and never deploys lib/, so anything sourced on the phone has to sit beside the entry script. deploy.sh has two hardcoded lists, not one - an adb push into the staging dir and an adb_root cp out of it. Both were updated; missing the push would have left the copy pointing at a file that was never staged. The test harness copies only the entry script into its scratch dir, so it was taught to copy the sibling too. That is the same coupling as the phone deployment, in a form that can actually be run - and running it is the evidence: 17 passed, 0 failed, identical to the pre-split baseline, with the daemon sourcing the new sibling exactly as it will on the device. This script is #!/system/bin/sh with no `set -e`, so the extractor refused to guess an anchor rather than placing the source line somewhere wrong. It went after the existing config.sh source by hand. All 20 functions verbatim. Not verified on the phone - the next deploy is where that gets confirmed. Over-cap files 25 -> 24. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011w2Pj4Ek3ZNMQVYcFHgXDY
139 lines
5.4 KiB
Bash
Executable File
139 lines
5.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Regression test for tether_enforcer.sh.
|
|
#
|
|
# The enforcer ends in `main "$@"` (an infinite loop), so — like a real deploy —
|
|
# we run it as a subprocess with the Android tools it calls (settings, iptables,
|
|
# ip6tables, cmd, getprop) replaced by stubs on PATH, and drive it through the
|
|
# full gate + apply/revert state machine, asserting observable state each step.
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
SRC="$SCRIPT_DIR/../../tether_enforcer.sh"
|
|
|
|
RUN="$(mktemp -d)"
|
|
cleanup() {
|
|
if [ -n "${PID:-}" ]; then
|
|
kill "$PID" 2>/dev/null || true
|
|
wait "$PID" 2>/dev/null || true # let its TERM handler finish before rm
|
|
fi
|
|
rm -rf "$RUN"
|
|
}
|
|
trap cleanup EXIT
|
|
mkdir -p "$RUN/bin" "$RUN/state" "$RUN/ipt" "$RUN/settings" "$RUN/calls" "$RUN/app"
|
|
STATE="$RUN/state"
|
|
|
|
# --- fake config.sh in the daemon's own dir (it sources "$SCRIPT_DIR/config.sh") ---
|
|
cp "$SRC" "$RUN/app/tether_enforcer.sh"
|
|
# tether_enforcer sources this sibling; the phone gets it from deploy.sh's
|
|
# copy list, and this harness has to mirror that or the daemon dies on source.
|
|
cp "$(dirname "$SRC")/tether_iptables.sh" "$RUN/app/tether_iptables.sh"
|
|
cat >"$RUN/app/config.sh" <<EOF
|
|
export STATE_DIR="$STATE"
|
|
export MODE_FILE="$STATE/current_mode.txt"
|
|
export TETHER_ENFORCER_ENABLED=1
|
|
export TETHER_CHECK_INTERVAL=1
|
|
export TETHER_LOG="$STATE/tether_enforcer.log"
|
|
export TETHER_ENFORCER_STATE="$STATE/tether_applied"
|
|
export TETHER_OFFLOAD_KEY="tether_offload_disabled"
|
|
export TETHER_OFFLOAD_SNAP="$STATE/tether_offload.snap"
|
|
export TETHER_IPT_CHAIN="FOCUS_TETHER_BLOCK"
|
|
export TETHER_STOP_SOFTAP_ENABLED=1
|
|
export TETHER_OVERRIDE_FILE="$STATE/tether_override"
|
|
export TETHER_FORCE_FILE="$STATE/tether_force_on"
|
|
EOF
|
|
|
|
# --- stubs ---
|
|
cat >"$RUN/bin/settings" <<EOF
|
|
#!/usr/bin/env bash
|
|
db="$RUN/settings/tether_offload_disabled"
|
|
echo "settings \$*" >> "$RUN/calls/settings.log"
|
|
case "\$1 \$2" in
|
|
"get global") [ -f "\$db" ] && cat "\$db" || echo "null" ;;
|
|
"put global") printf '%s' "\$4" > "\$db" ;;
|
|
"delete global") rm -f "\$db" ;;
|
|
esac
|
|
exit 0
|
|
EOF
|
|
# iptables/ip6tables: minimal chain-state model so chain_intact converges.
|
|
cat >"$RUN/bin/iptables" <<EOF
|
|
#!/usr/bin/env bash
|
|
bin="\$(basename "\$0")"; s="$RUN/ipt/\$bin"; mkdir -p "\$s"
|
|
[ "\$1" = "-w" ] && shift 2
|
|
case "\$1" in
|
|
-L) [ -f "\$s/exists" ] ;;
|
|
-N) touch "\$s/exists"; : > "\$s/rules" ;;
|
|
-C) [ -f "\$s/jump" ] ;;
|
|
-D) if [ -f "\$s/jump" ]; then rm -f "\$s/jump"; exit 0; else exit 1; fi ;;
|
|
-I) touch "\$s/jump" ;;
|
|
-A) echo "-A rule" >> "\$s/rules" ;;
|
|
-F) : > "\$s/rules" ;;
|
|
-S) cat "\$s/rules" 2>/dev/null ;;
|
|
-X) rm -f "\$s/exists" "\$s/rules" "\$s/jump" ;;
|
|
esac
|
|
exit \$?
|
|
EOF
|
|
cp "$RUN/bin/iptables" "$RUN/bin/ip6tables"
|
|
printf '#!/usr/bin/env bash\necho "cmd $*" >> "%s/calls/cmd.log"\nexit 0\n' "$RUN" >"$RUN/bin/cmd"
|
|
printf '#!/usr/bin/env bash\necho 13\n' >"$RUN/bin/getprop"
|
|
chmod +x "$RUN/bin/"*
|
|
export PATH="$RUN/bin:$PATH"
|
|
|
|
PASS=0
|
|
FAIL=0
|
|
ok() {
|
|
PASS=$((PASS + 1))
|
|
printf ' OK: %s\n' "$1"
|
|
}
|
|
no() {
|
|
FAIL=$((FAIL + 1))
|
|
printf ' FAIL: %s\n' "$1"
|
|
}
|
|
applied() { [ -f "$STATE/tether_applied" ]; }
|
|
offload() { cat "$RUN/settings/tether_offload_disabled" 2>/dev/null || echo "<unset>"; }
|
|
v4jump() { [ -f "$RUN/ipt/iptables/jump" ]; }
|
|
v6jump() { [ -f "$RUN/ipt/ip6tables/jump" ]; }
|
|
v4rules() { grep -c '^-A' "$RUN/ipt/iptables/rules" 2>/dev/null || echo 0; }
|
|
softap() { grep -c 'stop-softap' "$RUN/calls/cmd.log" 2>/dev/null || echo 0; }
|
|
|
|
sh "$RUN/app/tether_enforcer.sh" &
|
|
PID=$!
|
|
sleep 2
|
|
|
|
# [A] Away from home -> block OFF
|
|
if applied; then no "A: applied while away"; else ok "A: not applied while away"; fi
|
|
if [ "$(offload)" = "<unset>" ]; then ok "A: offload untouched away"; else no "A: offload changed away"; fi
|
|
if v4jump; then no "A: v4 jump while away"; else ok "A: no v4 jump while away"; fi
|
|
|
|
# [B] force-on -> block ENGAGES (all three levers)
|
|
touch "$STATE/tether_force_on"
|
|
sleep 3
|
|
if applied; then ok "B: applied on force"; else no "B: not applied on force"; fi
|
|
if [ "$(offload)" = "1" ]; then ok "B: offload disabled"; else no "B: offload=$(offload)"; fi
|
|
if v4jump; then ok "B: v4 FORWARD jump pinned"; else no "B: no v4 jump"; fi
|
|
if v6jump; then ok "B: v6 FORWARD jump pinned"; else no "B: no v6 jump"; fi
|
|
if [ "$(v4rules)" = "1" ]; then ok "B: single REJECT rule (no rebuild loop)"; else no "B: v4 rules=$(v4rules)"; fi
|
|
if [ "$(softap)" -ge 1 ]; then ok "B: stop-softap invoked"; else no "B: softap not stopped"; fi
|
|
if [ "$(cat "$STATE/tether_offload.snap" 2>/dev/null)" = "null" ]; then ok "B: offload snapshot captured"; else no "B: bad snapshot"; fi
|
|
|
|
# [C] clear force -> block REVERTS
|
|
rm -f "$STATE/tether_force_on"
|
|
sleep 3
|
|
if applied; then no "C: still applied"; else ok "C: reverted on force-clear"; fi
|
|
if [ "$(offload)" = "<unset>" ]; then ok "C: offload restored"; else no "C: offload=$(offload)"; fi
|
|
if v4jump; then no "C: v4 jump remains"; else ok "C: v4 chain torn down"; fi
|
|
|
|
# [D] current_mode=focus -> ENGAGES via home gate
|
|
echo focus >"$STATE/current_mode.txt"
|
|
sleep 3
|
|
if applied; then ok "D: applied at home (focus)"; else no "D: not applied at home"; fi
|
|
if v4jump; then ok "D: v4 jump pinned at home"; else no "D: no v4 jump at home"; fi
|
|
|
|
# [E] override -> SUSPENDS even at home
|
|
touch "$STATE/tether_override"
|
|
sleep 3
|
|
if applied; then no "E: applied despite override"; else ok "E: suspended by override"; fi
|
|
if v4jump; then no "E: v4 jump despite override"; else ok "E: torn down by override"; fi
|
|
|
|
printf '\n%d passed, %d failed\n' "$PASS" "$FAIL"
|
|
[ "$FAIL" -eq 0 ]
|