@@ -180,18 +180,36 @@ logger() { :; }
180180# Override ubus to return nothing (init script defines its own wrapper)
181181__UBUS_BIN=" true"
182182
183+ # Mock `nft`: track invocations and return success by default. Tests can
184+ # override __nft_rc to simulate failure.
185+ __nft_calls_file=" $TESTDIR /nft_calls"
186+ __nft_rc=0
187+ : > " $__nft_calls_file "
188+ nft () {
189+ printf ' %s\n' " $* " >> " $__nft_calls_file "
190+ return " $__nft_rc "
191+ }
192+
183193# ── Source the init script (skip the shebang line) ──────────────────
194+ #
195+ # Patch the readonly NOTRACK_NFT_FILE path so tests can write under
196+ # $TESTDIR instead of /usr/share/nftables.d/ruleset-post/.
184197
185198INIT_SCRIPT=" ./files/etc/init.d/https-dns-proxy"
186199if [ ! -f " $INIT_SCRIPT " ]; then
187200 echo " ERROR: Cannot find $INIT_SCRIPT . Run from the https-dns-proxy package root."
188201 exit 1
189202fi
190203
204+ PATCHED_INIT=" $TESTDIR /https-dns-proxy.patched"
205+ NOTRACK_TEST_FILE=" $TESTDIR /usr/share/nftables.d/ruleset-post/20-https-dns-proxy-notrack.nft"
206+ sed " s|^readonly NOTRACK_NFT_FILE=.*|readonly NOTRACK_NFT_FILE='$NOTRACK_TEST_FILE '|" \
207+ " $INIT_SCRIPT " > " $PATCHED_INIT "
208+
191209# Source all functions. The #!/bin/sh /etc/rc.common line is harmless
192210# when we've already defined the framework stubs above.
193211# shellcheck disable=SC1090
194- . " $INIT_SCRIPT "
212+ . " $PATCHED_INIT "
195213
196214# ##############################################################################
197215# TEST CATEGORIES #
@@ -611,6 +629,71 @@ load_package_config
611629assert_eq " load_package_config: canary disabled → canaryDomains empty" " " " $canaryDomains "
612630assert_eq " load_package_config: force_dns=0 → unset" " " " $force_dns "
613631
632+ printf " \n##\n## 10: notrack_nft (regression: missing nftables.d/ruleset-post dir)\n##\n\n"
633+
634+ # Reset state — ensure parent dir does NOT exist (this is the apk-install
635+ # bug: post-install runs `start` before fw4 has created the directory).
636+ rm -rf " $TESTDIR /usr/share"
637+ __nft_rc=0
638+ : > " $__nft_calls_file "
639+
640+ assert_eq " notrack_nft: NOTRACK_NFT_FILE patched to test path" " $NOTRACK_TEST_FILE " " $NOTRACK_NFT_FILE "
641+
642+ # Pre-condition: parent dir genuinely missing
643+ [ ! -d " $( dirname " $NOTRACK_TEST_FILE " ) " ]
644+ assert_rc " notrack_nft: parent dir absent before update" 0 $?
645+
646+ # THE REGRESSION: previously this failed with
647+ # "can't create .../20-https-dns-proxy-notrack.nft: nonexistent directory"
648+ notrack_nft update " 53 5053"
649+ assert_rc " notrack_nft update creates parent dir on first call" 0 $?
650+
651+ [ -f " $NOTRACK_TEST_FILE " ]
652+ assert_rc " notrack_nft update wrote nft snippet file" 0 $?
653+
654+ [ -d " $( dirname " $NOTRACK_TEST_FILE " ) " ]
655+ assert_rc " notrack_nft update created parent dir" 0 $?
656+
657+ # Content should reference the table, hook, and ports we passed
658+ grep -q " table inet https_dns_proxy_notrack" " $NOTRACK_TEST_FILE "
659+ assert_rc " notrack_nft snippet declares the wrapper table" 0 $?
660+
661+ grep -q " type filter hook output priority raw" " $NOTRACK_TEST_FILE "
662+ assert_rc " notrack_nft snippet declares raw output hook" 0 $?
663+
664+ grep -q " 53 5053" " $NOTRACK_TEST_FILE "
665+ assert_rc " notrack_nft snippet contains supplied ports" 0 $?
666+
667+ # Syntax check should have been invoked
668+ grep -q -- " -c -f $NOTRACK_TEST_FILE " " $__nft_calls_file "
669+ assert_rc " notrack_nft update invokes 'nft -c -f' on the snippet" 0 $?
670+
671+ # ── Idempotence: same content → no extra write churn ──
672+ # We can't easily detect a no-op write, but we can confirm the function
673+ # still succeeds when the file already exists with matching content.
674+ notrack_nft update " 53 5053"
675+ assert_rc " notrack_nft update idempotent on identical content" 0 $?
676+
677+ # ── Empty port_set → routes to remove ──
678+ notrack_nft update " "
679+ [ ! -f " $NOTRACK_TEST_FILE " ]
680+ assert_rc " notrack_nft update '' removes the snippet file" 0 $?
681+
682+ # ── Explicit remove ──
683+ mkdir -p " $( dirname " $NOTRACK_TEST_FILE " ) "
684+ echo " stale" > " $NOTRACK_TEST_FILE "
685+ : > " $__nft_calls_file "
686+ notrack_nft remove
687+ [ ! -f " $NOTRACK_TEST_FILE " ]
688+ assert_rc " notrack_nft remove deletes the snippet file" 0 $?
689+
690+ grep -q " delete table inet https_dns_proxy_notrack" " $__nft_calls_file "
691+ assert_rc " notrack_nft remove invokes 'nft delete table'" 0 $?
692+
693+ # ── remove is a no-op when file already absent ──
694+ notrack_nft remove
695+ assert_rc " notrack_nft remove succeeds when file already absent" 0 $?
696+
614697# ##############################################################################
615698# SHELL SCRIPT SYNTAX #
616699# ##############################################################################
0 commit comments