| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- 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)
- }
- }
|