Files
IPTables-Management/tests/test_env_check.sh
ahdoawhfo ec1a37d18f Fix env_check_apply_fixes under partial fix needs
The function used a chain of `(( NEED_X == 1 )) && { ... }` statements.
When the last flag is 0 the trailing arithmetic evaluates to false and
bash returns 1 from the function. Under the main script's `set -e` that
propagates up to bootstrap which exits with the misleading "line 60"
ERR trap right after the installer announces it is going to create the
state directory.

Rewrite the body as plain `if` blocks and return 0 explicitly. Add two
regression assertions that exercise the "only some flags set" and
"nothing to do" paths so the class of bug is caught in CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 14:11:53 +08:00

145 lines
4.2 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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"
status_of() {
set +e
"$@" >/dev/null 2>&1
local rc=$?
set -e
printf '%s\n' "${rc}"
}
TMP_DIR=$(mktemp -d)
trap 'rm -rf "${TMP_DIR}"' EXIT
BIN_DIR="${TMP_DIR}/bin"
mkdir -p "${BIN_DIR}"
IPTABLES_PATH="${BIN_DIR}/iptables"
IP6TABLES_PATH="${BIN_DIR}/ip6tables"
PERSIST_PATH="${BIN_DIR}/netfilter-persistent"
DPKG_PATH="${BIN_DIR}/dpkg"
SYSCTL_PATH="${BIN_DIR}/sysctl"
SYSTEMCTL_PATH="${BIN_DIR}/systemctl"
DEBCONF_PATH="${BIN_DIR}/debconf-set-selections"
APT_PATH="${BIN_DIR}/apt-get"
cat >"${DPKG_PATH}" <<'MOCK'
#!/usr/bin/env bash
set -euo pipefail
exit 1
MOCK
cat >"${SYSCTL_PATH}" <<MOCK
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' "\$*" >>"${TMP_DIR}/sysctl.log"
printf '1\n' >"${TMP_DIR}/ipv4_forward"
printf '1\n' >"${TMP_DIR}/ipv6_forward"
MOCK
cat >"${SYSTEMCTL_PATH}" <<'MOCK'
#!/usr/bin/env bash
set -euo pipefail
exit 1
MOCK
cat >"${DEBCONF_PATH}" <<'MOCK'
#!/usr/bin/env bash
set -euo pipefail
cat >/dev/null
MOCK
cat >"${APT_PATH}" <<MOCK
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' "\$*" >>"${TMP_DIR}/apt.log"
MOCK
chmod +x "${DPKG_PATH}" "${SYSCTL_PATH}" "${SYSTEMCTL_PATH}" "${DEBCONF_PATH}" "${APT_PATH}"
export IPF_STORAGE_DIR="${TMP_DIR}/storage"
export IPF_SYSCTL_FILE="${TMP_DIR}/99-iptables-forward.conf"
export IPF_IPV4_FORWARD_FILE="${TMP_DIR}/ipv4_forward"
export IPF_IPV6_FORWARD_FILE="${TMP_DIR}/ipv6_forward"
export IPF_CHECK_IPTABLES_CMD="${BIN_DIR}/missing-iptables"
export IPF_CHECK_IP6TABLES_CMD="${BIN_DIR}/missing-ip6tables"
export IPF_CHECK_PERSIST_CMD="${BIN_DIR}/missing-persist"
export DPKG_BIN="${DPKG_PATH}"
export SYSCTL_BIN="${SYSCTL_PATH}"
export SYSTEMCTL_BIN="${SYSTEMCTL_PATH}"
export DEBCONF_SET_SELECTIONS_BIN="${DEBCONF_PATH}"
export APT_GET_BIN="${APT_PATH}"
echo 0 >"${IPF_IPV4_FORWARD_FILE}"
echo 0 >"${IPF_IPV6_FORWARD_FILE}"
# shellcheck source=lib/common.sh
source "${ROOT_DIR}/lib/common.sh"
# shellcheck source=lib/env_check.sh
source "${ROOT_DIR}/lib/env_check.sh"
env_check_collect_issues
assert_eq '6' "${#ENV_CHECK_ISSUES[@]}" 'env_check_collect_issues should capture missing binaries, persistence, forwarding and storage'
cat >"${IPTABLES_PATH}" <<'MOCK'
#!/usr/bin/env bash
set -euo pipefail
exit 0
MOCK
cat >"${IP6TABLES_PATH}" <<'MOCK'
#!/usr/bin/env bash
set -euo pipefail
exit 0
MOCK
cat >"${PERSIST_PATH}" <<'MOCK'
#!/usr/bin/env bash
set -euo pipefail
exit 0
MOCK
cat >"${DPKG_PATH}" <<'MOCK'
#!/usr/bin/env bash
set -euo pipefail
exit 0
MOCK
chmod +x "${IPTABLES_PATH}" "${IP6TABLES_PATH}" "${PERSIST_PATH}" "${DPKG_PATH}"
mkdir -p "${IPF_STORAGE_DIR}"
export IPF_CHECK_IPTABLES_CMD="${IPTABLES_PATH}"
export IPF_CHECK_IP6TABLES_CMD="${IP6TABLES_PATH}"
export IPF_CHECK_PERSIST_CMD="${PERSIST_PATH}"
export IPF_ASSUME_YES=1
env_check_all
assert_file_contains "${IPF_SYSCTL_FILE}" 'net.ipv4.ip_forward=1' 'env_check_all should write IPv4 forwarding setting'
assert_file_contains "${IPF_SYSCTL_FILE}" 'net.ipv6.conf.all.forwarding=1' 'env_check_all should write IPv6 forwarding setting'
assert_file_contains "${TMP_DIR}/sysctl.log" '--system' 'env_check_all should apply sysctl settings'
export IPF_CHECK_IPTABLES_CMD="${BIN_DIR}/missing-iptables-again"
export IPF_CHECK_IP6TABLES_CMD="${BIN_DIR}/missing-ip6tables-again"
export IPF_CHECK_PERSIST_CMD="${BIN_DIR}/missing-persist-again"
export IPF_ASSUME_YES=0
export IPF_TEST_INPUTS=$'n\n'
assert_eq '3' "$(status_of env_check_all)" 'env_check_all should return 3 when user rejects autofix'
# Regression: env_check_apply_fixes must return 0 even when the last flag is 0.
# 之前写成 `(( NEED_SYSCTL == 1 )) && { ... }`NEED_SYSCTL=0 时函数返回 1
# 外层 set -e 直接把脚本打死。
ENV_CHECK_NEED_PACKAGES=1
ENV_CHECK_NEED_STORAGE=0
ENV_CHECK_NEED_SYSCTL=0
assert_eq '0' "$(status_of env_check_apply_fixes)" \
'env_check_apply_fixes should return 0 when only some fixes are needed'
ENV_CHECK_NEED_PACKAGES=0
ENV_CHECK_NEED_STORAGE=0
ENV_CHECK_NEED_SYSCTL=0
assert_eq '0' "$(status_of env_check_apply_fixes)" \
'env_check_apply_fixes should return 0 when no fixes are needed'
pass 'test_env_check.sh'