blob: 2a9d9b663bdf2a6ae2562c737d60a513e5201f4b [file] [log] [blame]
Robert Findleyb15dac22022-08-30 14:40:12 -04001// Copyright 2021 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package fuzzy_test
6
7import (
8 "testing"
9
10 . "golang.org/x/tools/internal/fuzzy"
11)
12
13func TestSymbolMatchIndex(t *testing.T) {
14 tests := []struct {
15 pattern, input string
16 want int
17 }{
18 {"test", "foo.TestFoo", 4},
19 {"test", "test", 0},
20 {"test", "Test", 0},
21 {"test", "est", -1},
22 {"t", "shortest", 7},
23 {"", "foo", -1},
24 {"", string([]rune{0}), -1}, // verify that we don't default to an empty pattern.
25 {"anything", "", -1},
26 }
27
28 for _, test := range tests {
29 matcher := NewSymbolMatcher(test.pattern)
30 if got, _ := matcher.Match([]string{test.input}); got != test.want {
31 t.Errorf("NewSymbolMatcher(%q).Match(%q) = %v, _, want %v, _", test.pattern, test.input, got, test.want)
32 }
33 }
34}
35
36func TestSymbolRanking(t *testing.T) {
37 matcher := NewSymbolMatcher("test")
38
39 // symbols to match, in ascending order of ranking.
40 symbols := []string{
41 "this.is.better.than.most",
42 "test.foo.bar",
Robert Findleyb15dac22022-08-30 14:40:12 -040043 "thebest",
44 "test.foo",
45 "test.foo",
Rob Findleyddfa2202023-05-08 17:03:33 -040046 "atest",
Robert Findleyb15dac22022-08-30 14:40:12 -040047 "testage",
Rob Findleyddfa2202023-05-08 17:03:33 -040048 "tTest",
Robert Findleyb15dac22022-08-30 14:40:12 -040049 "foo.test",
50 "test",
51 }
52 prev := 0.0
53 for _, sym := range symbols {
54 _, score := matcher.Match([]string{sym})
55 t.Logf("Match(%q) = %v", sym, score)
56 if score < prev {
57 t.Errorf("Match(%q) = _, %v, want > %v", sym, score, prev)
58 }
59 prev = score
60 }
61}
62
Rob Findleyddfa2202023-05-08 17:03:33 -040063// Test that we strongly prefer exact matches.
64//
65// In golang/go#60027, we preferred "Runner" for the query "rune" over several
66// results containing the word "rune" exactly. Following this observation,
67// scoring was tweaked to more strongly emphasize sequential characters and
68// exact matches.
69func TestSymbolRanking_Issue60027(t *testing.T) {
70 matcher := NewSymbolMatcher("rune")
71
72 // symbols to match, in ascending order of ranking.
73 symbols := []string{
74 "Runner",
75 "singleRuneParam",
76 "Config.ifsRune",
77 "Parser.rune",
78 }
79 prev := 0.0
80 for _, sym := range symbols {
81 _, score := matcher.Match([]string{sym})
82 t.Logf("Match(%q) = %v", sym, score)
83 if score < prev {
84 t.Errorf("Match(%q) = _, %v, want > %v", sym, score, prev)
85 }
86 prev = score
87 }
88}
89
Robert Findleyb15dac22022-08-30 14:40:12 -040090func TestChunkedMatch(t *testing.T) {
91 matcher := NewSymbolMatcher("test")
92
93 chunked := [][]string{
94 {"test"},
95 {"", "test"},
96 {"test", ""},
97 {"te", "st"},
98 }
99
100 for _, chunks := range chunked {
101 offset, score := matcher.Match(chunks)
102 if offset != 0 || score != 1.0 {
103 t.Errorf("Match(%v) = %v, %v, want 0, 1.0", chunks, offset, score)
104 }
105 }
106}