package app import "testing" func alertMessages(alerts []map[string]string) string { joined := "" for _, alert := range alerts { joined += alert["level"] + ":" + alert["message"] + "\n" } return joined } func TestAIUsageAlerts(t *testing.T) { // Nothing is wrong while the feature is off, however bad the numbers look. if got := aiUsageAlerts(false, false, 0, 100, 500, 400, 9, "boom"); len(got) != 0 { t.Fatalf("a disabled feature must not raise alerts: %v", got) } healthy := aiUsageAlerts(true, true, 3, 100, 10, 0, 0, "") if len(healthy) != 0 { t.Fatalf("a healthy setup must be quiet: %v", healthy) } tests := []struct { name string alerts []map[string]string contains string }{ {name: "no model", alerts: aiUsageAlerts(true, false, 3, 0, 0, 0, 0, ""), contains: "没有可用的模型"}, {name: "no agents", alerts: aiUsageAlerts(true, true, 0, 0, 0, 0, 0, ""), contains: "还没有账号开启托管"}, {name: "quota reached", alerts: aiUsageAlerts(true, true, 2, 100, 100, 0, 0, ""), contains: "今日调用已达上限"}, {name: "quota near", alerts: aiUsageAlerts(true, true, 2, 100, 80, 0, 0, ""), contains: "超过配额的 80%"}, {name: "failure rate", alerts: aiUsageAlerts(true, true, 2, 0, 10, 4, 0, "上游 429"), contains: "失败率超过 30%"}, {name: "stuck worker", alerts: aiUsageAlerts(true, true, 2, 0, 0, 0, 3, ""), contains: "worker 是否在运行"}, } for _, test := range tests { if !contains(alertMessages(test.alerts), test.contains) { t.Errorf("%s: expected an alert mentioning %q, got %s", test.name, test.contains, alertMessages(test.alerts)) } } // The most recent error is quoted so the console shows why calls fail. if !contains(alertMessages(aiUsageAlerts(true, true, 2, 0, 10, 4, 0, "上游 429")), "上游 429") { t.Error("the failure alert must quote the latest error") } // A couple of failures out of a handful of calls is noise, not an alert. if got := aiUsageAlerts(true, true, 2, 0, 4, 2, 0, ""); len(got) != 0 { t.Errorf("a tiny sample must not trigger the failure alert: %v", got) } if got := aiUsageAlerts(true, true, 2, 0, 10, 2, 0, ""); len(got) != 0 { t.Errorf("a 20%% failure rate must stay below the threshold: %v", got) } } func contains(haystack, needle string) bool { return len(needle) > 0 && len(haystack) >= len(needle) && indexOf(haystack, needle) >= 0 } func indexOf(haystack, needle string) int { for index := 0; index+len(needle) <= len(haystack); index++ { if haystack[index:index+len(needle)] == needle { return index } } return -1 }