182 lines
3.8 KiB
Go
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)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|