test(ops): 提升日志链路覆盖率并修复lint阻塞
This commit is contained in:
243
backend/internal/service/ops_system_log_service_test.go
Normal file
243
backend/internal/service/ops_system_log_service_test.go
Normal file
@@ -0,0 +1,243 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
)
|
||||
|
||||
func TestOpsServiceListSystemLogs_DefaultClampAndSuccess(t *testing.T) {
|
||||
var gotFilter *OpsSystemLogFilter
|
||||
repo := &opsRepoMock{
|
||||
ListSystemLogsFn: func(ctx context.Context, filter *OpsSystemLogFilter) (*OpsSystemLogList, error) {
|
||||
gotFilter = filter
|
||||
return &OpsSystemLogList{
|
||||
Logs: []*OpsSystemLog{{ID: 1, Level: "warn", Message: "x"}},
|
||||
Total: 1,
|
||||
Page: filter.Page,
|
||||
PageSize: filter.PageSize,
|
||||
}, nil
|
||||
},
|
||||
}
|
||||
svc := NewOpsService(repo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
|
||||
out, err := svc.ListSystemLogs(context.Background(), &OpsSystemLogFilter{
|
||||
Page: 0,
|
||||
PageSize: 999,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("ListSystemLogs() error: %v", err)
|
||||
}
|
||||
if gotFilter == nil {
|
||||
t.Fatalf("expected repository to receive filter")
|
||||
}
|
||||
if gotFilter.Page != 1 || gotFilter.PageSize != 200 {
|
||||
t.Fatalf("filter normalized unexpectedly: page=%d pageSize=%d", gotFilter.Page, gotFilter.PageSize)
|
||||
}
|
||||
if out.Total != 1 || len(out.Logs) != 1 {
|
||||
t.Fatalf("unexpected result: %+v", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceListSystemLogs_MonitoringDisabled(t *testing.T) {
|
||||
svc := NewOpsService(
|
||||
&opsRepoMock{},
|
||||
nil,
|
||||
&config.Config{Ops: config.OpsConfig{Enabled: false}},
|
||||
nil, nil, nil, nil, nil, nil, nil, nil,
|
||||
)
|
||||
_, err := svc.ListSystemLogs(context.Background(), &OpsSystemLogFilter{})
|
||||
if err == nil {
|
||||
t.Fatalf("expected disabled error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceListSystemLogs_NilRepoReturnsEmpty(t *testing.T) {
|
||||
svc := NewOpsService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
out, err := svc.ListSystemLogs(context.Background(), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("ListSystemLogs() error: %v", err)
|
||||
}
|
||||
if out == nil || out.Page != 1 || out.PageSize != 50 || out.Total != 0 || len(out.Logs) != 0 {
|
||||
t.Fatalf("unexpected nil-repo result: %+v", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceListSystemLogs_RepoErrorMapped(t *testing.T) {
|
||||
repo := &opsRepoMock{
|
||||
ListSystemLogsFn: func(ctx context.Context, filter *OpsSystemLogFilter) (*OpsSystemLogList, error) {
|
||||
return nil, errors.New("db down")
|
||||
},
|
||||
}
|
||||
svc := NewOpsService(repo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
_, err := svc.ListSystemLogs(context.Background(), &OpsSystemLogFilter{})
|
||||
if err == nil {
|
||||
t.Fatalf("expected mapped internal error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "OPS_SYSTEM_LOG_LIST_FAILED") {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceCleanupSystemLogs_SuccessAndAudit(t *testing.T) {
|
||||
var audit *OpsSystemLogCleanupAudit
|
||||
repo := &opsRepoMock{
|
||||
DeleteSystemLogsFn: func(ctx context.Context, filter *OpsSystemLogCleanupFilter) (int64, error) {
|
||||
return 3, nil
|
||||
},
|
||||
InsertSystemLogCleanupAuditFn: func(ctx context.Context, input *OpsSystemLogCleanupAudit) error {
|
||||
audit = input
|
||||
return nil
|
||||
},
|
||||
}
|
||||
svc := NewOpsService(repo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
userID := int64(7)
|
||||
now := time.Now().UTC()
|
||||
filter := &OpsSystemLogCleanupFilter{
|
||||
StartTime: &now,
|
||||
Level: "warn",
|
||||
RequestID: "req-1",
|
||||
ClientRequestID: "creq-1",
|
||||
UserID: &userID,
|
||||
Query: "timeout",
|
||||
}
|
||||
|
||||
deleted, err := svc.CleanupSystemLogs(context.Background(), filter, 99)
|
||||
if err != nil {
|
||||
t.Fatalf("CleanupSystemLogs() error: %v", err)
|
||||
}
|
||||
if deleted != 3 {
|
||||
t.Fatalf("deleted=%d, want 3", deleted)
|
||||
}
|
||||
if audit == nil {
|
||||
t.Fatalf("expected cleanup audit")
|
||||
}
|
||||
if !strings.Contains(audit.Conditions, `"client_request_id":"creq-1"`) {
|
||||
t.Fatalf("audit conditions should include client_request_id: %s", audit.Conditions)
|
||||
}
|
||||
if !strings.Contains(audit.Conditions, `"user_id":7`) {
|
||||
t.Fatalf("audit conditions should include user_id: %s", audit.Conditions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceCleanupSystemLogs_RepoUnavailableAndInvalidOperator(t *testing.T) {
|
||||
svc := NewOpsService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
if _, err := svc.CleanupSystemLogs(context.Background(), &OpsSystemLogCleanupFilter{RequestID: "r"}, 1); err == nil {
|
||||
t.Fatalf("expected repo unavailable error")
|
||||
}
|
||||
|
||||
svc = NewOpsService(&opsRepoMock{}, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
if _, err := svc.CleanupSystemLogs(context.Background(), &OpsSystemLogCleanupFilter{RequestID: "r"}, 0); err == nil {
|
||||
t.Fatalf("expected invalid operator error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceCleanupSystemLogs_FilterRequired(t *testing.T) {
|
||||
repo := &opsRepoMock{
|
||||
DeleteSystemLogsFn: func(ctx context.Context, filter *OpsSystemLogCleanupFilter) (int64, error) {
|
||||
return 0, errors.New("cleanup requires at least one filter condition")
|
||||
},
|
||||
}
|
||||
svc := NewOpsService(repo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
_, err := svc.CleanupSystemLogs(context.Background(), &OpsSystemLogCleanupFilter{}, 1)
|
||||
if err == nil {
|
||||
t.Fatalf("expected filter required error")
|
||||
}
|
||||
if !strings.Contains(strings.ToLower(err.Error()), "filter") {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceCleanupSystemLogs_InvalidRange(t *testing.T) {
|
||||
repo := &opsRepoMock{}
|
||||
svc := NewOpsService(repo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
start := time.Now().UTC()
|
||||
end := start.Add(-time.Hour)
|
||||
_, err := svc.CleanupSystemLogs(context.Background(), &OpsSystemLogCleanupFilter{
|
||||
StartTime: &start,
|
||||
EndTime: &end,
|
||||
}, 1)
|
||||
if err == nil {
|
||||
t.Fatalf("expected invalid range error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceCleanupSystemLogs_NoRowsAndInternalError(t *testing.T) {
|
||||
repo := &opsRepoMock{
|
||||
DeleteSystemLogsFn: func(ctx context.Context, filter *OpsSystemLogCleanupFilter) (int64, error) {
|
||||
return 0, sql.ErrNoRows
|
||||
},
|
||||
}
|
||||
svc := NewOpsService(repo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
deleted, err := svc.CleanupSystemLogs(context.Background(), &OpsSystemLogCleanupFilter{
|
||||
RequestID: "req-1",
|
||||
}, 1)
|
||||
if err != nil || deleted != 0 {
|
||||
t.Fatalf("expected no rows shortcut, deleted=%d err=%v", deleted, err)
|
||||
}
|
||||
|
||||
repo.DeleteSystemLogsFn = func(ctx context.Context, filter *OpsSystemLogCleanupFilter) (int64, error) {
|
||||
return 0, errors.New("boom")
|
||||
}
|
||||
if _, err := svc.CleanupSystemLogs(context.Background(), &OpsSystemLogCleanupFilter{
|
||||
RequestID: "req-1",
|
||||
}, 1); err == nil {
|
||||
t.Fatalf("expected internal cleanup error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceCleanupSystemLogs_AuditFailureIgnored(t *testing.T) {
|
||||
repo := &opsRepoMock{
|
||||
DeleteSystemLogsFn: func(ctx context.Context, filter *OpsSystemLogCleanupFilter) (int64, error) {
|
||||
return 5, nil
|
||||
},
|
||||
InsertSystemLogCleanupAuditFn: func(ctx context.Context, input *OpsSystemLogCleanupAudit) error {
|
||||
return errors.New("audit down")
|
||||
},
|
||||
}
|
||||
svc := NewOpsService(repo, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
deleted, err := svc.CleanupSystemLogs(context.Background(), &OpsSystemLogCleanupFilter{
|
||||
RequestID: "r1",
|
||||
}, 1)
|
||||
if err != nil || deleted != 5 {
|
||||
t.Fatalf("audit failure should not break cleanup, deleted=%d err=%v", deleted, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalSystemLogCleanupConditions_NilAndMarshalError(t *testing.T) {
|
||||
if got := marshalSystemLogCleanupConditions(nil); got != "{}" {
|
||||
t.Fatalf("nil filter should return {}, got %s", got)
|
||||
}
|
||||
|
||||
now := time.Now().UTC()
|
||||
userID := int64(1)
|
||||
filter := &OpsSystemLogCleanupFilter{
|
||||
StartTime: &now,
|
||||
EndTime: &now,
|
||||
UserID: &userID,
|
||||
}
|
||||
got := marshalSystemLogCleanupConditions(filter)
|
||||
if !strings.Contains(got, `"start_time"`) || !strings.Contains(got, `"user_id":1`) {
|
||||
t.Fatalf("unexpected marshal payload: %s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpsServiceGetSystemLogSinkHealth(t *testing.T) {
|
||||
svc := NewOpsService(nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil)
|
||||
health := svc.GetSystemLogSinkHealth()
|
||||
if health.QueueCapacity != 0 || health.QueueDepth != 0 {
|
||||
t.Fatalf("unexpected health for nil sink: %+v", health)
|
||||
}
|
||||
|
||||
sink := NewOpsSystemLogSink(&opsRepoMock{})
|
||||
svc = NewOpsService(&opsRepoMock{}, nil, nil, nil, nil, nil, nil, nil, nil, nil, sink)
|
||||
health = svc.GetSystemLogSinkHealth()
|
||||
if health.QueueCapacity <= 0 {
|
||||
t.Fatalf("expected non-zero queue capacity: %+v", health)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user