| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- package main
- // 无头审计: 复用 analyzer 全套审计逻辑 (结构 + 索引内容一致性), 不走 HTTP。
- // 用法: AUDIT_DB=<库文件> AUDIT_OUT=<JSON 输出> go test -run TestHeadlessAudit -v ./analyzer
- // 若被分析库旁边有 <db>.analyzer 缓存且指纹匹配, 会直接命中缓存秒回。
- import (
- "encoding/json"
- "fmt"
- "os"
- "testing"
- "time"
- )
- func TestHeadlessAudit(t *testing.T) {
- p := os.Getenv("AUDIT_DB")
- if p == "" {
- t.Skip("AUDIT_DB 未设置")
- }
- out := os.Getenv("AUDIT_OUT")
- if out == "" {
- out = "audit_out.json"
- }
- if err := useDB(p); err != nil {
- t.Fatal("打开库:", err)
- }
- invalidateAudit()
- mu.Lock()
- fp = p
- rHdr()
- tabs = pTabs()
- mu.Unlock()
- setCacheFP(fingerprint())
- deadline := time.Now().Add(15 * time.Minute)
- for {
- a, _, _ := computeAudit()
- if a == nil {
- cacheMu.Lock()
- msg := auditErrMsg
- cacheMu.Unlock()
- t.Fatal("审计失败:", msg)
- }
- if !a.IdxPending {
- b, err := json.MarshalIndent(a, "", " ")
- if err != nil {
- t.Fatal("序列化:", err)
- }
- if err := os.WriteFile(out, b, 0o644); err != nil {
- t.Fatal("写结果:", err)
- }
- fmt.Printf("审计完成: verdict=%s pages=%d 孤儿=%d 交叉引用=%d 非法指针=%d "+
- "索引序乱=%d 悬空PK=%d 缺主键条目=%d 缺二级条目=%d 空闲活页=%d\n",
- a.Verdict, a.TotalPages,
- a.Reach.Unaccounted,
- a.MultiRef, a.BadRefCount,
- a.IdxBadOrder, a.IdxOrphanPK, a.IdxMissingRow, a.IdxMissingEntry,
- len(a.FreeLive))
- fmt.Println("结果 JSON:", out)
- return
- }
- if time.Now().After(deadline) {
- t.Fatal("索引内容补全超时")
- }
- time.Sleep(500 * time.Millisecond)
- }
- }
|