package main import ( "context" "database/sql" "path/filepath" "testing" "git.yeij.top/AskaEth/Cyrene_v2/internal/config" "git.yeij.top/AskaEth/Cyrene_v2/internal/db" ) // 本文件锁定组合根接线(K1):wireFrontend 调用的 wireAPIKeys 必须真的把 SQLite // 载体接到 key 管理器,否则签发的 key 又回到「重启即失效」。 // // 为什么在组合根测这件事:newApp 无法在单元测试里实例化(要开库、迁移、拉起全部 // 子系统,见 wire_context_test.go 的说明),所以这里直接对 wireAPIKeys 这一步 // 接线取证 —— 它与 newApp 里调用的是同一个函数。 // openMigratedTestDB 打开一个临时文件库并跑完全部迁移。用文件而非 :memory:, // 因为「重启仍在」必须跨连接读同一份数据。 func openMigratedTestDB(t *testing.T, path string) *sql.DB { t.Helper() ctx := context.Background() conn, err := db.Open(ctx, path, testLog()) if err != nil { t.Fatalf("db.Open(%s): %v", path, err) } if err := db.MigrateUp(ctx, conn, testLog()); err != nil { _ = conn.Close() t.Fatalf("db.MigrateUp: %v", err) } t.Cleanup(func() { _ = conn.Close() }) return conn } // TestWireAPIKeys_KeySurvivesRestart 断言组合根接的线真的落盘:签发 → 关连接 // (进程退出)→ 用同一个库重新接线 → 同一把 key 仍能认证。 func TestWireAPIKeys_KeySurvivesRestart(t *testing.T) { path := filepath.Join(t.TempDir(), "cyrene.db") first := &app{db: openMigratedTestDB(t, path), cfg: &config.Config{}, log: testLog()} keys := first.wireAPIKeys() key, err := keys.Generate() if err != nil { t.Fatalf("Generate: %v", err) } if err := first.db.Close(); err != nil { t.Fatalf("close first connection: %v", err) } second := &app{db: openMigratedTestDB(t, path), cfg: &config.Config{}, log: testLog()} restarted := second.wireAPIKeys() if !restarted.Verify(key) { t.Fatal("重启后 key 无法认证:组合根没有把落盘载体接上") } } // TestWireAPIKeys_NilDBFallsBackToMemory 断言没有数据库句柄时(纯内存测试/ // 构建路径)接线是空操作且不 panic:key 照旧可签发可校验,只是不跨重启。 func TestWireAPIKeys_NilDBFallsBackToMemory(t *testing.T) { a := &app{db: nil, cfg: &config.Config{}, log: testLog()} keys := a.wireAPIKeys() // 必须不 panic key, err := keys.Generate() if err != nil { t.Fatalf("Generate: %v", err) } if !keys.Verify(key) { t.Fatal("未接库路径的 key 无法认证") } }