score_test.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // License: GPLv3 Copyright: 2023, Kovid Goyal, <kovid at kovidgoyal.net>
  2. package subseq
  3. import (
  4. "fmt"
  5. "kitty/tools/utils"
  6. "strconv"
  7. "strings"
  8. "testing"
  9. "github.com/google/go-cmp/cmp"
  10. )
  11. var _ = fmt.Print
  12. func TestSubseq(t *testing.T) {
  13. var positions [][]int
  14. sort_by_score := false
  15. simple := func(items, query string, expected ...string) {
  16. matches := ScoreItems(query, utils.Splitlines(items), Options{})
  17. if sort_by_score {
  18. matches = utils.StableSort(matches, func(a, b *Match) int {
  19. if b.Score < a.Score {
  20. return -1
  21. }
  22. if b.Score > a.Score {
  23. return 1
  24. }
  25. return 0
  26. })
  27. }
  28. actual := make([]string, 0, len(matches))
  29. actual_positions := make([][]int, 0, len(matches))
  30. for _, m := range matches {
  31. if m.Score > 0 {
  32. actual = append(actual, m.Text)
  33. actual_positions = append(actual_positions, m.Positions)
  34. }
  35. }
  36. if expected == nil {
  37. expected = []string{}
  38. }
  39. if diff := cmp.Diff(expected, actual); diff != "" {
  40. t.Fatalf("Failed for items: %v\nMatches: %#v\n%s", utils.Splitlines(items), matches, diff)
  41. }
  42. if positions != nil {
  43. if diff := cmp.Diff(positions, actual_positions); diff != "" {
  44. t.Fatalf("Failed positions for items: %v\n%s", utils.Splitlines(items), diff)
  45. }
  46. positions = nil
  47. }
  48. }
  49. simple("test\nxyz", "te", "test")
  50. simple("abc\nxyz", "ba")
  51. simple("abc\n123", "abc", "abc")
  52. simple("test\nxyz", "Te", "test")
  53. simple("test\nxyz", "XY", "xyz")
  54. simple("test\nXYZ", "xy", "XYZ")
  55. simple("test\nXYZ", "mn")
  56. positions = [][]int{{0, 2}, {0, 1}}
  57. simple("abc\nac", "ac", "abc", "ac")
  58. positions = [][]int{{0}}
  59. simple("abc\nv", "a", "abc")
  60. positions = [][]int{{len("汉"), 7}}
  61. simple("汉a字b\nxyz", "ab", "汉a字b")
  62. sort_by_score = true
  63. // Match at start
  64. simple("archer\nelementary", "e", "elementary", "archer")
  65. // Match at level factor
  66. simple("xxxy\nxx/y", "y", "xx/y", "xxxy")
  67. // CamelCase
  68. simple("xxxy\nxxxY", "y", "xxxY", "xxxy")
  69. // Total length
  70. simple("xxxya\nxxxy", "y", "xxxy", "xxxya")
  71. // Distance
  72. simple("abbc\nabc", "ac", "abc", "abbc")
  73. // Extreme chars
  74. simple("xxa\naxx", "a", "axx", "xxa")
  75. // Highest score
  76. positions = [][]int{{3}}
  77. simple("xa/a", "a", "xa/a")
  78. sort_by_score = false
  79. items := make([]string, 256)
  80. for i := range items {
  81. items[i] = strconv.Itoa(i)
  82. }
  83. expected := make([]string, 0, len(items))
  84. for _, x := range items {
  85. if strings.ContainsRune(x, rune('2')) {
  86. expected = append(expected, x)
  87. }
  88. }
  89. simple(strings.Join(items, "\n"), "2", expected...)
  90. }