Files
MeowOS-For-R3P2/patch_v2/meow_netmgrd/test_netmgrd.sh
T
AskaEth 7c7d891570 feat: M6.44+M6.45 收编 — 真机 0.8.45 现场保全(reader章节/key_router按键路由/WiFi连接修复/ncm bench+IME修复)
脏工作区现场收编:devdocs/local/m6_44_45_dirty_tracked.patch(46 个已跟踪文本文件,
+3090/-585, 已对 M6.43 基线干净适配) + m6_44_45_untracked_src.tar.gz 中 patch_v2/ 下
13 个新增源文件, 合成单个提交, 内容与容器工作树(R3ProII/patch_v2)逐字节一致。

- reader 章节: 新增 core/rdchapter.{h,c} — TXT 章节规范解析器, 扫描 512KB 码位对齐段文件
  逐段流式识别标题行(行首缩进≤4/显示宽≤40/行内标点≤1 三重约束防误判), 输出标题+全书字符
  偏移+段号/段内偏移+阿拉伯章号(中文数字归一), 首章前内容归"卷首"; book/reader/rdenc/
  rdlayout/settings 接入章节跳转与进度锚点, 附 chapter_smoke/turn_repro/build_turn_repro.sh
- key_router 按键路由: 新增 meow_launcherd/key_router.{h,c} — launcher-UI 页物理键统一路由
  (P1 仅音量键), 把读取边沿+防抖+长按 held+ramp 推进从 5 个会话收敛为进程内单开;
  各页每圈 key_router_pump() 取防抖后边沿, 动作(调音量/光标导航)仍由调用页决定,
  保留 run_menu 的 meow_mode 分支; App 前台 volume_page 武装时边沿抑制;
  main_menu/now_playing/notif_center/settings_page/subpage 接入, 附 test_key_router_vol/test_np_keys
- WiFi 连接修复: meow_netmgrd connect 有界等待 wpa_state=COMPLETED(普通 10s/隐藏网络 15s,
  env 可调)修设置页连接无响应; list_networks/scan_results 的 \xNN 转义还原始字节, 修中文 SSID
  永不命中致新建同名 open 记录顶影; launcher netmgr_ipc 配读超时; 附 test_wifi_connect(桩
  wpa_cli 驱动 static wifi_connect_ex), test_netmgrd.sh 补用例; wifi_page 同步
- ncm bench: 新增 bench/lyric_sim.c、bench/plpage_sim.c, vol_sync_sim 与 ncm core/app 同步
- SDK IME 修复: shift 大小写、K_ENTER 只提交不关、阻塞 IME 循环喂 on_tick 不被遮挡、
  IME 打开 ~200ms TAP 冷却窗吞 stray-TAP; 附 sdk/test_ime_fix.c
- 同期: meow_audiod 音量异步 ACK 线程(代际防 fd/槽复用竞态)、watchdog 音量收编(首选 audiod
  权威, settings.conf 覆盖路径)、panel 文件搜索(F1-④)与蓝牙只读详情(F1-③)、各类 build 脚本同步

范围红线: third_party/legado-E-main 原开发者未跟踪, 本次不入库(保留 devdocs/local tar 参考);
二进制不入库(后续重编); devdocs/ 不入库。59 文件全部在 patch_v2/ 下, 无 third_party/devdocs。
验证: git apply --check 干净; 59 文件 md5 与容器 patch_v2 逐一比对 59/59 一致(含
key_router.c/rdchapter.c/meow_ui_ime.c/test_wifi_connect.c 抽查); 可执行位保守
(check_lgpl_release.sh 100755, build_turn_repro.sh 100644 与容器一致)。
2026-11-04 20:02:28 +08:00

