mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-01 08:23:56 +08:00
🎨 Sync 2026-10-09 01:04:17
This commit is contained in:
1 parent
eb76e89012
commit
812da7f08b
154 files changed
+10613
-3987
No files matched your search
@@ -269,7 +269,7 @@ Two further host differences are bridged so the remaining checks still run:
|
||||
| `tests/i18n-coverage.py` | Reports how many `po/templates/homeproxy-pro.pot` strings have a non-fuzzy, non-empty `po/zh_Hans/homeproxy-pro.po` translation. Technical tokens that stay as-is are listed in `tests/i18n-ignore.txt`; anything else missing fails the run (`--fail-below 100`) and adds a job-summary entry. The release workflow (`build.yml`) deliberately warns instead of failing, so a translation gap cannot block packaging - the PR gates already catch it. |
|
||||
| `tests/luci-form-snapshot.js` | Dumps every option (name, kind, title, description, depends, values, datatype/default/…) of the node, client and server views. Diffs against `tests/snapshots/{node,client,server}.json`, so a refactor that changes a field or its visibility fails. |
|
||||
| `tests/ucode/test_homeproxy_utils.uc` | `executeCommand()` return shape, stderr/exit-code capture, binary detection, and a descriptor-leak check (200 calls). |
|
||||
| `tests/ucode/test_china_ip_ruleset.sh` | `runtime/china_ip_ruleset.uc`, the generator that turns `china_ip4.txt` into the `type: local` rule-set the route side matches mainland destinations with — the same list `firewall_post.ut` renders `homeproxy_mainland_addr_v4` from, so both sides decide from one source. The cases are the ones that break a router silently: a malformed line must be skipped (sing-box rejects the *whole* rule-set over one bad entry, and the client then will not start), the file must be replaced by rename (the running instance watches it with fswatch), and an empty or unreadable source must fail instead of installing a rule-set that matches nothing. Pins the bundled list's `8.152.0.0/13` — the range `geoip-cn.srs` does not carry, and the reason this exists. |
|
||||
| `tests/ucode/test_china_ip_ruleset.sh` | `runtime/china_ip_ruleset.uc`, the generator that turns `china_ip4.txt` into the `type: local` rule-set the route side matches mainland destinations with — the same list `firewall_post.ut` renders `homeproxy_mainland_addr_v4` from, so both sides decide from one source. The cases are the ones that break a router silently: a malformed line must be skipped (sing-box rejects the *whole* rule-set over one bad entry, and the client then will not start), the file must be replaced by rename (the running instance watches it with fswatch), and an empty or unreadable source must fail instead of installing a rule-set that matches nothing. Pins the bundled list's `8.152.0.0/13` — the range `geoip-cn.srs` does not carry, and the reason this exists — and, since the list changed source, that same assertion now also pins that the new upstream still carries it. The v6 half gets the same treatment: it is generated and checked for the absence of IPv4 entries, because `firewall_post.ut` reads a zero prefix count in `china_ip6.txt` as "IPv6 cannot be classified" and turns `v6_handled` off with nothing logged. |
|
||||
| `tests/ucode/test_resource_blob_sha.sh` | `resource_blob_sha.uc`, the digest the resource updater verifies downloads with. The expected values are git's own (`git hash-object` on the same bytes), covering the two cases an implementation gets wrong quietly: the empty file (a real blob id, not "no digest") and content whose byte length differs from its character count. Unreadable input must produce *no* digest and exit non-zero - the updater treats an empty answer as "cannot verify" and refuses, so a made-up digest would turn an unreadable file into a passing check. Re-checks the repository's real resource files against git when the host has it. |
|
||||
| `tests/ucode/test_homeproxy_utils_inject.uc` | The failure path of `executeCommand()`: the script stages a copy of `homeproxy-pro.uc` whose `system()` call is replaced by `die()`, then checks that the exception still propagates and that neither descriptor leaks. |
|
||||
| `tests/ucode/test_tls_transport.uc` | Direct calls into `buildTLSObject()` / `buildTransportObject()`: client-vs-server-only fields (no `insecure` on a server inbound, no `utls` on a server, `public_key` only on the client and `private_key` only on the server for reality), the ECH client/server split, and the `validateHomeProxyPath()` gate on `cert_path` / `key_path`. This is the boundary the generator fixtures only exercised end-to-end, so it is where the "server emitted insecure=true" and "reality key on the wrong side" classes of bug get named. |
|
||||
@@ -299,7 +299,7 @@ Two further host differences are bridged so the remaining checks still run:
|
||||
| `tests/runtime/test_dns_snippets.sh` | The dnsmasq snippet writer's incremental behaviour (review L6). Counts `init.d/dnsmasq restart` calls through a stub and asserts that an identical second write does *not* restart (a restart flushes every client's DNS cache), while a changed resource list, routing mode, DNS port or `ipv6_support` setting does. Also pins that a mode change drops the snippet the previous mode produced, and that removing a resource list removes its snippet so the next call is stable again. Pure shell, runs anywhere. |
|
||||
| `tests/runtime/test_health_probe.sh` | The functional health probes (`runtime/health.sh`): `hp_probe_dns` / `hp_probe_tcp` answer 0 / 1 / 2 and keep "cannot probe here" (no tool, no port) distinct from "the probe failed"; `hp_run_probes` *reports* by default and only fails the gate when `health_probe_strict` is on, and never fails it for a probe that could not run; `hp_config_port_for_tag` reads the probe ports out of the running configuration in both the generator's pretty shape and the compact one. `nslookup` and `nc` are stubbed, so it is pure shell and runs anywhere. |
|
||||
| `tests/runtime/test_crontab_perms.sh` | `hp_crontab_drop()` (runtime/service.sh) edits `/etc/crontabs/root` through a temporary file, and `mv` replaces the file rather than its contents - so the new one inherited the shell's umask (0644) while procd creates the root crontab as 0600. The test drives the function against a sandboxed crontab and pins: the entry is dropped, other jobs survive, the mode is 0600 (including a file an older version had already loosened), a missing crontab is reported as a failure and is not created. Pure shell, runs anywhere. |
|
||||
| `tests/runtime/test_resource_update.sh` | The content-verification path of `scripts/update_resources.sh`: the download URL is pinned to a commit, and the file is installed only when its git blob id matches the one GitHub reports for that path and commit. Drives all four outcomes (match, mismatch, no digest from the API, no local digest) with `uclient-fetch` / `jsonfilter` / `ucode` / `uci` / `flock` stubbed and the script's absolute paths rewritten into a sandbox, asserting in each failure case that the installed list and its `.ver` are left untouched - the point of the check is that it refuses, so a driver that only walked the happy path would keep passing with the check deleted. Pure shell, runs anywhere. |
|
||||
| `tests/runtime/test_resource_update.sh` | The content-verification path of `scripts/update_resources.sh`: the download URL is pinned to a commit, and the file is installed only when its git blob id matches the one GitHub reports for that path and commit. Drives all four outcomes (match, mismatch, no digest from the API, no local digest) with `uclient-fetch` / `jsonfilter` / `ucode` / `uci` / `flock` stubbed and the script's absolute paths rewritten into a sandbox, asserting in each failure case that the installed list and its `.ver` are left untouched - the point of the check is that it refuses, so a driver that only walked the happy path would keep passing with the check deleted. Also covers the two post-processing steps that carry a failure silently: `china_list`'s normalisation ordering, the address-family split (both IP lists come out of one upstream file, so each has to land at its own `.txt` holding only its own family, the combined download must not be left in `RUN_DIR`, and a family with no entries has to be refused rather than installed empty), and the firewall re-render that closes the loop on the nft half. That last one is the reason a test exists at all: the route side goes live on fswatch while `homeproxy_mainland_addr_v4/v6` are rendered into `fw4_post.nft` and otherwise only a start/restart installs them, so "the list updated" and "the kernel sees it" are different events. Both directions are asserted — a successful update must re-render and call `fw4 reload`, and a failed render must leave the previous ruleset in place, must not reach `fw4`, and must not fail the update (a resource that can never refresh is worse than one briefly missing from the firewall). Pure shell, runs anywhere. |
|
||||
| `tests/runtime/test_runtime_extraction.sh` | Drives `init.d/homeproxy-pro` through a stubbed environment (fake `ip` / `nft` / `fw4` / `ucode` / `sing-box` / `uci` / `netstat` / `nslookup` / `nc`, fake procd and jsonfilter state, fixture UCI) across five scenarios and diffs the resulting command + file trace against a baseline. Two baselines exist and are captured with the SAME harness, so the diff between them is exactly the intentional change: `tests/fixtures/runtime/trace.pre-pr05.txt` (the 517-line init script before PHASE 7 moved the plumbing out — the record that the extraction was behaviour-preserving) and `tests/fixtures/runtime/trace.golden.txt` (after the health-gate fix). Scenario D is the P0 regression: a candidate whose `mixed_port` is already taken must be rejected by the health gate, the previous known-good must survive, and the reload must roll back onto it. The generated fixture configuration is pretty-printed like the generator's own `%.J` output, because the runtime reads that file (`hp_config_ports`, `hp_config_port_for_tag`) and a compact fixture would test a shape production never writes. Pure shell, no ucode needed. Regenerate with `HP_UPDATE_GOLDEN=1` (optionally `HP_GOLDEN=` / `HP_INITD=` to target another baseline or revision). |
|
||||
|
||||
**`HP_UPDATE_GOLDEN=1` is a baseline-update mode, not a test.** It copies the
|
||||
|
||||
@@ -106,7 +106,24 @@ emit() {
|
||||
fi
|
||||
}
|
||||
case "$url" in
|
||||
*api.github.com/*/commits*) emit "$(cat "$HP_T_API_COMMITS")" ;;
|
||||
*api.github.com/*/commits*)
|
||||
# Filtered by path, the way the real endpoint is. Asking for a file
|
||||
# that is not at that path is not a narrower question, it is a different
|
||||
# one: it matches no commit and comes back []. That is the whole reason
|
||||
# the in-repo path is a separate argument from the file name, and it is
|
||||
# what this branch can now catch - every list this project ships used to
|
||||
# live in the repo root, so path= and the file name were the same string
|
||||
# and nothing could tell them apart.
|
||||
case "$url" in
|
||||
*repos/MetaCubeX/*)
|
||||
case "$url" in
|
||||
*"path=geo/geoip/cn.list"*) emit "$(cat "$HP_T_API_COMMITS")" ;;
|
||||
*) emit '[]' ;;
|
||||
esac
|
||||
;;
|
||||
*) emit "$(cat "$HP_T_API_COMMITS")" ;;
|
||||
esac
|
||||
;;
|
||||
*api.github.com/*/contents*) emit "$(cat "$HP_T_API_CONTENTS")" ;;
|
||||
*)
|
||||
# A spider probe (-s) checks reachability only, and its stdout is captured
|
||||
@@ -115,6 +132,19 @@ case "$url" in
|
||||
# applet prints nothing for a probe.
|
||||
[ "$probe" = "0" ] || exit 0
|
||||
if [ -n "${HP_T_FETCH_FAIL:-}" ]; then exit 1; fi
|
||||
# The same wrong-path mistake reaches the download as a 404, and
|
||||
# pick_mirror turns that into "all mirrors unreachable" - a second
|
||||
# symptom of the one bug, reported as an unrelated-looking network
|
||||
# failure. Scoped to this source so the other lists, whose file name is
|
||||
# their in-repo path, keep resolving.
|
||||
case "$url" in
|
||||
*MetaCubeX/meta-rules-dat*)
|
||||
case "$url" in
|
||||
*geo/geoip/cn.list*) ;;
|
||||
*) exit 1 ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
emit "$(cat "$HP_T_BODY")"
|
||||
;;
|
||||
esac
|
||||
@@ -179,6 +209,21 @@ cat > "$WORK/bin/flock" <<'EOF'
|
||||
#!/bin/sh
|
||||
exit 0
|
||||
EOF
|
||||
# utpl renders firewall_post.ut into the file named by -O-less stdout; the stub
|
||||
# writes a marker line and honours a failure switch, which is all the two
|
||||
# cases below need. fw4 records that it was called and honours its own.
|
||||
cat > "$WORK/bin/utpl" <<'EOF'
|
||||
#!/bin/sh
|
||||
[ -n "${HP_T_UTPL_FAIL:-}" ] && exit 1
|
||||
printf 'rendered-from-utpl\n'
|
||||
exit 0
|
||||
EOF
|
||||
cat > "$WORK/bin/fw4" <<'EOF'
|
||||
#!/bin/sh
|
||||
[ -n "$HP_T_FW4_CALLED" ] && printf 'called\n' >> "$HP_T_FW4_CALLED"
|
||||
[ -n "${HP_T_FW4_FAIL:-}" ] && exit 1
|
||||
exit 0
|
||||
EOF
|
||||
chmod +x "$WORK/bin/"*
|
||||
|
||||
PATH="$WORK/bin:$PATH"
|
||||
@@ -205,14 +250,20 @@ EOF
|
||||
|
||||
write_contents_json() {
|
||||
# write_contents_json <blob-sha-or-empty>
|
||||
# The upstream file is cn.list, not ipv4.txt: it carries both address
|
||||
# families and each listtype takes one half of it (install_download).
|
||||
if [ -n "$1" ]; then
|
||||
printf '{"name":"ipv4.txt","size":6,"sha":"%s"}' "$1" > "$WORK/api-contents.json"
|
||||
printf '{"name":"cn.list","size":6,"sha":"%s"}' "$1" > "$WORK/api-contents.json"
|
||||
else
|
||||
printf '{"name":"ipv4.txt","size":6}' > "$WORK/api-contents.json"
|
||||
printf '{"name":"cn.list","size":6}' > "$WORK/api-contents.json"
|
||||
fi
|
||||
}
|
||||
|
||||
printf 'fresh\n' > "$WORK/body.txt"
|
||||
# Mixed on purpose: china_ip4 must end up holding only the first line, and the
|
||||
# IPv6 line is what the china_ip6 cases below split out. Keeping "fresh" as the
|
||||
# single IPv4 line means the cases that only care about the blob-id handshake
|
||||
# keep asserting on "fresh" unchanged.
|
||||
printf 'fresh\n2001:db8::/32\n' > "$WORK/body.txt"
|
||||
printf 'stale-installed-copy\n' > "$WORK/resources/china_ip4.txt"
|
||||
printf 'OLDVERSION' > "$WORK/resources/china_ip4.ver"
|
||||
|
||||
@@ -269,7 +320,7 @@ expect "the .ver is untouched" "$(cat "$WORK/resources/china_ip4.ver")" "OLDVERS
|
||||
expect "no .updated_at was written" "$([ -e "$WORK/resources/china_ip4.updated_at" ] && echo yes || echo no)" "no"
|
||||
expect "the refusal is logged with both ids" \
|
||||
"$(grep -c "does not match the content of commit $API_SHA" "$WORK/run/homeproxy-pro.log")" "1"
|
||||
expect "the downloaded copy was discarded" "$([ -e "$WORK/run/ipv4.txt" ] && echo yes || echo no)" "no"
|
||||
expect "the downloaded copy was discarded" "$([ -e "$WORK/run/cn.list" ] && echo yes || echo no)" "no"
|
||||
|
||||
echo "== case 3: no blob id from the API -> refused =="
|
||||
reset_state
|
||||
@@ -373,6 +424,109 @@ expect "the .ver is untouched" "$(cat "$WORK/resources/china_list.ver")" "OLDVER
|
||||
expect "the generator was never called" \
|
||||
"$([ -e "$HP_T_SEEN_SOURCE" ] && echo yes || echo no)" "no"
|
||||
|
||||
echo "== case 8: cn.list is split by address family =="
|
||||
# Both IP lists come out of one upstream file now (MetaCubeX cn.list), so the
|
||||
# install step splits rather than moves. What has to hold: each listtype ends
|
||||
# up at its own .txt name with only its own family in it, and the combined
|
||||
# download is not left lying in RUN_DIR for the next run to trip over.
|
||||
reset_state
|
||||
printf 'OLDVERSION' > "$WORK/resources/china_ip6.ver"
|
||||
rm -f "$WORK/resources/china_ip6.txt"
|
||||
# Set here rather than relying on the top-of-file fixture: case 6 overwrote
|
||||
# body.txt with its own domain lines.
|
||||
printf '1.0.0.0/24\n2001:db8::/32\n' > "$WORK/body.txt"
|
||||
: > "$WORK/run/homeproxy-pro.log"
|
||||
printf '%s' "$LOCAL_SHA" > "$HP_T_LOCAL_BLOB"
|
||||
rc="$("$RUN_SH" "$WORK/scripts/update_resources.sh" china_ip6 > "$WORK/stdout" 2>&1; echo $?)"
|
||||
expect "exit status 0" "$rc" "0"
|
||||
expect "china_ip6.txt was created by the split" \
|
||||
"$(cat "$WORK/resources/china_ip6.txt" 2>/dev/null)" "2001:db8::/32"
|
||||
expect "it holds no IPv4 entry" \
|
||||
"$(grep -cE '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/' "$WORK/resources/china_ip6.txt" || true)" "0"
|
||||
expect "its .ver advanced like the v4 one" \
|
||||
"$(cat "$WORK/resources/china_ip6.ver")" "2026-01-02 $API_SHA"
|
||||
expect "the combined download was cleaned out of RUN_DIR" \
|
||||
"$([ -e "$WORK/run/cn.list" ] && echo yes || echo no)" "no"
|
||||
expect "no half-written temp file survived" \
|
||||
"$([ -e "$WORK/resources/china_ip6.txt.hp-new" ] && echo yes || echo no)" "no"
|
||||
|
||||
echo "== case 9: a family with no entries is refused, not installed empty =="
|
||||
# The failure this guards is silent: an empty china_ip6.txt makes
|
||||
# firewall_post.ut count zero usable prefixes and turn v6_handled off, after
|
||||
# which every mainland IPv6 connection goes to the proxy - with no error
|
||||
# anywhere. Keeping the previous list is the only acceptable outcome.
|
||||
reset_state
|
||||
printf 'stale-v6-copy\n' > "$WORK/resources/china_ip6.txt"
|
||||
printf 'OLDVERSION' > "$WORK/resources/china_ip6.ver"
|
||||
printf 'only-v4-here/24\n' > "$WORK/body.txt"
|
||||
: > "$WORK/run/homeproxy-pro.log"
|
||||
printf '%s' "$LOCAL_SHA" > "$HP_T_LOCAL_BLOB"
|
||||
rc="$("$RUN_SH" "$WORK/scripts/update_resources.sh" china_ip6 > "$WORK/stdout" 2>&1; echo $?)"
|
||||
expect "exit status non-zero" "$rc" "1"
|
||||
expect "the previous v6 list is untouched" \
|
||||
"$(cat "$WORK/resources/china_ip6.txt")" "stale-v6-copy"
|
||||
expect "its .ver is untouched" "$(cat "$WORK/resources/china_ip6.ver")" "OLDVERSION"
|
||||
expect "the reason is logged" \
|
||||
"$(grep -c 'carries no v6 entries' "$WORK/run/homeproxy-pro.log")" "1"
|
||||
expect "no empty temp file survived" \
|
||||
"$([ -e "$WORK/resources/china_ip6.txt.hp-new" ] && echo yes || echo no)" "no"
|
||||
|
||||
echo "== case 10: a successful IP update re-renders the firewall sets =="
|
||||
# The two halves of the mainland split read the same file but go live on
|
||||
# different triggers: sing-box watches the generated rule-set, while the nft
|
||||
# set is rendered into fw4_post.nft and otherwise only a start/restart puts
|
||||
# it in place. Without this step the kernel's copy silently ages past the
|
||||
# file's, and a segment the list has since dropped keeps matching
|
||||
# `ip daddr @homeproxy_mainland_addr_v4 counter return` - which returns before
|
||||
# the redirect, so the route side never gets to correct it.
|
||||
reset_state
|
||||
printf 'v4-here/24\n2001:db8::/32\n' > "$WORK/body.txt"
|
||||
printf 'stale-rendered-ruleset\n' > "$WORK/run/fw4_post.nft"
|
||||
rm -f "$WORK/run/fw4_post.nft.new"
|
||||
export HP_T_FW4_CALLED="$WORK/fw4-called"
|
||||
rm -f "$HP_T_FW4_CALLED"
|
||||
: > "$WORK/run/homeproxy-pro.log"
|
||||
rc="$("$RUN_SH" "$WORK/scripts/update_resources.sh" china_ip4 > "$WORK/stdout" 2>&1; echo $?)"
|
||||
expect "exit status 0" "$rc" "0"
|
||||
expect "fw4_post.nft was re-rendered from the new list" \
|
||||
"$(cat "$WORK/run/fw4_post.nft" 2>/dev/null)" "rendered-from-utpl"
|
||||
expect "fw4 reload ran" \
|
||||
"$(grep -c 'called' "$HP_T_FW4_CALLED" 2>/dev/null || echo 0)" "1"
|
||||
expect "no temp file left behind" \
|
||||
"$([ -e "$WORK/run/fw4_post.nft.new" ] && echo yes || echo no)" "no"
|
||||
expect "the success is logged" \
|
||||
"$(grep -c 'Firewall mainland sets re-rendered' "$WORK/run/homeproxy-pro.log")" "1"
|
||||
|
||||
echo "== case 11: a failed render is warned about, not fatal =="
|
||||
# Failing the update would be worse than the lag it is reporting: the list on
|
||||
# disk is already the one the commit vouched for, and a resource that can
|
||||
# never refresh is a far bigger problem than one that is briefly not in the
|
||||
# firewall. The previous ruleset has to survive, or a bad render takes the
|
||||
# whole intercept layer down with it.
|
||||
reset_state
|
||||
printf 'v4-here/24\n2001:db8::/32\n' > "$WORK/body.txt"
|
||||
printf 'known-good-ruleset\n' > "$WORK/run/fw4_post.nft"
|
||||
rm -f "$WORK/run/fw4_post.nft.new"
|
||||
export HP_T_UTPL_FAIL=1
|
||||
: > "$WORK/run/homeproxy-pro.log"
|
||||
# Cleared because the point of this case is that a failed render must not
|
||||
# reach fw4 at all - inheriting case 10's record would make the assertion
|
||||
# pass for the wrong reason if the branch started reloading anyway.
|
||||
rm -f "$HP_T_FW4_CALLED"
|
||||
rc="$("$RUN_SH" "$WORK/scripts/update_resources.sh" china_ip4 > "$WORK/stdout" 2>&1; echo $?)"
|
||||
unset HP_T_UTPL_FAIL
|
||||
expect "the update still succeeded" "$rc" "0"
|
||||
expect "the list was still installed" \
|
||||
"$(cat "$WORK/resources/china_ip4.txt")" "v4-here/24"
|
||||
expect "the previous ruleset is untouched" \
|
||||
"$(cat "$WORK/run/fw4_post.nft")" "known-good-ruleset"
|
||||
expect "no half-written temp file survived" \
|
||||
"$([ -e "$WORK/run/fw4_post.nft.new" ] && echo yes || echo no)" "no"
|
||||
expect "fw4 was NOT reloaded" \
|
||||
"$(grep -c 'called' "$HP_T_FW4_CALLED" 2>/dev/null || echo 0)" "0"
|
||||
expect "the warning names the manual recovery" \
|
||||
"$(grep -c 'could not re-render fw4_post.nft' "$WORK/run/homeproxy-pro.log")" "1"
|
||||
|
||||
printf '%d checks, %d failures\n' "$CHECKS" "$FAILURES"
|
||||
if [ "$FAILED" != "0" ]; then
|
||||
echo "RESOURCE UPDATE TESTS FAILED"
|
||||
|
||||
@@ -104,12 +104,24 @@ expect "output carries a version" \
|
||||
# The list this ships with is what the firewall renders its nft set from; a
|
||||
# generator that mangles it would break both sides at once.
|
||||
expect "the bundled china_ip4.txt generates" \
|
||||
"$(generate "$ROOT/root/etc/homeproxy-pro/resources/china_ip4.txt" "$WORK/real.json")" "4068 prefixes"
|
||||
"$(generate "$ROOT/root/etc/homeproxy-pro/resources/china_ip4.txt" "$WORK/real.json")" "6163 prefixes"
|
||||
# 8.152.0.0/13 is the range geoip-cn.srs does *not* carry, and the one that
|
||||
# made segmentfault.com and ctrip.com resolve into the proxy path.
|
||||
# made segmentfault.com and ctrip.com resolve into the proxy path. The list
|
||||
# changed source since, so this is now also the assertion that the new upstream
|
||||
# still carries it rather than having merged it away.
|
||||
expect "the bundled list carries 8.152.0.0/13" \
|
||||
"$(grep -c '8\.152\.0\.0/13' "$WORK/real.json")" "1"
|
||||
|
||||
# The v6 half, which used to be the untested one. It matters for the same
|
||||
# reason: firewall_post.ut counts usable prefixes in china_ip6.txt and turns
|
||||
# v6_handled off entirely when the count is zero, which silently sends every
|
||||
# mainland IPv6 connection down the proxy. A generator that emitted an empty
|
||||
# v6 rule-set would look identical from the config.
|
||||
expect "the bundled china_ip6.txt generates" \
|
||||
"$(generate "$ROOT/root/etc/homeproxy-pro/resources/china_ip6.txt" "$WORK/real6.json")" "3446 prefixes"
|
||||
expect "the v6 rule-set carries no IPv4 entry" \
|
||||
"$(grep -cE '"[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/' "$WORK/real6.json")" "0"
|
||||
|
||||
# --- failure paths ----------------------------------------------------------
|
||||
|
||||
# An empty source must not install an empty rule-set: the caller would then be
|
||||
|
||||
Reference in new issue
Block a user