mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-26 12:23:23 +00:00
C 化从「一把刀」推进到「可持续推进」,本轮先把基础设施建起来:
不建它,后续每个 C 切片都在裸奔(无告警门禁、无内存安全检查、
无交叉编译验证、无 ABI 漂移检测)。
新增门禁(make check-csrc / check-csrc-full,已接进 make test):
- csrc-lint gcc+clang 双编译器 × -Wall -Wextra -Wpedantic -Wshadow
-Wconversion,零告警才算过(-Wconversion 是为 cgo 窄化
准备的:size_t→int 截断在默认档下是静默的)
- csrc-abi ABI 版本运行期自述 + 荒谬值检查
- csrc-headers 头文件自包含性(每个 .h 能单独编过)
- csrc-sanitize ASan+UBSan 跑 C 契约测试
- csrc-cross arm64 交叉编译(homed 的真实发布目标)
- csrc-fuzz libFuzzer:内存安全 + 6 条不变式(可 CI 门禁)
新增 ABI 契约(csrc/include/ha_abi.h):
- ha_codec.h 声明「签名冻结」,但冻结只写在注释里;现改为
HA_CODEC_ABI_MAJOR/MINOR + 运行期自述 + Go 侧常量,
三方交叉断言,版本漂移在测试期判红而非线上表现为行为诡异。
- 门禁当场抓出我自己的两个真 bug:①_Static_assert 是 C11 而项目
是 -std=c99(-Wpedantic 报的);②##msg 不能拼接字符串字面量,
导致两个断言共用一个 typedef 名(clang 报的)。
基础设施当场抓出的三个真实缺陷(都是「本机 gcc 能编过、别处会炸」类):
- bench 用了 POSIX clock_gettime,而 CMake 刻意 C_EXTENSIONS OFF
(严格 c99)→ 头文件未声明;补 _POSIX_C_SOURCE(须在任何头之前)
- 头文件缺 include 时只在「恰好被别的头先包含」处静默编过
- Go 不允许在 _test.go 用 cgo ⇒ C 侧 const 桥接只能放非测试文件,
且 cgo 生成的 *_Cvar_* 不是 Go 常量(「两边一起错成一样」的盲区,
改用 C 函数返回 + 编译期 _Static_assert 补上)
实测(全部当场可复现):
- 双编译器 × c99/c11 零告警;ASan+UBSan PASS
- libFuzzer 91s 跑 3329316 次、零崩溃(6 条不变式全过)
- 变异测试:改 C 侧宏 / 让 Go 常量与 C 函数「一起错成一样」,
均被对应断言抓住(证明门禁不是摆设)
- C 侧纯函数基准(首次把函数体成本与 cgo 边界成本分开测):
ascii_1k 121.7ns/8.4GB/s;zh_1k 1434ns;truncate 两者均约 128-134ns
- 全量 go test -count=1 ./...:57 包 0 FAIL
- make build-linux-arm64 → ELF aarch64
- 纪律检查 FAIL=0;SDK 公开接口 diff = 0 行
未动:csrc/ 是内核 C ABI,不属 third_party/homeagent-sdk 公开接口。
38 lines
1.4 KiB
Go
38 lines
1.4 KiB
Go
//go:build cgo
|
||
|
||
package api
|
||
|
||
// codec_abimacro_test.go —— 堵住「Go 常量与 C 函数一起错成一样」的盲区。
|
||
//
|
||
// TestABIVersionMatches 比的是「Go 常量 vs C 函数返回值」。若有人同时把
|
||
// Go 常量和 C 函数一起改成 2(而忘了改 ha_abi.h 的宏),那条测试照样通过
|
||
// —— **两边一起错成一样**是它的盲区。本测试直接问 C 侧宏。
|
||
//
|
||
// (C 侧宏的取法在 codec_cgo.go:Go 不允许在 _test.go 里用 cgo,
|
||
// 故 const 桥接只能写在非测试文件。)
|
||
|
||
import "testing"
|
||
|
||
func TestABIMacroMatchesRuntimeAndGo(t *testing.T) {
|
||
macro := codecABIVersionMacroValue()
|
||
runtime := codecABIVersion()
|
||
|
||
if macro != runtime {
|
||
t.Fatalf("C 侧宏与运行期值不一致:\n"+
|
||
" HA_CODEC_ABI_VERSION(宏展开)= %d\n"+
|
||
" ha_codec_abi_version() = %d\n"+
|
||
" 说明:改了 ha_abi.h 的宏但没同步改 ha_codec_abi_version(),或反之。",
|
||
macro, runtime)
|
||
}
|
||
|
||
wantGo := codecABIMajorExpected*1000 + codecABIMinorExpected
|
||
if macro != wantGo {
|
||
t.Fatalf("C 侧宏与 Go 侧常量不一致:\n"+
|
||
" C 宏 HA_CODEC_ABI_VERSION = %d (major=%d minor=%d)\n"+
|
||
" Go 常量期望 = %d (major=%d minor=%d)\n"+
|
||
" 改法:同步更新 ha_abi.h 与 codec_cgo.go 的 codecABIMajor/MinorExpected。",
|
||
macro, macro/1000, macro%1000,
|
||
wantGo, wantGo/1000, wantGo%1000)
|
||
}
|
||
}
|