package tools import ( "testing" "fwh-toolbox-server/domain" "fwh-toolbox-server/dto" ) func TestRecognizeMode(t *testing.T) { cases := []struct { solar, load string params map[string]any want string issues bool }{ {"1,2,0", "1,3,2", nil, "A", false}, {"2,5,0", "2,9,5", nil, "A", false}, // 归一化后匹配 {"1,2,0", "1,2,0", nil, "B", false}, {"1,3,2", "1,2,0", nil, "C", false}, {"1,3,2", "1,3,2", nil, "D", false}, {"1,2,3", "1,2,0", nil, "E/G", false}, {"1,2,0", "1,2,3", nil, "F/H", false}, {"9,9,9", "9,9,9", map[string]any{"gridDischargeMax": 0.1, "gridFeedMax": 0.1}, "Zero Import", false}, {"9,9,9", "9,9,9", map[string]any{"gridFeedMax": 5.0}, "Zero Import", true}, {"5,5,5", "5,5,5", nil, "自定义", false}, // 归一化为 1,1,1,不是 Zero Import {"", "", nil, "未设置", false}, {"", "", map[string]any{"chargePower": 8.0}, "强制充电", false}, {"", "", map[string]any{"dischargePower": 10.0}, "强制放电", false}, {"", "", map[string]any{"chargePower": 8.0, "dischargePower": 10.0}, "自定义", true}, {"1,2,0", "", nil, "自定义", true}, } for _, c := range cases { got, issues := RecognizeMode(c.solar, c.load, c.params) if got != c.want || (len(issues) > 0) != c.issues { t.Errorf("RecognizeMode(%q,%q)=%s issues=%v,期望 %s issues=%v", c.solar, c.load, got, issues, c.want, c.issues) } } } func TestNormalizePriority(t *testing.T) { for in, want := range map[string]string{"9,9,9": "1,1,1", "2,5,1": "2,3,1", "0,5,9": "0,1,2"} { if got, ok := normalizePriority(in); !ok || got != want { t.Errorf("normalizePriority(%s)=%s,期望 %s", in, got, want) } } if _, ok := normalizePriority("1,2"); ok { t.Error("长度不为 3 应失败") } } func TestOrganizeTouDetail(t *testing.T) { detail := map[string]any{ "template": map[string]any{"name": "T", "templateId": 1}, "strategyList": []any{map[string]any{ "seasonName": "All", "month": "1,2,3", "dayName": "Every day", "eleticRatePeak": 0.3, "detailVoList": []any{ map[string]any{"startHourTime": "06:00", "endHourTime": "24:00", "waveType": 2, "solarPriority": "1,3,2", "loadPriority": "1,3,2", "chargeMax": -1}, map[string]any{"startHourTime": "00:00", "endHourTime": "06:00", "waveType": 0, "solarPriority": "", "loadPriority": "", "chargePower": 8}, }, }}, } out, ok := OrganizeTouDetail(detail) if !ok { t.Fatal("应能整理") } st := out["strategies"].([]map[string]any)[0] ps := st["periods"].([]TouPeriod) if ps[0].Start != "00:00" || ps[0].Mode != "强制充电" || ps[1].Mode != "D" || ps[1].WaveType != "峰" { t.Errorf("时段整理不正确: %+v", ps) } if _, has := ps[1].Params["chargeMax"]; has { t.Error("-1 应视为未设置") } if _, has := st["issues"]; has { t.Errorf("时段覆盖全天,不应有问题: %v", st["issues"]) } if _, ok := OrganizeTouDetail(map[string]any{"foo": 1}); ok { t.Error("没有 strategyList 时应返回 false") } } func TestCheckCoverageGap(t *testing.T) { issues := checkCoverage([]TouPeriod{{Start: "00:00", End: "06:00"}, {Start: "07:00", End: "24:00"}}) if len(issues) != 1 { t.Errorf("应发现 1 处不衔接: %v", issues) } } func TestPowerFlowToRows(t *testing.T) { p := &dto.SitePowerFlow{ DeviceTimeArray: []string{"2026-10-01 00:00:00", "2026-10-01 00:05:00"}, PowerSunArray: []float32{1.5, 2}, SocArray: []float32{80}, RunStatusArray: []uint{1, 2}, } rows := PowerFlowToRows(p) if len(rows) != 2 || len(rows[0]) != len(powerFlowCols) { t.Fatalf("行列数不正确: %v", rows) } if rows[0][1] != "1.5" || rows[0][6] != "80" || rows[1][6] != "" || rows[1][7] != "2" { t.Errorf("映射不正确: %v", rows) } } func TestMapEventRows(t *testing.T) { end := "2026-10-01 10:00:00" rows := MapEventRows([]domain.EventAlarmItem{ {LogType: "0", AlarmCode: "0", LogTime: "2026-10-01 08:00:00", LogName: "启动"}, {LogType: "1", AlarmCode: "E101", LogTime: "2026-10-01 09:00:00", EndTime: &end}, }) if rows[0].Kind != "告警" || rows[0].EndTime != end || rows[1].Code != "" { t.Errorf("映射或排序不正确: %+v", rows) } } func TestParseSN(t *testing.T) { r, err := ParseSN("10060006A03X25310091") if err != nil { t.Fatal(err) } if r["productName"] != "aGate (网关)" || r["year"] != "2025" || r["week"] != "31" || r["serialNumber"] != "0091" { t.Errorf("解析不正确: %v", r) } if _, err := ParseSN("1006"); err == nil { t.Error("长度不足应报错") } } func TestParseIdentifier(t *testing.T) { p, n, err := parseIdentifier("fwh-42") if err != nil || p != "FWH" || n != 42 { t.Errorf("parseIdentifier 错误: %s %d %v", p, n, err) } if _, _, err := parseIdentifier("FWH"); err == nil { t.Error("缺少序号应报错") } } func TestSortCodeCounts(t *testing.T) { got := SortCodeCounts(map[string]uint{"b": 2, "a": 2, "c": 5}) if got[0].Code != "c" || got[1].Code != "a" || got[2].Code != "b" { t.Errorf("排序不正确: %v", got) } }