用户原话:「开关都存在显示问题 我都不能判断它是不是真的开启还是关闭(包括 WiFi 页也是)」。
根因不是「没读到硬件态」,而是「读到/没读到都被拿去当用户意图的装饰」:
- bt_page.c:103 开关初值来自 settings 布尔;:112-114 下发后立刻 g_sys.bt_on = on(显示意图);
:129 c->bt_on = nm_bt_powered() 赋值后全文无人引用(M45 也独立发现)。
- wifi_page.c:40 读不到 settings 时默认 1(显示已开)。
- netmgrd 的 bt/wifi 查询本身把「问不到」塌缩成 0(nm_bt_powered/nm_wifi_connected)。
本单只解「状态可信」,不碰扫描/配对/音频(另有 M45/M46 单)。
1) 真实态三态(-1 未知 / 0 关 / 1 开)
- net.c 新增 net_bt_power_probe()(hciconfig hci0 UP/DOWN;无输出=未知)与
net_wifi_power_probe()(rfkill wlan soft/hard 汇总,回退 wlan0 IFF_UP;读不到=未知)。
- netmgr_ipc.c 新增 nm_bt_power_state()(daemon bt status 的 available/powered 权威,不可达
回退直连探测)与 nm_wifi_power_state()(netmgrd 的 wifi status 只有 wpa_state、不报射频态,
故取本地 rfkill——daemon 的 wifi on/off 改的就是同一份内核状态)。
- 两个子页的 top_sw/rows 只读这两个函数;settings 布尔降级为「意图持久化」,不再决定外观。
- 「读不到默认 1」删除:未知就是未知。
2) 点击 → 待确认 → 真实态定稿
- 纯函数 meow_toggle_{display,pending,rollback,error}(bt_page.c,无 I/O/UI):
只有 probe 确认才算收敛;probe 未知继续等,绝不因 last_real 恰好等于意图就宣布成功。
- 页面:落盘意图 → 下发 → 250ms 轮询(BT 上限 4s、WiFi 上限 5s;hciconfig 0.3~2s、
wifi_up.sh 起 supplicant/DHCP 更慢,故不用 20ms 级忙轮询)→ 真实态定稿;失败/超时把
settings 回滚到已确认真实态 + s_dd_modal 可见报错,不静默、不乐观。
- subpage.c:切换前先画「正在开启/关闭…(等待设备确认)」条(待确认态与稳定态可区分);
切换后回读 top_sw 定稿(取消原「点了就翻面」),live tick 也回读,外部改动驻留期间可见。
3) 第三态呈现(未知 ≠ 已关)
- SDK meow_switch 只有两态:未知时开关停「关」并在左侧画灰色「?」;行内另有
「蓝牙状态未知 / WiFi 开关状态未知」文字说明。选「?」是因为它不占用开关控件本身、
且「关+?」不会被读成「已关」。
4) 顺带修 net.c 三条开关失真(塔追加的 M45 盘点,同一病根)
- s_net_toggle_bt() 补 rfkill soft(与 netmgrd 的 bt on/off 同一语义;开:先 unblock 再 up;
关:先 down 再 block)。此前只发 hciconfig → 「BT 页关过再从头开」会被 rfkill 拦下。
- s_net_sync_from_sys() WiFi 判据从 wlan_connected()(已关联)改为射频态;BT 用三态,
读不到不写(旧写法把「网卡 up 未关联」写成 0,把未知写成已关)。
- rfkill 同类多节点(本机 2 wlan + 2 bluetooth)按「任一 block 即 block」读、全部写入。
测试(`bash patch_v2/meow_launcherd/build_launcher.sh test`,新增 test 入口)
- test_bt_page.c:P4 三态与未知占位、P5 收敛四例(达成/下发失败/超时/未知)、P6 收敛矩阵
12 组(真实开/关 × 下发成功/失败/超时 × probe 未知),全 PASS(64 条断言)。
- test_netmgr_ipc.c:新增 nm_bt_power_state 解析(powered=1/0、available=0、缺字段→-1)、
nm_wifi_power_state 透传、不可达回退=未知、wifi_rows 未知态占位;并修掉两处既有测试缺陷
(行内 UI 桩缺失导致本文件此前根本链不过;直连连接桩统一返回 "0\n" 导致等满 10s 必失败)。
- 交叉编译 0 warning(-Wall -Wextra,逐文件单独编 + 整链);launcherd 899388 B
md5 1c88661a9410ac1a4139304362281cdd,同 commit 同步 scripts/build/fw_content.conf 钉值。
真机(10.58.215.50,仅只读自检,未替换 /usr/bin/meow_launcherd、未刷机)
- 二进制放 /usr/data/mnt/sd_0/MeowOS/tmp/ 跑 --sysdump:exit 0,输出 wifi_on=1 / bt_seen=1
bt_on=0,与设备现状一致(rfkill 全 0 + wlan0 up + hci0 DOWN + netmgrd powered=0)。
- 卡上 du -s /usr/data/mnt/sd_0/Music 前后恒 199164544;临时文件已删;settings 未改。
- launcherd 在 squashfs 里 → 本改动需刷机生效。
已知不在本单:输出目标只写 settings(audiod 仅启动读一次)→ M45 finding / M46;
netmgrd 侧四处失真(未知当关、up 与 unblock 顺序、rfkill 只写首节点、wifi status 无射频字段)
已报 finding;设置主页/通知中心的开关显示仍是 settings(另立单)。
336 lines
17 KiB
C
336 lines
17 KiB
C
/* test_netmgr_ipc.c — M6.0 宿主桩测试:设置页 netmgr IPC 客户端 / WiFi 新网络录入逻辑。
|
||
*
|
||
* 假 socket 帧:本测试起一个 AF_UNIX 服务器线程,按 Meow IPC 帧(16B 头 + 负载)应答
|
||
* MSG_HELLO→ACK、MSG_NET_WIFI_CTL/BT_CTL→*_RESULT(netmgrd 同构),让 launcher 侧
|
||
* netmgr_ipc.c(netmgr_wifi / nm_wifi_* 系列 / netmgr_ok)与 wifi_page.c(wifi_rows)跑真实数据。
|
||
*
|
||
* 覆盖(打桩帧):
|
||
* ① 扫描列表渲染:netmgrd 返回 scan_results → nm_wifi_scan / wifi_rows 解析出 SSID/mac/sec,
|
||
* 加密网络 sec=WPA-PSK、开放网络 sec=Open;
|
||
* ② 连接成功/失败两态:connect 子命令 MEOW_OK / MEOW_ERR_NODEV → nm_wifi_connect 返回值+错误文本;
|
||
* ③ 降级占位:MEOW_NET_SOCK 指向不存在路径 → netmgr_ok()==0、netmgr_wifi=NETMGR_UNREACH、
|
||
* nm_wifi_scan 回退直连(桩返回 0 不崩),且 wifi_rows 渲染「网络管理服务未运行(直连模式)」占位。
|
||
*
|
||
* 编译(链 netmgr_ipc.o;net.c 回退函数/UI 用桩替代,同 test_media.c 惯例):
|
||
* gcc -I../sdk -I. -Wall -Wextra -c netmgr_ipc.c -o netmgr_ipc.test.o
|
||
* gcc -I../sdk -I. -Wall -Wextra test_netmgr_ipc.c netmgr_ipc.test.o -lpthread -o test_netmgr_ipc
|
||
*/
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <stdarg.h>
|
||
#include <unistd.h>
|
||
#include <errno.h>
|
||
#include <pthread.h>
|
||
#include <sys/socket.h>
|
||
#include <sys/un.h>
|
||
#include <assert.h>
|
||
|
||
#include "meow_launcher_internal.h" /* meow_net_t / S_NET_MAX / nm_* / sub_page_t etc. */
|
||
#include "wifi_page.c" /* 把静态 wifi_ctx_t/wifi_rows 平移进本 TU(沿用既有模式) */
|
||
|
||
/* ---------- net.c 直连回退路径桩(netmgrd 不可达时走这里;宿主无 wpa_cli/bluetoothctl) ---------- */
|
||
int wlan_connected(void) { return 0; }
|
||
int net_wifi_saved(meow_net_t *out, int max) { (void)out; (void)max; return 0; }
|
||
int net_wifi_scan(meow_net_t *out, int max) { (void)out; (void)max; return 0; }
|
||
void net_wifi_ssid(char *buf, int len) { (void)len; buf[0] = 0; }
|
||
int net_wifi_info(char (*info)[48], int max) { (void)info; (void)max; return 0; }
|
||
int hci_powered(void) { return 0; }
|
||
int net_bt_paired(meow_net_t *out, int max) { (void)out; (void)max; return 0; }
|
||
void s_net_toggle_wifi(int on) { (void)on; }
|
||
void s_net_toggle_bt(int on) { (void)on; }
|
||
void net_wifi_scan_trigger(void) {}
|
||
int net_bt_connected(meow_net_t *out, int max) { (void)out; (void)max; return 0; }
|
||
int net_bt_scan(meow_net_t *out, int max) { (void)out; (void)max; return 0; }
|
||
void net_bt_scan_trigger(void) {}
|
||
|
||
/* UI 桩:wifi_connecting_banner 走 SDK 绘制函数;宿主无 fb,空实现即可(不验证像素)。 */
|
||
const meow_ui_theme_t *s_ui_theme(void) { static meow_ui_theme_t th; return &th; }
|
||
int meow_ui_width(void) { return 480; }
|
||
void meow_ui_fill_rect(int x, int y, int w, int h, uint32_t color)
|
||
{ (void)x; (void)y; (void)w; (void)h; (void)color; }
|
||
void meow_ui_text_center(int cx, int y, const char *utf8, int size, uint32_t color)
|
||
{ (void)cx; (void)y; (void)utf8; (void)size; (void)color; }
|
||
int meow_ui_text_height(int size) { return size; }
|
||
void meow_dirty_full(void) {}
|
||
void meow_ui_flush(void) {}
|
||
char *popen_read_tmo(int tmo_ms, const char *cmd)
|
||
{
|
||
(void)tmo_ms;
|
||
/* 直连回退(不可达分支)会跑 wpa_cli 剧本:list_networks/add_network/status/save_config。
|
||
* 桩按子命令给近似真机的应答——旧桩统一返回 "0\n",会让 nm_direct_connect_ex 等满 10s
|
||
* 再报 MEOW_ERR_NODEV(该断言因此长期失败;M47 顺手把桩修成可收敛)。 */
|
||
if (strstr(cmd, " status")) return strdup("wpa_state=COMPLETED\nip_address=192.168.1.5\nssid=Home2G\n");
|
||
if (strstr(cmd, "list_networks")) return strdup("network id / ssid / bssid / flags\n0\tHome2G\t00:11:22:33:44:01\t[WPA-PSK-CCMP]\n");
|
||
return strdup("OK\n");
|
||
}
|
||
|
||
/* ---------- M47:net.c 三态直连探测桩(daemon 不可达时 nm_*_power_state 落到这里) ---------- */
|
||
int nm_bt_power_state(void); /* netmgr_ipc.c(头文件不在本单改动范围) */
|
||
static int g_bt_probe = -1, g_wifi_probe = -1;
|
||
int net_bt_power_probe(void) { return g_bt_probe; }
|
||
int net_wifi_power_probe(void) { return g_wifi_probe; }
|
||
|
||
/* M47:开关收敛判定纯函数的实现放在 bt_page.c,矩阵测试在 test_bt_page.c;本测试只验
|
||
* nm_*_power_state 的解析/回退与 wifi_rows 的未知态渲染,故这里给可链接的最小桩。 */
|
||
int meow_toggle_display(int intent, int last, int ok, int probe, int to)
|
||
{ (void)intent; (void)ok; (void)to; return (probe >= 0) ? probe : last; }
|
||
int meow_toggle_pending(int intent, int last, int ok, int probe, int to)
|
||
{ (void)intent; (void)last; (void)ok; (void)probe; (void)to; return 0; }
|
||
int meow_toggle_rollback(int intent, int last, int ok, int probe, int to)
|
||
{ (void)intent; (void)last; (void)ok; (void)probe; (void)to; return 0; }
|
||
int meow_toggle_error(int intent, int last, int ok, int probe, int to)
|
||
{ (void)intent; (void)last; (void)ok; (void)probe; (void)to; return 0; }
|
||
|
||
/* ---------- launcher/UI/IME 桩(wifi_page.c 链接所需;测试不触碰这些路径) ---------- */
|
||
static unsigned long long g_test_ms = 0;
|
||
int meow_settings_get_bool(const char *k, int *v) { (void)k; if (v) *v = 1; return 1; }
|
||
int meow_settings_set_bool(const char *k, int v) { (void)k; (void)v; return 0; }
|
||
int meow_settings_save(void) { return 0; }
|
||
void paint_sb_right(void) {}
|
||
void logmsg(const char *fmt, ...) { (void)fmt; }
|
||
unsigned long long now_ms(void) { return ++g_test_ms; }
|
||
void bt_role_refresh(int force) { (void)force; }
|
||
meow_sys_state g_sys; /* extern meow_sys_state g_sys */
|
||
int s_dd_modal(const char *title, const char *item[S_NET_MAX], int n, int cur)
|
||
{ (void)title; (void)item; (void)n; (void)cur; return -1; }
|
||
int meow_subpage_run(sub_page_t *p) { (void)p; return 0; }
|
||
int meow_ui_text_input(meow_ime_ctx *ctx) { (void)ctx; return 0; } /* 取消:不进 IME 路径 */
|
||
|
||
/* ---------- 假 netmgrd 服务器 ---------- */
|
||
typedef struct {
|
||
int lfd;
|
||
int fail_connect; /* 1=connect 返回 MEOW_ERR_NODEV */
|
||
const char *scan_text;
|
||
const char *networks_text;
|
||
const char *status_text;
|
||
const char *bt_status_text;
|
||
const char *bt_paired_text;
|
||
} fake_net_t;
|
||
|
||
static int rw_all(int fd, uint8_t *b, size_t n)
|
||
{ size_t o = 0; while (o < n) { ssize_t r = read(fd, b + o, n - o); if (r <= 0) return -1; o += (size_t)r; } return 0; }
|
||
static int wr_all(int fd, const uint8_t *b, size_t n)
|
||
{ size_t o = 0; while (o < n) { ssize_t r = write(fd, b + o, n - o); if (r <= 0) return -1; o += (size_t)r; } return 0; }
|
||
|
||
static void fk_send(int fd, uint16_t type, uint32_t req, const void *pl, uint32_t len)
|
||
{
|
||
uint8_t hdr[MEOW_IPC_HDR_LEN];
|
||
uint32_t magic = MEOW_IPC_MAGIC, rlen = len;
|
||
uint16_t ver = MEOW_IPC_VERSION, t = type;
|
||
memcpy(hdr + 0, &magic, 4); memcpy(hdr + 4, &ver, 2); memcpy(hdr + 6, &t, 2);
|
||
memcpy(hdr + 8, &req, 4); memcpy(hdr + 12, &rlen, 4);
|
||
if (wr_all(fd, hdr, sizeof hdr) < 0) return;
|
||
if (len && pl) wr_all(fd, pl, len);
|
||
}
|
||
static void fk_result(int fd, uint16_t type, uint32_t req, uint32_t code, const char *txt)
|
||
{
|
||
m_net_cmd_result_t r;
|
||
memset(&r, 0, sizeof r);
|
||
r.code = code;
|
||
size_t pl = txt ? strlen(txt) : 0;
|
||
if (pl > sizeof r.text - 1) pl = sizeof r.text - 1;
|
||
r.text_len = (uint16_t)pl;
|
||
memcpy(r.text, txt, pl);
|
||
r.text[pl] = 0;
|
||
fk_send(fd, type, req, &r, (uint32_t)(8 + pl + 1));
|
||
}
|
||
|
||
static void fk_handle(int c, fake_net_t *f)
|
||
{
|
||
for (;;) {
|
||
uint8_t hdr[MEOW_IPC_HDR_LEN];
|
||
if (rw_all(c, hdr, sizeof hdr) < 0) return;
|
||
uint32_t magic, rlen, req; uint16_t ver, type;
|
||
memcpy(&magic, hdr, 4); memcpy(&ver, hdr + 4, 2); memcpy(&type, hdr + 6, 2);
|
||
memcpy(&req, hdr + 8, 4); memcpy(&rlen, hdr + 12, 4);
|
||
if (magic != MEOW_IPC_MAGIC || ver != MEOW_IPC_VERSION) return;
|
||
uint8_t pl[MEOW_IPC_MAX];
|
||
if (rlen) { if (rlen > sizeof pl) rlen = sizeof pl; if (rw_all(c, pl, rlen) < 0) return; }
|
||
if (type == MSG_HELLO) {
|
||
m_ack_t a; memset(&a, 0, sizeof a); a.code = MEOW_OK;
|
||
fk_send(c, MSG_ACK, req, &a, sizeof a);
|
||
continue;
|
||
}
|
||
m_net_cmd_t q; memset(&q, 0, sizeof q);
|
||
if (rlen > sizeof q) rlen = sizeof q;
|
||
memcpy(&q, pl, rlen);
|
||
if (type == MSG_NET_WIFI_CTL) {
|
||
if (!strcmp(q.cmd, "scan")) fk_result(c, MSG_NET_WIFI_RESULT, req, MEOW_OK, f->scan_text);
|
||
else if (!strcmp(q.cmd, "networks")) fk_result(c, MSG_NET_WIFI_RESULT, req, MEOW_OK, f->networks_text);
|
||
else if (!strcmp(q.cmd, "status")) fk_result(c, MSG_NET_WIFI_RESULT, req, MEOW_OK, f->status_text);
|
||
else if (!strcmp(q.cmd, "connect")) {
|
||
char buf[200];
|
||
if (f->fail_connect) fk_result(c, MSG_NET_WIFI_RESULT, req, MEOW_ERR_NODEV,
|
||
"connect: add_network 失败 (wpa_cli 不可用?)");
|
||
else { snprintf(buf, sizeof buf, "connect: ssid=%s network_id=5 (已 enable+select)", q.arg);
|
||
fk_result(c, MSG_NET_WIFI_RESULT, req, MEOW_OK, buf); }
|
||
}
|
||
else if (!strcmp(q.cmd, "disconnect")) fk_result(c, MSG_NET_WIFI_RESULT, req, MEOW_OK, "wifi disconnect: 已下发");
|
||
else if (!strcmp(q.cmd, "on") || !strcmp(q.cmd, "off")) fk_result(c, MSG_NET_WIFI_RESULT, req, MEOW_OK, "wifi on/off: rfkill wlan done");
|
||
else fk_result(c, MSG_NET_WIFI_RESULT, req, MEOW_ERR_INVAL, "wifi: 未知子命令");
|
||
continue;
|
||
}
|
||
if (type == MSG_NET_BT_CTL) {
|
||
if (!strcmp(q.cmd, "status")) fk_result(c, MSG_NET_BT_RESULT, req, MEOW_OK, f->bt_status_text);
|
||
else if (!strcmp(q.cmd, "paired")) fk_result(c, MSG_NET_BT_RESULT, req, MEOW_OK, f->bt_paired_text);
|
||
else if (!strcmp(q.cmd, "on") || !strcmp(q.cmd, "off")) fk_result(c, MSG_NET_BT_RESULT, req, MEOW_OK, "bt on/off: hci0 done");
|
||
else fk_result(c, MSG_NET_BT_RESULT, req, MEOW_ERR_INVAL, "bt: 未知子命令");
|
||
continue;
|
||
}
|
||
return; /* 未知帧:断开 */
|
||
}
|
||
}
|
||
|
||
static void *fk_server(void *arg)
|
||
{
|
||
fake_net_t *f = arg;
|
||
for (;;) {
|
||
int c = accept(f->lfd, NULL, NULL);
|
||
if (c < 0) return NULL;
|
||
fk_handle(c, f);
|
||
close(c);
|
||
}
|
||
}
|
||
|
||
static int start_server(fake_net_t *f, const char *path)
|
||
{
|
||
f->lfd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||
if (f->lfd < 0) return -1;
|
||
struct sockaddr_un a;
|
||
memset(&a, 0, sizeof a);
|
||
a.sun_family = AF_UNIX;
|
||
strncpy(a.sun_path, path, sizeof a.sun_path - 1);
|
||
unlink(path);
|
||
if (bind(f->lfd, (struct sockaddr *)&a, sizeof a) < 0) return -2;
|
||
if (listen(f->lfd, 5) < 0) return -3;
|
||
pthread_t t;
|
||
return pthread_create(&t, NULL, fk_server, f) == 0 ? 0 : -4;
|
||
}
|
||
|
||
static int row_has_label(const sub_row_t *rows, int n, const char *needle)
|
||
{ for (int i = 0; i < n; i++) if (rows[i].label && strstr(rows[i].label, needle)) return 1; return 0; }
|
||
|
||
int main(void)
|
||
{
|
||
char sock[110];
|
||
/* 宿主 /tmp 可能不可写(Android 上 /tmp 属 shell):优先 TMPDIR。 */
|
||
snprintf(sock, sizeof sock, "%s/meow_net_test_%d.sock",
|
||
getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp", (int)getpid());
|
||
|
||
fake_net_t f;
|
||
memset(&f, 0, sizeof f);
|
||
f.scan_text =
|
||
"bssid / frequency / signal level / flags / ssid\n"
|
||
"00:11:22:33:44:01 2412 -45 [WPA-PSK-CCMP][ESS] Home2G\n"
|
||
"00:11:22:33:44:02 2417 -60 [WPA2-PSK][ESS] Office\n"
|
||
"00:11:22:33:44:03 2442 -70 [ESS] FreeWiFi\n";
|
||
f.networks_text =
|
||
"network id / ssid / bssid / flags\n"
|
||
"0\tHome2G\t00:11:22:33:44:01\t[WPA-PSK-CCMP]\n";
|
||
f.status_text = "wifi state=COMPLETED connected=1 ssid=Home2G ip=192.168.1.5 rssi=-45";
|
||
f.bt_status_text = "bt available=1 powered=1 address=00:1A:7D:DA:71:13 paired=2";
|
||
f.bt_paired_text = "Device 00:1A:7D:DA:71:13 Headphones\nDevice 00:1A:7D:DA:71:14 Speaker\n";
|
||
|
||
if (start_server(&f, sock) != 0) { fprintf(stderr, "fake server start fail\n"); return 1; }
|
||
setenv("MEOW_NET_SOCK", sock, 1);
|
||
|
||
/* ---- ① 扫描列表渲染:nm_wifi_scan 解析(IPsec/开放安全类型) ---- */
|
||
meow_net_t scan[S_NET_MAX];
|
||
int sn = nm_wifi_scan(scan, S_NET_MAX);
|
||
assert(sn >= 2 && "scan: 至少解析 2 条(BSSID 去重后)");
|
||
assert(!strcmp(scan[0].name, "Home2G") && "scan[0].name=Home2G");
|
||
assert(!strcmp(scan[0].sec, "WPA-PSK-CCMP") && "scan[0].sec 加密");
|
||
assert(!strcmp(scan[1].sec, "WPA2-PSK") && "scan[1].sec 加密");
|
||
/* FreeWiFi 无 WPA → Open */
|
||
int open_idx = -1;
|
||
for (int i = 0; i < sn; i++) if (!strcmp(scan[i].name, "FreeWiFi")) open_idx = i;
|
||
assert(open_idx >= 0 && "scan 含 FreeWiFi");
|
||
assert(!strcmp(scan[open_idx].sec, "Open") && "开放网络 sec=Open");
|
||
printf("[A] nm_wifi_scan: %d 条, Home2G/WPA-PSK-CCMP, FreeWiFi/Open PASS\n", sn);
|
||
|
||
/* ---- wifi_rows:附近网络分组渲染(含 SSID/sec 摘要行) ---- */
|
||
{
|
||
wifi_ctx_t c; memset(&c, 0, sizeof c);
|
||
sub_row_t rows[SUB_ROWS_MAX];
|
||
int rn = wifi_rows(&c, rows, SUB_ROWS_MAX);
|
||
assert(row_has_label(rows, rn, "附近网络") && "rows 有「附近网络」分组");
|
||
assert(row_has_label(rows, rn, "Home2G") && "rows 渲染扫描 SSID Home2G");
|
||
assert(row_has_label(rows, rn, "FreeWiFi") && "rows 渲染开放网络 FreeWiFi");
|
||
assert(row_has_label(rows, rn, "已保存网络") && "rows 有「已保存网络」分组");
|
||
assert(!row_has_label(rows, rn, "网络管理服务未运行") && "netmgrd 在 → 无降级占位");
|
||
printf("[B] wifi_rows 渲染: 附近/已保存/扫描SSID 均现, 无降级占位 PASS\n");
|
||
}
|
||
|
||
/* ---- ② 连接成功/失败两态 ---- */
|
||
char err[192]; err[0] = 0;
|
||
f.fail_connect = 0;
|
||
int rc = nm_wifi_connect("Home2G", "pass1234", err, sizeof err);
|
||
assert(rc == MEOW_OK && "connect 成功返回 MEOW_OK");
|
||
assert(strstr(err, "network_id=5") && "connect 成功带回 network_id");
|
||
printf("[C] connect 成功: rc=%d err=%s PASS\n", rc, err);
|
||
|
||
f.fail_connect = 1;
|
||
err[0] = 0;
|
||
rc = nm_wifi_connect("Home2G", "bad", err, sizeof err);
|
||
assert(rc == MEOW_ERR_NODEV && "connect 失败返回 MEOW_ERR_NODEV");
|
||
assert(strstr(err, "add_network") && "connect 失败带回原因");
|
||
printf("[D] connect 失败: rc=%d err=%s PASS\n", rc, err);
|
||
|
||
/* ---- ③ M47:开关真实态三态查询(daemon 权威解析) ---- */
|
||
{
|
||
f.bt_status_text = "bt available=1 powered=1 address=00:1A:7D:DA:71:13 paired=2 connected=0";
|
||
assert(nm_bt_power_state() == 1 && "bt status powered=1 → 1(开)");
|
||
f.bt_status_text = "bt available=1 powered=0 address=00:1A:7D:DA:71:13 paired=2 connected=0";
|
||
assert(nm_bt_power_state() == 0 && "bt status powered=0 → 0(关)");
|
||
f.bt_status_text = "bt available=0 powered=0 address=- paired=-1 connected=-1";
|
||
assert(nm_bt_power_state() == 0 && "无控制器(available=0) → 0");
|
||
f.bt_status_text = "bt available=1 address=00:1A:7D:DA:71:13 paired=-1 connected=-1";
|
||
assert(nm_bt_power_state() == -1 && "缺 powered 字段 → -1(未知,不猜 0)");
|
||
g_wifi_probe = -1;
|
||
assert(nm_wifi_power_state() == -1 && "wifi 探测失败 → -1(不再默认已开)");
|
||
g_wifi_probe = 1;
|
||
assert(nm_wifi_power_state() == 1 && "wifi 探测开 → 1");
|
||
g_wifi_probe = 0;
|
||
assert(nm_wifi_power_state() == 0 && "wifi 探测关 → 0");
|
||
printf("[F] nm_bt_power_state/nm_wifi_power_state 三态解析 PASS\n");
|
||
}
|
||
|
||
/* ---- ④ 降级占位:MEOW_NET_SOCK 指向不存在路径 ----
|
||
* 先发一次 netmgr_wifi(内部强制重连,失败 → 置可达缓存=0),再断言 netmgr_ok()。 */
|
||
setenv("MEOW_NET_SOCK", "/tmp/meow_net_nonexistent_zz.sock", 1);
|
||
assert(netmgr_wifi("status", NULL, err, sizeof err) == NETMGR_UNREACH && "netmgr_wifi=NETMGR_UNREACH");
|
||
assert(netmgr_ok() == 0 && "netmgr_ok()==0(服务不可达)");
|
||
err[0] = 0;
|
||
int dr = nm_wifi_connect("Home2G", "x", err, sizeof err);
|
||
assert(dr == MEOW_OK && "不可达→回退直连(桩返回成功,保功能)");
|
||
int nr = nm_wifi_scan(scan, S_NET_MAX);
|
||
assert(nr == 0 && "不可达→回退直连扫描(桩返回 0,不崩)");
|
||
{
|
||
wifi_ctx_t c; memset(&c, 0, sizeof c);
|
||
sub_row_t rows[SUB_ROWS_MAX];
|
||
int rn = wifi_rows(&c, rows, SUB_ROWS_MAX);
|
||
assert(row_has_label(rows, rn, "网络管理服务未运行(直连模式)") && "降级占位渲染");
|
||
printf("[E] 降级: netmgr_ok=0, UNREACH, 回退不崩, 占位渲染 PASS\n");
|
||
}
|
||
|
||
/* ---- ⑤ M47:daemon 不可达时真实态回退直连探测;探测失败=未知(不当已关/已开) ---- */
|
||
g_bt_probe = -1;
|
||
assert(nm_bt_power_state() == -1 && "BT daemon 不可达 + 直连探测失败 → -1");
|
||
g_bt_probe = 0;
|
||
assert(nm_bt_power_state() == 0 && "BT daemon 不可达 + 直连探测关 → 0");
|
||
g_wifi_probe = -1;
|
||
assert(nm_wifi_power_state() == -1 && "WiFi 探测失败 → -1");
|
||
{
|
||
wifi_ctx_t c; memset(&c, 0, sizeof c);
|
||
sub_row_t rows[SUB_ROWS_MAX];
|
||
int rn = wifi_rows(&c, rows, SUB_ROWS_MAX);
|
||
assert(row_has_label(rows, rn, "WiFi 开关状态未知") && "未知态 → 行内第三态占位");
|
||
printf("[G] 不可达回退三态: BT/WiFi 失败=未知, 行内第三态 PASS\n");
|
||
}
|
||
|
||
printf("ALL PASS\n");
|
||
unlink(sock);
|
||
return 0;
|
||
}
|