package main import ( "bytes" "context" "encoding/json" "fmt" "net/http" "net/http/httptest" "path/filepath" "testing" "time" "github.com/gin-gonic/gin" "github.com/glebarez/sqlite" "gorm.io/gorm" businessbiz "kra/internal/biz/business" taskbiz "kra/internal/biz/task" businessdata "kra/internal/data/business" taskdata "kra/internal/data/task" "kra/internal/server/handler" "kra/internal/server/router" taskservice "kra/internal/service/task" "kra/internal/worker" platformtask "kra/pkg/task" ) func TestAlertTriggerThroughNativeTaskHTTP(t *testing.T) { db, err := gorm.Open(sqlite.Open(filepath.Join(t.TempDir(), "alert-task.db")), &gorm.Config{}) if err != nil { t.Fatal(err) } pool, _ := db.DB() t.Cleanup(func() { _ = pool.Close() }) for _, step := range append(taskdata.Migrations(), businessdata.Migrations()...) { if err := step.Migrate(db); err != nil { t.Fatal(err) } } for _, sql := range []string{ "CREATE TABLE sys_users(id INTEGER,username TEXT,level INTEGER,parent_id INTEGER,id_path TEXT,authority_id INTEGER,deleted_at DATETIME)", "CREATE TABLE tab_promote(id INTEGER,source_db TEXT,busier_id INTEGER,account TEXT,promote_level INTEGER,status INTEGER,last_login_time INTEGER,create_time INTEGER)", "INSERT INTO sys_users VALUES(10,'一级',1,0,'0',901,NULL),(20,'二级',2,10,'0,10',902,NULL),(30,'三级',3,20,'0,10,20',903,NULL)", "INSERT INTO sys_user_bind_platform(user_id,source_db,platform_busier_id,platform_busier_account,status) VALUES(30,'lx',7,'绑定','0')", "INSERT INTO tab_promote VALUES(10,'lx',7,'测试渠道',1,1,0,1)", "INSERT INTO sys_alert_rule(rule_name,rule_type,monitor_metric,creator_id,unlogin_days,warning_color,enabled,is_deleted) VALUES('未登录规则','未登录',3,10,1,'red',1,0)", } { if err := db.Exec(sql).Error; err != nil { t.Fatal(err) } } provider := businessHTTPData{db} registry := platformtask.NewRegistry() tasks := taskbiz.NewTaskUsecaseWithRegistry(taskdata.NewTaskRepo(reportTaskHTTPData{provider}), registry) alerts := businessbiz.NewAlertTriggerUsecase(businessdata.NewAlertTriggerRepo(provider)) worker.NewTaskMethods(tasks, nil, nil, nil, nil, alerts).RegisterTasks(registry) scheduler := worker.NewTaskScheduler(tasks, nil, worker.NewTaskExecutorWithRegistry(tasks, registry), nil) defer func() { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() _ = scheduler.Stop(ctx) }() engine := gin.New() router.RegisterTask(engine.Group(""), handler.NewTask(taskservice.NewTaskService(taskbiz.NewTaskApplicationUsecase(tasks, scheduler)))) server := httptest.NewServer(engine) defer server.Close() call := func(method, path string, body any) map[string]any { t.Helper() raw, _ := json.Marshal(body) req, _ := http.NewRequest(method, server.URL+"/timedTask/"+path, bytes.NewReader(raw)) req.Header.Set("Content-Type", "application/json") res, err := server.Client().Do(req) if err != nil { t.Fatal(err) } defer res.Body.Close() var result map[string]any if err := json.NewDecoder(res.Body).Decode(&result); err != nil { t.Fatal(err) } if result["code"] != float64(0) { t.Fatalf("预警任务 HTTP 失败: %+v", result) } return result["data"].(map[string]any) } call("POST", "createTimedTask", map[string]any{"name": "预警 HTTP 演练", "spec": "@daily", "executorType": "method", "methodName": "alertTriggerTask", "enabled": false}) var id uint if err := db.Table("sys_timed_tasks").Select("id").Where("name=?", "预警 HTTP 演练").Scan(&id).Error; err != nil || id == 0 { t.Fatalf("任务未创建: %v", err) } for iteration := 0; iteration < 2; iteration++ { call("POST", "triggerTimedTask", map[string]any{"id": id}) deadline := time.Now().Add(8 * time.Second) finished := false for time.Now().Before(deadline) { logs := call("GET", fmt.Sprintf("getTimedTaskLogList?taskId=%d&page=1&pageSize=10", id), nil)["list"].([]any) if len(logs) > iteration { if logs[0].(map[string]any)["status"] != "success" { t.Fatalf("预警任务失败: %+v", logs) } finished = true break } time.Sleep(20 * time.Millisecond) } if !finished { t.Fatal("没有收到预警执行完成日志") } } var rows []struct { BusinessID, TargetPromoteID uint Status int PlatformCode string } if err := db.Table("sys_alert_record").Scan(&rows).Error; err != nil { t.Fatal(err) } if len(rows) != 1 || rows[0].BusinessID != 10 || rows[0].TargetPromoteID != 10 || rows[0].PlatformCode != "lx" || rows[0].Status != 1 { t.Fatalf("重复触发或归属错误: %+v", rows) } var enabled int64 db.Table("sys_timed_tasks").Where("enabled=1").Count(&enabled) if enabled != 0 { t.Fatal("手动触发不应启用自动计划") } }