#!/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}" <>"${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}" <>"${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'