448 lines
20 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.
#!/bin/bash
# test_netmgrd.sh — meow_netmgrd 宿主桩测试(假 sysfs/procfs 节点 + 桩后端命令,MEOW_* env 覆盖)。
# 用法:./test_netmgrd.sh [host二进制路径](默认 ./meow_netmgrd_host;可传 mipsel 二进制 + QEMU 前缀)
# QEMU="qemu-mipsel" ./test_netmgrd.sh ./meow_netmgrd # qemu 验证
set -u
cd "$(dirname "$0")"
BIN="${1:-./meow_netmgrd_host}"
Q="${QEMU:-}"
T=$(mktemp -d /tmp/netmgrdtest.XXXXXX)
trap 'kill $DPID 2>/dev/null; rm -rf "$T"' EXIT
PASS=0; FAIL=0
ck() { # ck <名> <期望子串> <实际>
if echo "$3" | grep -qF "$2"; then PASS=$((PASS+1)); echo "PASS $1";
else FAIL=$((FAIL+1)); echo "FAIL $1: 期望含 [$2] 实际=[$3]"; fi
}
# ---- 搭假节点 ----
NET="$T/net"; RF="$T/rfkill"; BT="$T/bt"
mkdir -p "$NET/lo" "$NET/wlan0" "$RF/rfkill0" "$RF/rfkill1" "$BT/hci0"
echo up > "$NET/lo/operstate"
echo up > "$NET/wlan0/operstate"
echo wlan > "$RF/rfkill0/type"; echo 0 > "$RF/rfkill0/soft"; echo 0 > "$RF/rfkill0/hard"
echo bluetooth > "$RF/rfkill1/type"; echo 1 > "$RF/rfkill1/soft"; echo 0 > "$RF/rfkill1/hard"
echo 00:1A:7D:DA:71:13 > "$BT/hci0/address"
echo on > "$BT/hci0/power"
cat > "$T/netdev" <<'EOF'
Inter-| Receive | Transmit
face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
lo: 1000 10 0 0 0 0 0 0 1000 10 0 0 0 0 0 0
wlan0: 5000000 5000 0 0 0 0 0 0 1000000 1000 0 0 0 0 0 0
EOF
cat > "$T/route" <<'EOF'
Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT
wlan0 005EC20A 6F3DC20A 0003 0 0 0 00FFFFFF 0 0 0
lo 0100007F 00000000 0001 0 0 0 000000FF 0 0 0
EOF
printf 'nameserver 223.5.5.5\nnameserver 10.78.193.1\n' > "$T/resolv"
echo meow > "$T/boot_mode"
# ---- 期2 观测层打桩:/proc/net/{tcp,udp}(IPv4 LE hex)+ 域名规则 conf + amsd/svcd 缺省 ----
cat > "$T/tcp" <<'EOF'
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 32C14E0A:5137 0905CD8C:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 12345 1 0 0 10 0
1: 32C14E0A:4F32 32C34E0A:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 12346 1 0 0 10 0
2: 32C14E0A:0A00 00000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 67890 1 0 0 10 0
3: 32C14E0A:4F33 32C34E0A:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 0 1 0 0 10 0
EOF
cat > "$T/udp" <<'EOF'
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 0100007F:D301 0100007F:0035 07 00000000:00000000 00:00000000 00000000 0 0 99999 1 0 0 10 0
EOF
printf 'app:dev.player.ncm domain=-ads.example.com\nproc:dropbear domain=+x\n' > "$T/policy"
# 桩后端命令(popen stubbing)
cat > "$T/wpa_cli" <<'EOF'
#!/bin/sh
case "$1" in
status) echo "wpa_state=COMPLETED"; echo "ssid=MyWiFi"; echo "ip_address=10.78.193.50"; echo "signal=-45";;
scan) echo OK;;
scan_results) printf 'bssid / frequency / signal level / flags / ssid\nxx:xx / 2412 / -50 / WPA2 / TestAP\n';;
list_networks) printf 'network id / ssid / bssid / flags\n0\tMyWiFi\tany\t[CURRENT]\n';;
add_network) echo 1;;
set_network) echo OK;;
enable_network) echo OK;;
select_network) echo OK;;
disconnect) echo OK;;
esac
exit 0
EOF
cat > "$T/hciconfig" <<'EOF'
#!/bin/sh
echo "hci0: Type: Primary Bus: USB"
echo " BD Address: 00:1A:7D:DA:71:13 ACL MTU: 1021:8 SCO MTU: 64:1"
echo " UP RUNNING PSCAN"
EOF
cat > "$T/bluetoothctl" <<'EOF'
#!/bin/sh
case "${1:-}" in
paired|paired-devices)
echo "Device 00:1A:7D:DA:71:13 My Headset"
echo "Device 11:22:33:44:55:66 Speaker";;
devices)
echo "Device 00:1A:7D:DA:71:13 My Headset"
echo "Device 11:22:33:44:55:66 Speaker"
echo "Device 33:DE:2E:21:AD:30 Pudding";;
connect|disconnect|pair|remove)
echo "Controller 00:1A:7D:DA:71:13 Connected: yes";;
*) echo "Device 00:1A:7D:DA:71:13 My Headset"; echo "Device 11:22:33:44:55:66 Speaker";;
esac
exit 0
EOF
cat > "$T/hcitool" <<'EOF'
#!/bin/sh
echo " < ACL 33:DE:2E:21:AD:30 handle 12 state 1 lm MASTER"
echo " < ACL 11:22:33:44:55:66 handle 13 state 1 lm SLAVE"
exit 0
EOF
cat > "$T/bluealsa-cli" <<'EOF'
#!/bin/sh
if [ "${1:-}" = "a2dp" ]; then
echo "/org/bluealsa/hci0/dev_33_DE_2E_21_AD_30/a2dpsrc:"
echo " Type: A2DP Source"
echo " Codec: SBC"
echo " Sampling: 44100 Hz"
echo " Channels: 2"
echo " Bits per Sample: 16"
echo " State: RUNNING"
echo " Acquired: yes"
fi
exit 0
EOF
cat > "$T/ip" <<'EOF'
#!/bin/sh
for a in "$@"; do
if [ "$a" = "wlan0" ]; then echo "2: wlan0 inet 10.78.193.50/24 brd 255.255.255.255 scope global wlan0"; fi
if [ "$a" = "lo" ]; then echo "1: lo inet 127.0.0.1/8 scope host lo"; fi
done
exit 0
EOF
for f in wpa_cli hciconfig bluetoothctl hcitool bluealsa-cli ip; do chmod +x "$T/$f"; done
mkdir -p "$T/logs" "$T/pid"
# 期2:DNS 禁用(宿主无 root 不绑 53),观测层经 MEOW_TCP/UDP 打桩;amsd/svcd 缺省(实体归因走 proc:comm→unknown)。
ENVS="MEOW_NET_DIR=$NET MEOW_NETDEV=$T/netdev MEOW_NET_ROUTE=$T/route MEOW_RESOLV=$T/resolv
MEOW_RFKILL_DIR=$RF MEOW_BT_DIR=$BT MEOW_BOOT_MODE=$T/boot_mode MEOW_BOOTTS_CACHE=$T/bootts
MEOW_IP=$T/ip MEOW_WPA_CLI=$T/wpa_cli MEOW_HCICONFIG=$T/hciconfig MEOW_BLUETOOTHCTL=$T/bluetoothctl
MEOW_HCITOOL=$T/hcitool MEOW_BLUEALSA_CLI=$T/bluealsa-cli MEOW_BT_SCAN_CACHE=$T/bt_scan.txt
MEOW_NET_SOCK=$T/net.sock MEOW_NET_POLL_SEC=1 MEOW_LOG_DIR=$T/logs
MEOW_TCP=$T/tcp MEOW_UDP=$T/udp MEOW_NET_POLICY=$T/policy
MEOW_AMS_SOCK=$T/no_ams MEOW_SVCD_SOCK=$T/no_svcd MEOW_DNS_DISABLE=1"
ln -sf "$(readlink -f "$BIN")" "$T/meow_net" # argv[0] 双形态 → CLI
# ---- T0: 守护起 ----
env $ENVS $Q "$BIN" --sock "$T/net.sock" >"$T/daemon.log" 2>&1 &
DPID=$!
for i in $(seq 1 30); do [ -S "$T/net.sock" ] && break; sleep 0.2; done
[ -S "$T/net.sock" ] || { echo "FAIL T0: daemon socket 未出现"; cat "$T/daemon.log"; exit 1; }
PASS=$((PASS+1)); echo "PASS T0 daemon up"
# ---- T1: status(读级,任意调用者)----
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
ck T1a "mode=meow src=daemon" "$OUT"
ck T1b "iface:lo kind=lo up=true" "$OUT"
ck T1c "iface:wlan0 kind=wifi up=true" "$OUT"
ck T1d "ip=10.78.193.50" "$OUT" # 若 iface 行 ip 解析成功(ip 桩已修)——实际由 wlan gw 行给,见下
ck T1e "gw=10.194.61.111" "$OUT"
ck T1f "wifi connected=1 state=COMPLETED ssid=MyWiFi" "$OUT"
ck T1g "bt available=1 powered=1 address=00:1A:7D:DA:71:13 paired=2" "$OUT"
ck T1h "rfkill:wlan soft=0 hard=0" "$OUT"
ck T1i "rfkill:bluetooth soft=1 hard=0" "$OUT"
# ---- T2: iface 单/全 ----
OUT=$(env $ENVS $Q "$T/meow_net" iface wlan0 2>&1)
ck T2a '"name":"wlan0"' "$OUT"
ck T2b '"kind":"wifi"' "$OUT"
ck T2c '"ip":"10.78.193.50"' "$OUT"
OUT=$(env $ENVS $Q "$T/meow_net" iface 2>&1)
ck T2d '"name":"lo"' "$OUT"
# ---- T3: wifi networks(读级)----
OUT=$(env $ENVS $Q "$T/meow_net" wifi networks 2>&1)
ck T3a "MyWiFi" "$OUT"
# ---- T4: wifi scan(写级;宿主 CLI=CALL_OTHER → 拒)----
OUT=$(env $ENVS $Q "$T/meow_net" wifi scan 2>&1)
ck T4a "permission denied" "$OUT"
# ---- T5: bt status / bt paired(读级)----
OUT=$(env $ENVS $Q "$T/meow_net" bt status 2>&1)
ck T5a "available=1 powered=1" "$OUT"
ck T5b "paired=2" "$OUT"
ck T5b2 "connected=2" "$OUT" # P1:内核 ACL 权威已连接数
OUT=$(env $ENVS $Q "$T/meow_net" bt paired 2>&1)
ck T5c "My Headset" "$OUT"
ck T5d "Speaker" "$OUT"
# ---- T5e: bt connected(P1:内核 ACL 权威,名经 devices 缓存兜底)----
OUT=$(env $ENVS $Q "$T/meow_net" bt connected 2>&1)
ck T5e "Device 33:DE:2E:21:AD:30 Pudding" "$OUT"
ck T5e2 "Device 11:22:33:44:55:66 Speaker" "$OUT"
# ---- T5f: bt a2dp(P1:bluealsa-cli a2dp list → codec/rate/acquired/role)----
OUT=$(env $ENVS $Q "$T/meow_net" bt a2dp 2>&1)
ck T5f "codec=SBC" "$OUT"
ck T5f2 "rate=44100" "$OUT"
ck T5f3 "acquired=1" "$OUT"
ck T5f4 "role=src" "$OUT"
# ---- T5g: bt devices(P1:netmgrd 权威扫描缓存)----
cat > "$T/bt_scan.txt" <<'EOF'
[NEW] Device 33:DE:2E:21:AD:30 Pudding
[NEW] Device AA:BB:CC:DD:EE:FF Earbuds
[DEL] Device 00:11:22:33:44:55
EOF
OUT=$(env $ENVS $Q "$T/meow_net" bt devices 2>&1)
ck T5g "Device 33:DE:2E:21:AD:30 Pudding" "$OUT"
ck T5g2 "Device AA:BB:CC:DD:EE:FF Earbuds" "$OUT"
# ---- T5h: bt 写级(connect/pair 等)在宿主 CLI=CALL_OTHER → 拒(仅系统身份+MeowOS 放行,见 T6)----
OUT=$(env $ENVS $Q "$T/meow_net" bt connect 33:DE:2E:21:AD:30 2>&1); RC=$?
ck T5h "permission denied" "$OUT"
ck T5h2 "rc=1" "rc=$RC"
OUT=$(env $ENVS $Q "$T/meow_net" bt scan on 2>&1)
ck T5i "permission denied" "$OUT"
# ---- T6: HibyOS 只读降级(读可查,写拒)----
echo hiby > "$T/boot_mode"
sleep 2 # 等守护下一拍热切换
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
ck T6a "mode=readonly" "$OUT"
ck T6b "iface:wlan0" "$OUT" # 读侧仍可查
OUT=$(env $ENVS $Q "$T/meow_net" wifi networks 2>&1)
ck T6c "MyWiFi" "$OUT" # 读级子命令仍可用
OUT=$(env $ENVS $Q "$T/meow_net" wifi on 2>&1); RC=$?
ck T6d "permission denied" "$OUT"
echo meow > "$T/boot_mode"
sleep 2
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
ck T6e "mode=meow" "$OUT" # 热切换回全功能
# ---- T7: 守护日志(每次开机新文件;接口 add/写拒绝 必记)----
sleep 1
LOGS=$(ls "$T/logs"/net_*.log 2>/dev/null | head -1)
[ -n "$LOGS" ] && { PASS=$((PASS+1)); echo "PASS T7a log file: $(basename "$LOGS")"; } || { FAIL=$((FAIL+1)); echo "FAIL T7a 无日志文件"; }
[ -n "$LOGS" ] && { grep -q "iface add kind=wifi name=wlan0" "$LOGS" && { PASS=$((PASS+1)); echo "PASS T7b iface add 已记"; } || { FAIL=$((FAIL+1)); echo "FAIL T7b 未记 iface add"; }; }
# ---- T8: 守护停 → CLI help 本地可用;status 报守护不可达 ----
kill $DPID 2>/dev/null; wait $DPID 2>/dev/null; DPID=""
sleep 0.5
OUT=$(env $ENVS $Q "$T/meow_net" help 2>&1)
ck T8a "usage: meow_net" "$OUT"
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
ck T8b "守护不可达" "$OUT"
# ---- T9: 无参 → help;未知子命令 → usage ----
OUT=$(env $ENVS $Q "$T/meow_net" 2>&1)
ck T9a "usage: meow_net" "$OUT"
OUT=$(env $ENVS $Q "$T/meow_net" bogus 2>&1); RC=$?
ck T9b "usage: meow_net" "$OUT"
# ---- 重启 daemon A(T8 已停)供期2 观测/连接表/日志测试 ----
env $ENVS $Q "$BIN" --sock "$T/net.sock" >"$T/daemon2.log" 2>&1 &
DPID=$!
for i in $(seq 1 30); do [ -S "$T/net.sock" ] && break; sleep 0.2; done
[ -S "$T/net.sock" ] || { echo "FAIL T10-pre: daemon 未重启"; cat "$T/daemon2.log"; exit 1; }
# ---- T10: 期2 conns(读级;观测层经 MEOW_TCP/UDP 桩 + amsd/svcd 缺省 → proc:unknown 归因)----
sleep 1 # 等守护普查一拍
OUT=$(env $ENVS $Q "$T/meow_net" conns 2>&1)
ck T10a "proc:unknown" "$OUT"
ck T10b "10.78.193.50:20791" "$OUT"
ck T10b2 "140.205.5.9:443" "$OUT"
ck T10c "ESTAB" "$OUT"
ck T10d "UDP" "$OUT"
ck T10e "connection" "$OUT"
# ---- T11: apps(实体聚合)----
OUT=$(env $ENVS $Q "$T/meow_net" apps 2>&1)
ck T11a "entity" "$OUT"
ck T11b "proc:unknown" "$OUT"
# ---- T12: dns status/stats(DNS 禁用 → 显示 disabled)----
OUT=$(env $ENVS $Q "$T/meow_net" dns status 2>&1)
ck T12a "proxy disabled" "$OUT"
OUT=$(env $ENVS $Q "$T/meow_net" dns stats 2>&1)
ck T12b "proxy disabled" "$OUT"
# ---- T13: dns flush(写级;宿主 CLI=CALL_OTHER → 拒)----
OUT=$(env $ENVS $Q "$T/meow_net" dns flush 2>&1)
ck T13a "permission denied" "$OUT"
# ---- T13b: 端到端 JSON 合法性(STATUS_0xE0 / IFACE_0xE2 可被完整解析,括号配对/无尾逗号)----
JOUT=$(python3 - "$T/net.sock" <<'PYEOF'
import socket,struct,sys,json
s=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM); s.connect(sys.argv[1]); s.settimeout(2)
def recvn(n):
d=b""
while len(d)<n:
c=s.recv(n-len(d))
if not c: return d
d+=c
return d
def req(typ,payload=b""):
s.sendall(struct.pack('<IHHII',0x4D4F5701,1,typ,1,len(payload))+payload)
H=struct.unpack('<IHHII', recvn(16)); body=recvn(H[4])
code,jlen=struct.unpack('<IH',body[:6]); return body[8:8+jlen].decode('utf-8','replace')
ok=1
for nm,typ,pl in [("STATUS",0x00E0,b""),("IFACE_ALL",0x00E2,b"\x00"*32),("IFACE_WLAN",0x00E2,b"wlan0"+b"\x00"*27)]:
js=req(typ,pl)
try:
json.loads(js); sys.stdout.write("%s VALID\n" % nm)
except Exception as e:
sys.stdout.write("%s INVALID %s\n" % (nm,e))
PYEOF
)
ck T13b "STATUS VALID" "$JOUT"
ck T13c "IFACE_ALL VALID" "$JOUT"
ck T13d "IFACE_WLAN VALID" "$JOUT"
echo "$JOUT" | grep -q "INVALID" && { FAIL=$((FAIL+1)); echo "FAIL T13e 存在无效 JSON"; } || { PASS=$((PASS+1)); echo "PASS T13e no INVALID"; }
# ---- T15: apps 无原始端点(tcp 桩含 inode=0 未归因 → proc:unknown,绝不落成 IP:port entity)----
OUT=$(env $ENVS $Q "$T/meow_net" conns 2>&1)
ck T15a "10.78.195.50:443" "$OUT" # inode=0 的连接仍在表中
OUT=$(env $ENVS $Q "$T/meow_net" apps 2>&1)
ck T15b "proc:unknown" "$OUT"
echo "$OUT" | grep -qE '^[0-9][0-9.]*:' && { FAIL=$((FAIL+1)); echo "FAIL T15c apps 出现原始端点行"; } || { PASS=$((PASS+1)); echo "PASS T15c no raw endpoint row"; }
# ---- T16: policy(读级 show 任意调用者;写级仅系统身份 → 宿主 CLI=CALL_OTHER 拒)----
OUT=$(env $ENVS $Q "$T/meow_net" policy show 2>&1)
ck T16a "app:dev.player.ncm" "$OUT"
ck T16b "domain=" "$OUT"
OUT=$(env $ENVS $Q "$T/meow_net" policy set app:dev.player.ncm allow 2>&1); RC=$?
ck T16c "permission denied" "$OUT"
[ $RC -eq 1 ] && { PASS=$((PASS+1)); echo "PASS T16d rc=1"; } || { FAIL=$((FAIL+1)); echo "FAIL T16d rc=$RC"; }
OUT=$(env $ENVS $Q "$T/meow_net" policy domain app:dev.player.ncm +x 2>&1)
ck T16e "permission denied" "$OUT"
OUT=$(env $ENVS $Q "$T/meow_net" policy del app:dev.player.ncm 2>&1)
ck T16f "permission denied" "$OUT"
# ---- T17: SDK 自愿通道 end-to-end(meow_net_policy_check/report 对守护 A)----
SDK_BIN="$T/test_net_ipc"
if [ -n "$Q" ]; then
"$HOME/Project/R3ProII/.tools/zig-mipsel-cc" -Os -Wall -Wextra -I../sdk -I../sdk/include -I../meow_launcherd \
../sdk/test_net_ipc.c ../sdk/meow_net_ipc.c -o "$SDK_BIN" 2>/dev/null
else
cc -Os -Wall -Wextra -I../sdk -I../sdk/include -I../meow_launcherd \
../sdk/test_net_ipc.c ../sdk/meow_net_ipc.c -o "$SDK_BIN" 2>/dev/null
fi
if [ -x "$SDK_BIN" ]; then
OUT=$(env MEOW_LOG_APP=dev.player.ncm MEOW_NET_SOCK="$T/net.sock" $Q "$SDK_BIN" 2>&1)
ck T17a "CHECK_GOOD=0" "$OUT" # music.163.com 放行
ck T17b "CHECK_BLOCK=1" "$OUT" # ads.example.com 被策略 deny → block
ck T17c "REPORT_DONE" "$OUT"
else
FAIL=$((FAIL+1)); echo "FAIL T17 SDK test 构建失败"
fi
# ---- T18: SDK report → status JSON entity_bytes 回读 ----
JOUT2=$(python3 - "$T/net.sock" <<'PYEOF'
import socket,struct,sys,json
s=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM); s.connect(sys.argv[1]); s.settimeout(2)
def recvn(n):
d=b""
while len(d)<n:
c=s.recv(n-len(d))
if not c: return d
d+=c
return d
s.sendall(struct.pack('<IHHII',0x4D4F5701,1,0x00E0,1,0))
H=struct.unpack('<IHHII', recvn(16)); body=recvn(H[4])
code,jlen=struct.unpack('<IH',body[:6]); js=body[8:8+jlen].decode('utf-8','replace')
o=json.loads(js)
eb=o.get("entity_bytes") or []
hit=[e for e in eb if e["entity"]=="app:dev.player.ncm"]
sys.stdout.write("EB_HIT=%d RX=%d TX=%d\n" % (len(hit), hit[0]["rx"] if hit else -1, hit[0]["tx"] if hit else -1))
PYEOF
)
ck T18a "EB_HIT=1" "$JOUT2"
ck T18b "RX=12345" "$JOUT2"
ck T18c "TX=67890" "$JOUT2"
# ---- RSSI 回读:status wifi rssi 应 >=0(signal_poll 桩已给)----
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
ck T18d "rssi=-45" "$OUT"
# ---- T14: DNS 代理 wire 实测(守护 B:高端口 + 桩上游 + 全局 deny;测 deny/forward/cache)----
HOSTIP=$(hostname -I 2>/dev/null | awk '{print $1}')
[ -n "$HOSTIP" ] || HOSTIP="127.0.0.1"
cat > "$T/policy_dns" <<'EOF'
global domain=-ads.example.com dns.filter_aaaa=1
EOF
printf 'nameserver %s\n' "$HOSTIP" > "$T/resolv_dns"
cat > "$T/dns_test.py" <<'PYEOF'
import socket, struct, threading, sys, os
UP_IP = os.environ.get("T_UP_IP", "0.0.0.0")
up = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
up.bind((UP_IP, 5311)) # 0.0.0.0 通配,绑到宿主自身 IP
up.settimeout(6)
def serve():
try:
while True:
d,a = up.recvfrom(1536)
off=12
while d[off]!=0: off += 1+d[off]
off += 1+4
qsec = d[12:off]
resp = d[:2] + b'\x81\x80' + b'\x00\x01\x00\x01\x00\x00\x00\x00' + qsec
resp += b'\xc0\x0c' + b'\x00\x01\x00\x01' + struct.pack('>I',60) + b'\x00\x04' + socket.inet_aton('11.22.33.44')
up.sendto(resp, a)
except Exception:
pass
threading.Thread(target=serve, daemon=True).start()
def query(name, qtype=1):
s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.settimeout(3)
hdr=b'\x12\x34'+b'\x01\x00'+b'\x00\x01\x00\x00\x00\x00\x00\x00'
q=b''.join(bytes([len(l)])+l.encode() for l in name.split('.'))+b'\x00'+struct.pack('>HH',qtype,1)
s.sendto(hdr+q, ("127.0.0.1", 5300))
r,_=s.recvfrom(1536); rco=r[3]&0xf; an=struct.unpack('>H',r[6:8])[0]
return rco,an
try:
d1,a1 = query("ads.example.com") # deny → NXDOMAIN (rcode 3)
d2,a2 = query("music.163.com") # allow → forward → A 11.22.33.44
da,aa = query("music.163.com", 28) # AAAA + dns.filter_aaaa=1 → 空应答(回落 A)
sys.stdout.write("DENY_RCODE=%d\nALLOW_AN=%d\nAAAA_RCODE=%d AAAA_AN=%d\n" % (d1, a2, da, aa))
except Exception as e:
sys.stdout.write("ERR=%s\n" % e)
PYEOF
# 追加式覆写(env 左→右,后者胜出):DNS 启用、换独立 socket/resolv/policy、上游端口。
DNSENV="$ENVS MEOW_DNS_DISABLE=0 MEOW_NET_SOCK=$T/dns.sock MEOW_RESOLV=$T/resolv_dns
MEOW_NET_POLICY=$T/policy_dns MEOW_DNS_PORT=5300 MEOW_DNS_UPSTREAM_PORT=5311"
ln -sf "$(readlink -f "$BIN")" "$T/dns_netmgrd"
env $DNSENV $Q "$BIN" --sock "$T/dns.sock" >"$T/dnsd.log" 2>&1 &
D2PID=$!
for i in $(seq 1 30); do [ -S "$T/dns.sock" ] && break; sleep 0.2; done
sleep 1
OUT=$(env $DNSENV $Q "$T/meow_net" dns status 2>&1)
ck T14a "enabled=1 upstream=$HOSTIP" "$OUT"
WIRE=$(python3 "$T/dns_test.py" 2>&1)
ck T14b "DENY_RCODE=3" "$WIRE"
ck T14c "ALLOW_AN=1" "$WIRE"
ck T14c2 "AAAA_RCODE=0" "$WIRE" # 期4 AAAA 过滤:rcode 0
ck T14c3 "AAAA_AN=0" "$WIRE" # 且 0 条应答(回落 A)
OUT=$(env $DNSENV $Q "$T/meow_net" dns stats 2>&1)
ck T14d "q=3" "$OUT" # deny + allow + AAAA = 3 查询
ck T14e "deny=1" "$OUT"
kill $D2PID 2>/dev/null; wait $D2PID 2>/dev/null
# 恢复守护 A 的 MEOW_RESOLV(其未被 DNS 触碰,此处确认)
grep -q "nameserver 223.5.5.5" "$T/resolv" && { PASS=$((PASS+1)); echo "PASS T14f daemonA resolv untouched"; } || { FAIL=$((FAIL+1)); echo "FAIL T14f daemonA resolv touched"; }
# ---- T19: WiFi connect 状态机/持久化/隐藏网络/中文 SSID(宿主桩直驱 wifi_connect_ex)----
# daemon IPC 写级需系统身份(SO_PEERCRED /proc/exe),宿主 CLI=CALL_OTHER 必拒;故用 #include
# meow_netmgrd.c 的独立宿主二进制直驱 static wifi_connect_ex,桩 wpa_cli 由二进制自建。
if [ -z "$Q" ]; then
WCON="$T/test_wifi_connect"
if cc -Os -Wall -Wextra -Wno-format-truncation -I../meow_launcherd \
test_wifi_connect.c -o "$WCON" >/dev/null 2>&1; then
if "$WCON" >"$T/wcon.out" 2>/dev/null && grep -q "FAIL=0" "$T/wcon.out"; then
PASS=$((PASS+1)); echo "PASS T19 wifi-connect host (12 asserts, FAIL=0)"
else
FAIL=$((FAIL+1)); echo "FAIL T19 wifi-connect host"; cat "$T/wcon.out"
fi
else
FAIL=$((FAIL+1)); echo "FAIL T19 wifi-connect host build"
fi
else
echo "SKIP T19 wifi-connect(qemu 下 fork/exec 宿主 /bin/sh 不便,宿主已覆盖)"
fi
echo "=============================="
echo "PASS=$PASS FAIL=$FAIL"
[ $FAIL -eq 0 ]