Add interactive menu regression

This commit is contained in:
2026-04-17 11:09:25 +08:00
parent b5ae4a5668
commit 7b854c7a96
8 changed files with 114 additions and 18 deletions

View File

@@ -24,6 +24,7 @@ run_test() {
run_test "${ROOT_DIR}/tests/test_common.sh"
run_test "${ROOT_DIR}/tests/test_cli.sh"
run_test "${ROOT_DIR}/tests/test_interactive.sh"
run_test "${ROOT_DIR}/tests/test_storage.sh"
run_test "${ROOT_DIR}/tests/test_env_check.sh"
run_test "${ROOT_DIR}/tests/test_rules_unit.sh"

View File

@@ -15,6 +15,17 @@ status_of() {
printf '%s\n' "${rc}"
}
prompt_tmp=$(mktemp)
trap 'rm -f "${prompt_tmp}"' EXIT
export IPF_TEST_INPUTS=$'first\nsecond\n'
prompt_input 'first prompt' '' >"${prompt_tmp}"
assert_eq 'first' "$(cat "${prompt_tmp}")" 'prompt_input should consume the first queued test input'
prompt_input 'second prompt' '' >"${prompt_tmp}"
assert_eq 'second' "$(cat "${prompt_tmp}")" 'prompt_input should consume subsequent queued test inputs'
assert_eq '' "${IPF_TEST_INPUTS}" 'prompt_input should drain queued test inputs in the current shell'
unset IPF_TEST_INPUTS
assert_status 0 "$(status_of validate_ipv4 '0.0.0.0')" 'validate_ipv4 should accept 0.0.0.0'
assert_status 0 "$(status_of validate_ipv4 '192.168.1.1')" 'validate_ipv4 should accept private address'
assert_status 0 "$(status_of validate_ipv4 '255.255.255.255')" 'validate_ipv4 should accept broadcast'

62
tests/test_interactive.sh Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
# shellcheck source=tests/lib/assert.sh
source "${ROOT_DIR}/tests/lib/assert.sh"
maybe_enter_namespace() {
if (( EUID == 0 )); then
return 0
fi
if [[ ${IPF_IN_NAMESPACE:-0} == 1 ]]; then
return 0
fi
if command -v unshare >/dev/null 2>&1 && unshare -Urn true >/dev/null 2>&1; then
exec unshare -Urn env IPF_IN_NAMESPACE=1 bash "$0"
fi
printf 'SKIP: 交互测试需要 root 或可用的 unshare。\n'
exit 0
}
maybe_enter_namespace
TMP_DIR=$(mktemp -d)
trap 'rm -rf "${TMP_DIR}"' EXIT
export IPF_STORAGE_DIR="${TMP_DIR}/storage"
export IPF_STORAGE_DB="${IPF_STORAGE_DIR}/rules.db"
export IPF_LOCK_FILE="${IPF_STORAGE_DIR}/.lock"
export IPTABLES_MOCK_DIR="${TMP_DIR}/iptables-mock"
export IPTABLES_MOCK_LOG="${TMP_DIR}/iptables.log"
export IPTABLES_BIN="${ROOT_DIR}/tests/mocks/iptables"
export IP6TABLES_BIN="${ROOT_DIR}/tests/mocks/ip6tables"
export IPTABLES_SAVE_BIN="${ROOT_DIR}/tests/mocks/iptables-save"
export IP6TABLES_SAVE_BIN="${ROOT_DIR}/tests/mocks/ip6tables-save"
export NETFILTER_PERSISTENT_BIN="${ROOT_DIR}/tests/mocks/persist-mock.sh"
export PERSIST_MOCK_LOG="${TMP_DIR}/persist.log"
export IPF_SKIP_ENV_CHECK=1
export IPF_FORCE_PLAIN_UI=1
export IPF_TEST_INPUTS=$'4\n2\n1\n8080\n1\n127.0.0.1\n80\ninteractive web\ny\n5\n1\n3\n1\ny\n0\n'
output=$("${ROOT_DIR}/iptables-forward.sh" 2>&1)
assert_contains "${output}" '== 环境状态 ==' 'interactive flow should open environment status view'
assert_contains "${output}" '规则总数: 0' 'environment status should show empty rule count before adding'
assert_contains "${output}" '== 添加新的转发规则 ==' 'interactive flow should enter add screen'
assert_contains "${output}" '描述: interactive web' 'interactive add summary should echo description'
assert_contains "${output}" '规则已保存到磁盘。' 'interactive flow should exercise menu save action'
assert_contains "${output}" 'interactive web' 'interactive list/delete flow should display the created description'
assert_contains "${output}" '规则已添加UUID=' 'interactive flow should add one managed rule'
assert_contains "${output}" '已退出。' 'interactive flow should return cleanly from main menu'
assert_eq '0' "$(wc -l < "${IPF_STORAGE_DB}")" 'interactive add/delete flow should leave storage empty'
assert_eq '0' "$(wc -l < "${IPTABLES_MOCK_DIR}/state.v4")" 'interactive add/delete flow should leave runtime mock state empty'
assert_eq '3' "$(grep -Ec ' -A ' "${IPTABLES_MOCK_LOG}")" 'interactive add flow should emit three IPv4 add commands'
assert_eq '3' "$(grep -Ec ' -D ' "${IPTABLES_MOCK_LOG}")" 'interactive delete should emit three delete commands'
assert_eq '3' "$(grep -Ec 'persist-mock\.sh save' "${PERSIST_MOCK_LOG}")" 'interactive add/menu-save/delete flow should persist three times'
pass 'test_interactive.sh'