package model import ( "fmt" "strings" "testing" "modelRT/constants" ) func TestFuzzyRecommendOffsetUsesFullMatchedInput(t *testing.T) { tests := []struct { name string searchPrefix string searchInput string want int }{ { name: "zone fuzzy prefix", searchPrefix: "grid000", searchInput: "z", want: len([]rune("grid000.z")), }, { name: "level one fuzzy", searchPrefix: "", searchInput: "g", want: len([]rune("g")), }, { name: "measurement fuzzy preserves config token", searchPrefix: "grid.zone.station.nspath.comp.config", searchInput: "m", want: len([]rune("grid.zone.station.nspath.comp.config.m")), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := fuzzyRecommendOffset(tt.searchPrefix, tt.searchInput) if got != tt.want { t.Fatalf("expected offset %d, got %d", tt.want, got) } }) } } func TestNormalizeRecommendResultsUsesInputLengthForExactCompletion(t *testing.T) { tests := []struct { name string input string }{ { name: "full token1 to token7 structure", input: "grid000.zone000.station000.220kV_学府路1-testProject1.compTag.config.IA_rms_CTA-testProject1", }, { name: "local token4 to token7 structure", input: "220kV_学府路1-testProject1.IA_rms_CTA-testProject1", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { results := map[string]SearchResult{ constants.MeasTagRecommendHierarchyType.String(): { RecommendType: constants.MeasTagRecommendHierarchyType, QueryDatas: []string{""}, IsFuzzy: false, }, } got := normalizeRecommendResults(tt.input, results) result := got[constants.MeasTagRecommendHierarchyType.String()] wantOffset := len([]rune(tt.input)) if result.Offset != wantOffset { t.Fatalf("expected offset %d, got %d", wantOffset, result.Offset) } if len(result.QueryDatas) != 0 { t.Fatalf("expected exact completion to return no suffix, got %v", result.QueryDatas) } }) } } func TestNormalizeRecommendResultsUsesInputLengthForLevelContinuation(t *testing.T) { tests := []struct { name string input string recommendType constants.RecommendHierarchyType }{ { name: "token1 grid can continue", input: "grid000", recommendType: constants.GridRecommendHierarchyType, }, { name: "token1 token2 zone can continue", input: "grid000.zone000", recommendType: constants.ZoneRecommendHierarchyType, }, { name: "token1 token2 token3 station can continue", input: "grid000.zone000.station000", recommendType: constants.StationRecommendHierarchyType, }, { name: "token1 token2 token3 token4 nspath can continue", input: "grid000.zone000.station000.110kV_TV-demoProject", recommendType: constants.CompNSPathRecommendHierarchyType, }, { name: "token1 token2 token3 token4 token5 compTag can continue", input: "grid000.zone000.station000.110kV_TV-demoProject.cable_26-demoProject110kV_TV", recommendType: constants.CompTagRecommendHierarchyType, }, { name: "token1 through token6 config can continue", input: "grid000.zone000.station000.110kV_TV-demoProject.cable_26-demoProject110kV_TV.base_extend", recommendType: constants.ConfigRecommendHierarchyType, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { results := map[string]SearchResult{ tt.recommendType.String(): { RecommendType: tt.recommendType, QueryDatas: []string{"."}, IsFuzzy: false, }, } got := normalizeRecommendResults(tt.input, results) result := got[tt.recommendType.String()] wantOffset := len([]rune(tt.input)) if result.Offset != wantOffset { t.Fatalf("expected offset %d, got %d", wantOffset, result.Offset) } if len(result.QueryDatas) != 1 || result.QueryDatas[0] != "." { t.Fatalf("expected level continuation '.', got %v", result.QueryDatas) } }) } } func TestNormalizeRecommendResultsKeepsFallbackOffsetZero(t *testing.T) { input := "x" results := map[string]SearchResult{ constants.GridRecommendHierarchyType.String(): { RecommendType: constants.GridRecommendHierarchyType, QueryDatas: []string{"grid000", "grid001"}, IsFuzzy: true, IsFallback: true, Offset: 0, }, constants.CompNSPathRecommendHierarchyType.String(): { RecommendType: constants.CompNSPathRecommendHierarchyType, QueryDatas: []string{"nspath000", "nspath001"}, IsFuzzy: true, IsFallback: true, Offset: 0, }, } got := normalizeRecommendResults(input, results) for key, result := range got { if result.Offset != 0 { t.Fatalf("expected fallback offset 0 for %s, got %d", key, result.Offset) } if len(result.QueryDatas) != 2 { t.Fatalf("expected fallback recommends to remain intact for %s, got %v", key, result.QueryDatas) } } } func TestNormalizeRecommendResultsKeepsParentPrefixOffsetForSpecificFallback(t *testing.T) { nsPath := "220kV_学府路1-testProject1" input := nsPath + ".x" offset := recommendPrefixOffset([]string{nsPath}) results := map[string]SearchResult{ constants.CompTagRecommendHierarchyType.String(): { RecommendType: constants.CompTagRecommendHierarchyType, QueryDatas: []string{ nsPath + ".CTA-testProject1220kV_学府路1", nsPath + ".CB-testProject1220kV_学府路1", }, IsFuzzy: true, IsFallback: true, Offset: offset, }, constants.MeasTagRecommendHierarchyType.String(): { RecommendType: constants.MeasTagRecommendHierarchyType, QueryDatas: []string{ nsPath + ".IA_rms_CTA-testProject1", nsPath + ".IB_rms_CTA-testProject1", }, IsFuzzy: true, IsFallback: true, Offset: offset, }, } got := normalizeRecommendResults(input, results) if offset != 24 { t.Fatalf("expected sample parent prefix offset 24, got %d", offset) } for key, result := range got { if result.Offset != 24 { t.Fatalf("expected specific fallback offset 24 for %s, got %d", key, result.Offset) } for _, recommend := range result.QueryDatas { if strings.HasPrefix(recommend, nsPath+".") { t.Fatalf("expected trimmed fallback recommend for %s, got %s", key, recommend) } } } } func TestRecommendGroupTokens(t *testing.T) { tests := []struct { name string inputSlice []string wantCompTag string wantConfig string wantOK bool }{ { name: "full token1 to token7 input", inputSlice: []string{"grid000", "zone000", "station000", "nspath", "comp_tag", "base_extend", ""}, wantCompTag: "comp_tag", wantConfig: "base_extend", wantOK: true, }, { name: "local token4 to token7 input", inputSlice: []string{"nspath", "comp_tag", "component", ""}, wantCompTag: "comp_tag", wantConfig: "component", wantOK: true, }, { name: "missing config token", inputSlice: []string{"nspath", ""}, wantOK: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { gotCompTag, gotConfig, gotOK := recommendGroupTokens(tt.inputSlice) if gotOK != tt.wantOK { t.Fatalf("expected ok %t, got %t", tt.wantOK, gotOK) } if gotCompTag != tt.wantCompTag || gotConfig != tt.wantConfig { t.Fatalf("expected compTag/config %q/%q, got %q/%q", tt.wantCompTag, tt.wantConfig, gotCompTag, gotConfig) } }) } } func TestFallbackSpecificSetKey(t *testing.T) { tests := []struct { name string hierarchy constants.RecommendHierarchyType inputSlice []string want string wantOK bool }{ { name: "zone fallback uses grid specific set", hierarchy: constants.ZoneRecommendHierarchyType, inputSlice: []string{"grid000", "z"}, want: fmt.Sprintf(constants.RedisSpecGridZoneSetKey, "grid000"), wantOK: true, }, { name: "component tag fallback uses previous nspath token", hierarchy: constants.CompTagRecommendHierarchyType, inputSlice: []string{"grid000", "I"}, want: fmt.Sprintf(constants.RedisSpecCompNSPathCompTagSetKey, "grid000"), wantOK: true, }, { name: "measurement fallback skips config token and uses component tag", hierarchy: constants.MeasTagRecommendHierarchyType, inputSlice: []string{"nspath", "comp_tag", "config", "m"}, want: fmt.Sprintf(constants.RedisSpecCompTagMeasSetKey, "comp_tag"), wantOK: true, }, { name: "config fallback has no parent specific set", hierarchy: constants.ConfigRecommendHierarchyType, inputSlice: []string{"nspath", "comp_tag", ""}, wantOK: false, }, { name: "missing previous token", hierarchy: constants.ZoneRecommendHierarchyType, inputSlice: []string{"z"}, wantOK: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, ok := fallbackSpecificSetKey(tt.hierarchy, tt.inputSlice) if ok != tt.wantOK { t.Fatalf("expected ok %t, got %t", tt.wantOK, ok) } if got != tt.want { t.Fatalf("expected key %q, got %q", tt.want, got) } }) } } func TestShouldFallbackToInitialRecommend(t *testing.T) { tests := []struct { input string want bool }{ {input: "", want: false}, {input: ".", want: true}, {input: ".x", want: true}, {input: "..x", want: true}, {input: "...x", want: true}, {input: "grid000", want: false}, {input: "grid000.", want: false}, {input: "grid000.zone000", want: false}, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { got := shouldFallbackToInitialRecommend(tt.input) if got != tt.want { t.Fatalf("expected %t, got %t", tt.want, got) } }) } }