star/bed/searcher/searcher_test.go
2025-04-26 19:33:14 +08:00

182 lines
3.8 KiB
Go

package searcher
import (
"strings"
"testing"
)
func TestSearcher(t *testing.T) {
testCases := []struct {
name string
str string
cursor int64
pattern string
forward bool
expected int64
err error
}{
{
name: "search forward",
str: "abcde",
cursor: 0,
pattern: "cd",
forward: true,
expected: 2,
},
{
name: "search forward but not found",
str: "abcde",
cursor: 2,
pattern: "cd",
forward: true,
err: errNotFound("cd"),
},
{
name: "search backward",
str: "abcde",
cursor: 4,
pattern: "bc",
forward: false,
expected: 1,
},
{
name: "search backward but not found",
str: "abcde",
cursor: 0,
pattern: "ba",
forward: true,
err: errNotFound("ba"),
},
{
name: "search large target forward",
str: strings.Repeat(" ", 10*1024*1024+100) + "abcde",
cursor: 102,
pattern: "bcd",
forward: true,
expected: 10*1024*1024 + 101,
},
{
name: "search large target forward but not found",
str: strings.Repeat(" ", 10*1024*1024+100) + "abcde",
cursor: 102,
pattern: "cba",
forward: true,
err: errNotFound("cba"),
},
{
name: "search large target backward",
str: "abcde" + strings.Repeat(" ", 10*1024*1024),
cursor: 10*1024*1024 + 2,
pattern: "bcd",
forward: false,
expected: 1,
},
{
name: "search large target backward but not found",
str: "abcde" + strings.Repeat(" ", 10*1024*1024),
cursor: 10*1024*1024 + 2,
pattern: "cba",
forward: false,
err: errNotFound("cba"),
},
{
name: "search hex",
str: "\x13\x24\x35\x46\x57\x68",
cursor: 0,
pattern: `\x35\x46\x57`,
forward: true,
expected: 2,
},
{
name: "search nul",
str: "\x06\x07\x08\x00\x09\x10\x11",
cursor: 0,
pattern: `\0`,
forward: true,
expected: 3,
},
{
name: "search bell and bs",
str: "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0b\x09\x0a",
cursor: 0,
pattern: `\a\b\v`,
forward: true,
expected: 7,
},
{
name: "search tab",
str: "\x06\x07\x08\x09\x10\x11",
cursor: 0,
pattern: `\t`,
forward: true,
expected: 3,
},
{
name: "search escape character",
str: `ab\cd\\e`,
cursor: 0,
pattern: `\\\`,
forward: true,
expected: 5,
},
{
name: "search unicode",
str: "\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf",
cursor: 0,
pattern: `\u3061\u306F`,
forward: true,
expected: 9,
},
{
name: "search unicode in supplementary multilingual plane",
str: "\U0001F604\U0001F606\U0001F60E\U0001F60D\U0001F642",
cursor: 0,
pattern: `\U0001F60E\U0001F60D`,
forward: true,
expected: 8,
},
{
name: "search hex literal",
str: "\x16\x27\x38\x49\x50\x61",
cursor: 0,
pattern: `0x38495`,
forward: true,
expected: 2,
},
{
name: "search bin literal",
str: "\x16\x27\x38\x48\x50\x61",
cursor: 0,
pattern: `0b0011100001001`,
forward: true,
expected: 2,
},
{
name: "search text starting with 0",
str: "432101234",
cursor: 0,
pattern: `0123`,
forward: true,
expected: 4,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
s := NewSearcher(strings.NewReader(testCase.str))
ch := s.Search(testCase.cursor, testCase.pattern, testCase.forward)
switch x := (<-ch).(type) {
case error:
if testCase.err == nil {
t.Error(x)
} else if x != testCase.err {
t.Errorf("Error should be %v but got %v", testCase.err, x)
}
case int64:
if x != testCase.expected {
t.Errorf("Search result should be %d but got %d", testCase.expected, x)
}
}
})
}
}