This commit is contained in:
cppla
2026-07-10 15:35:10 +08:00
parent 5322a9105e
commit e4ca0558f7
50 changed files with 3292 additions and 54736 deletions
+85
View File
@@ -0,0 +1,85 @@
package main
import (
"encoding/json"
"strings"
"testing"
"time"
"github.com/expr-lang/expr"
)
func TestNormalizeConfigPreservesCompatibility(t *testing.T) {
doc := minimalTestConfig()
doc["future"] = map[string]any{"enabled": true}
doc["watchdog"] = []any{
map[string]any{"name": "legacy", "rule": "cpu>90&load_1>5&username!='s01'", "interval": "600", "callback": nil},
map[string]any{"name": "type", "rule": "tcp_count>600&type='Oracle'", "interval": 60},
}
doc["servers"].([]any)[0].(map[string]any)["future_field"] = "kept"
normalized, runtime, apiErr := normalizeConfig(doc)
if apiErr != nil {
t.Fatal(apiErr)
}
if len(runtime.Watchdogs) != 2 || runtime.Watchdogs[0].Normalized != "cpu>90&&load_1>5&&username!='s01'" {
t.Fatalf("legacy rules were not normalized: %#v", runtime.Watchdogs)
}
server := normalized["servers"].([]any)[0].(map[string]any)
if server["future_field"] != "kept" || normalized["future"] == nil {
t.Fatal("unknown config fields were discarded")
}
if server["monthstart"] != json.Number("1") && server["monthstart"] != 1 {
t.Fatalf("monthstart not normalized: %#v", server["monthstart"])
}
}
func TestWatchdogLegacyRulesEvaluate(t *testing.T) {
rules := []string{
"online4=0&online6=0",
"(memory_used/memory_total)*100>90&memory_total>1048576",
"tcp_count>600&type='Oracle'",
"(network_out-last_network_out)/1024/1024/1024>18&(username='aliyun1'|username='aliyun2')",
}
for index, rule := range rules {
compiled, err := compileWatchdog(WatchdogConfig{Name: "test", Rule: rule, Interval: 1}, index)
if err != nil {
t.Fatalf("rule %q: %v", rule, err)
}
environment := watchdogEnvironment(ServerConfig{Username: "aliyun1", Type: "Oracle"}, AgentStats{MemoryTotal: 2_000_000, MemoryUsed: 1_900_000, TCPCount: 700, NetworkOut: 30 << 30}, false, false, 0, 0)
if _, err := expr.Run(compiled.Program, environment); err != nil {
t.Fatalf("run %q: %v", rule, err)
}
}
}
func TestConfigValidationErrors(t *testing.T) {
doc := minimalTestConfig()
doc["servers"] = append(doc["servers"].([]any), doc["servers"].([]any)[0])
_, _, apiErr := normalizeConfig(doc)
if apiErr == nil || apiErr.Status != 409 {
t.Fatalf("expected duplicate username error, got %#v", apiErr)
}
if _, err := decodeDocument([]byte(`{"servers":[]} {"servers":[]}`)); err == nil || !strings.Contains(err.Error(), "more than one") {
t.Fatalf("expected trailing JSON error, got %v", err)
}
}
func TestFormattingHelpers(t *testing.T) {
if got := formatUptime(90061); got != "1 天" {
t.Fatalf("formatUptime=%q", got)
}
if got := formatUptime(3661); got != "01:01:01" {
t.Fatalf("formatUptime=%q", got)
}
if got, err := certificateHost("https://example.com/path"); err != nil || got != "example.com" {
t.Fatalf("certificateHost=%q", got)
}
if got := secondsDuration(0); got != time.Second {
t.Fatalf("secondsDuration(0)=%s", got)
}
if got := secondsDuration(int(^uint(0) >> 1)); got < 365*24*time.Hour {
t.Fatalf("large interval overflowed or was truncated: %s", got)
}
}