#!/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 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" # shellcheck source=lib/common.sh source "${ROOT_DIR}/lib/common.sh" # shellcheck source=lib/storage.sh source "${ROOT_DIR}/lib/storage.sh" # shellcheck source=lib/persist.sh source "${ROOT_DIR}/lib/persist.sh" # shellcheck source=lib/iptables_ops.sh source "${ROOT_DIR}/lib/iptables_ops.sh" # shellcheck source=lib/rules_mgr.sh source "${ROOT_DIR}/lib/rules_mgr.sh" reset_mock_state() { rm -rf "${IPTABLES_MOCK_DIR}" "${IPF_STORAGE_DIR}" mkdir -p "${IPTABLES_MOCK_DIR}" "${IPF_STORAGE_DIR}" : >"${IPTABLES_MOCK_LOG}" : >"${PERSIST_MOCK_LOG}" unset IPTABLES_MOCK_FAIL_ON_N || true storage_init } reset_mock_state uuid_v4=$(cmd_add_batch tcp 8080 127.0.0.1 80 4 'web service') assert_eq '1' "$(storage_count)" 'cmd_add_batch should persist one rule' assert_eq '3' "$(grep -Ec '^iptables ' "${IPTABLES_MOCK_LOG}")" 'tcp/ipv4 add should emit three iptables commands' assert_contains "$(storage_get "${uuid_v4}")" "uuid=${uuid_v4}" 'stored line should contain generated uuid' assert_eq '1' "$(grep -Ec 'persist-mock\.sh save' "${PERSIST_MOCK_LOG}")" 'successful add should trigger persist_save' assert_contains "$(ipt_find_by_uuid "${uuid_v4}")" "MGMT:${uuid_v4}" 'ipt_find_by_uuid should locate saved mock rules' reset_mock_state uuid_both=$(cmd_add_batch both 5353 '127.0.0.1,::1' 53 both 'dual stack dns') add_count=$(grep -Ec '^(iptables|ip6tables) ' "${IPTABLES_MOCK_LOG}") assert_eq '12' "${add_count}" 'both/both add should emit twelve commands' cmd_delete_uuid "${uuid_both}" del_count=$(grep -Ec ' -D ' "${IPTABLES_MOCK_LOG}") assert_eq '12' "${del_count}" 'deleting both/both rule should emit twelve delete commands' assert_eq '0' "$(storage_count)" 'cmd_delete_uuid should remove rule from storage' reset_mock_state export IPTABLES_MOCK_FAIL_ON_N=2 assert_eq '1' "$(status_of cmd_add_batch tcp 9000 127.0.0.1 90 4 'rollback')" 'cmd_add_batch should fail when iptables mock injects an error' assert_eq '0' "$(storage_count)" 'failed add should not persist storage' assert_contains "$(cat "${IPTABLES_MOCK_LOG}")" ' -D ' 'failed add should trigger rollback deletes' assert_eq '0' "$(wc -l < "${PERSIST_MOCK_LOG}")" 'failed add before persistence should not call persist_save' pass 'test_rules_unit.sh'