kra-oa/internal/data/error_record_test.go

141 lines
4.2 KiB
Go

package data
import (
"context"
"testing"
"time"
"kra/internal/biz"
)
func errorString(value string) *string { return &value }
func newErrorRecordRepos(t *testing.T) (*auditRecorderRepo, *auditQueryRepo) {
t.Helper()
db, err := openWithDriver("sqlite", "file:"+t.Name()+"?mode=memory&cache=shared")
if err != nil {
t.Fatal(err)
}
if err = db.AutoMigrate(&errorRecordPO{}); err != nil {
t.Fatal(err)
}
sqlDB, err := db.DB()
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = sqlDB.Close() })
data := &Data{gormDB: newReloadableDB(db, nil)}
data.databaseReady.Store(true)
return &auditRecorderRepo{data: data}, &auditQueryRepo{data: data}
}
func TestCreateErrorBeforeDatabaseInitializationIsNoop(t *testing.T) {
db, err := openWithDriver("sqlite", "file:"+t.Name()+"?mode=memory&cache=shared")
if err != nil {
t.Fatal(err)
}
sqlDB, err := db.DB()
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { _ = sqlDB.Close() })
recorder := &auditRecorderRepo{data: &Data{gormDB: newReloadableDB(db, nil)}}
form := "后端"
if err = recorder.CreateError(context.Background(), &biz.ErrorRecord{Form: &form}); err != nil {
t.Fatalf("uninitialized error write = %v, want nil", err)
}
}
func TestCreateErrorPreservesNullableFieldsAndDefaultStatus(t *testing.T) {
recorder, query := newErrorRecordRepos(t)
createdAt := time.Date(2025, time.March, 4, 5, 6, 7, 0, time.UTC)
form := "前端"
if err := recorder.CreateError(context.Background(), &biz.ErrorRecord{
ID: 41,
CreatedAt: createdAt,
Form: &form,
Level: "error",
}); err != nil {
t.Fatal(err)
}
got, err := query.FindError(context.Background(), 41)
if err != nil {
t.Fatal(err)
}
if got.Form == nil || *got.Form != form {
t.Fatalf("form = %#v, want %q", got.Form, form)
}
if got.Info != nil || got.Solution != nil {
t.Fatalf("nullable fields = (%#v, %#v), want nil", got.Info, got.Solution)
}
if got.Status != "未处理" {
t.Fatalf("status = %q, want 未处理", got.Status)
}
if !got.CreatedAt.Equal(createdAt) {
t.Fatalf("created_at = %v, want %v", got.CreatedAt, createdAt)
}
}
func TestUpdateErrorDistinguishesOmittedAndExplicitEmptyFields(t *testing.T) {
recorder, query := newErrorRecordRepos(t)
form, info, solution := "后端", "错误内容", "解决方案"
if err := recorder.CreateError(context.Background(), &biz.ErrorRecord{
Form: &form,
Info: &info,
Solution: &solution,
Level: "error",
RequestID: "request-old",
TraceID: "trace-old",
Status: "处理中",
}); err != nil {
t.Fatal(err)
}
items, _, err := query.ListErrors(context.Background(), 1, 10, nil)
if err != nil || len(items) != 1 {
t.Fatalf("list before update = (%d, %v)", len(items), err)
}
id := items[0].ID
newForm := "服务端"
if err = query.UpdateError(context.Background(), &biz.ErrorRecord{ID: id, Form: &newForm}); err != nil {
t.Fatal(err)
}
got, err := query.FindError(context.Background(), id)
if err != nil {
t.Fatal(err)
}
if got.Info == nil || *got.Info != info || got.Solution == nil || *got.Solution != solution {
t.Fatalf("omitted fields changed: info=%#v solution=%#v", got.Info, got.Solution)
}
changedCreatedAt := time.Date(2024, time.January, 2, 3, 4, 5, 0, time.UTC)
if err = query.UpdateError(context.Background(), &biz.ErrorRecord{
ID: id,
CreatedAt: changedCreatedAt,
Form: errorString(""),
Info: errorString(""),
Solution: errorString(""),
RequestID: "request-new",
TraceID: "trace-new",
}); err != nil {
t.Fatal(err)
}
got, err = query.FindError(context.Background(), id)
if err != nil {
t.Fatal(err)
}
if got.Form == nil || *got.Form != "" || got.Info == nil || *got.Info != "" || got.Solution == nil || *got.Solution != "" {
t.Fatalf("explicit empty fields were not persisted: form=%#v info=%#v solution=%#v", got.Form, got.Info, got.Solution)
}
if got.Level != "error" || got.Status != "处理中" {
t.Fatalf("zero-value fields changed: level=%q status=%q", got.Level, got.Status)
}
if got.RequestID != "request-new" || got.TraceID != "trace-new" {
t.Fatalf("trace fields = (%q, %q), want updated values", got.RequestID, got.TraceID)
}
if !got.CreatedAt.Equal(changedCreatedAt) {
t.Fatalf("created_at = %v, want %v", got.CreatedAt, changedCreatedAt)
}
}