82 lines
2.6 KiB
Go
82 lines
2.6 KiB
Go
package engine
|
|
|
|
import (
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestPathPrefixIndexMatchesPointerScans(t *testing.T) {
|
|
entries := []struct {
|
|
pointer string
|
|
id int
|
|
}{
|
|
{pointer: "", id: 12},
|
|
{pointer: "/", id: 9},
|
|
{pointer: "/a", id: 6},
|
|
{pointer: "/a", id: 2},
|
|
{pointer: "/a/b", id: 4},
|
|
{pointer: "/a/b/c", id: 0},
|
|
{pointer: "/a/bc", id: 10},
|
|
{pointer: "/a~1b", id: 3},
|
|
{pointer: "/a~0b", id: 1},
|
|
{pointer: "/a~01b", id: 5},
|
|
{pointer: "/items/0", id: 8},
|
|
{pointer: "/items/01", id: 7},
|
|
{pointer: "/items/+1", id: 11},
|
|
}
|
|
var index pathPrefixIndex
|
|
for _, entry := range entries {
|
|
index.insert(entry.pointer, entry.id)
|
|
}
|
|
queries := []string{
|
|
"", "/", "/a", "/a/b", "/a/b/c", "/a/b/c/d", "/a/bc", "/a/bc/d",
|
|
"/a~1b", "/a~0b", "/a~01b", "/items", "/items/0", "/items/01", "/items/1", "/missing",
|
|
}
|
|
for _, query := range queries {
|
|
gotAncestors := make([]int, 0)
|
|
index.visitAncestors(query, func(id int) { gotAncestors = append(gotAncestors, id) })
|
|
wantAncestors := make([]int, 0)
|
|
gotDescendants := make([]int, 0)
|
|
wantDescendants := make([]int, 0)
|
|
wantEarliest, foundEarliest := 0, false
|
|
for _, entry := range entries {
|
|
if pointerContainsByString(entry.pointer, query) {
|
|
wantAncestors = append(wantAncestors, entry.id)
|
|
}
|
|
if pointerContainsByString(query, entry.pointer) {
|
|
wantDescendants = append(wantDescendants, entry.id)
|
|
}
|
|
if pointerContainsByString(entry.pointer, query) || pointerContainsByString(query, entry.pointer) {
|
|
if !foundEarliest || entry.id < wantEarliest {
|
|
wantEarliest, foundEarliest = entry.id, true
|
|
}
|
|
}
|
|
}
|
|
index.visitDescendants(query, func(id int) { gotDescendants = append(gotDescendants, id) })
|
|
if !slices.Equal(sortedPrefixIDs(gotAncestors), sortedPrefixIDs(wantAncestors)) {
|
|
t.Errorf("ancestors(%q) = %v, want %v", query, sortedPrefixIDs(gotAncestors), sortedPrefixIDs(wantAncestors))
|
|
}
|
|
if !slices.Equal(sortedPrefixIDs(gotDescendants), sortedPrefixIDs(wantDescendants)) {
|
|
t.Errorf("descendants(%q) = %v, want %v", query, sortedPrefixIDs(gotDescendants), sortedPrefixIDs(wantDescendants))
|
|
}
|
|
gotEarliest, gotFound := index.earliestIntersectingID(query)
|
|
if gotEarliest != wantEarliest || gotFound != foundEarliest {
|
|
t.Errorf("earliestIntersectingID(%q) = %d, %v, want %d, %v", query, gotEarliest, gotFound, wantEarliest, foundEarliest)
|
|
}
|
|
}
|
|
}
|
|
|
|
func pointerContainsByString(container, descendant string) bool {
|
|
if container == "" {
|
|
return true
|
|
}
|
|
return descendant == container || strings.HasPrefix(descendant, container+"/")
|
|
}
|
|
|
|
func sortedPrefixIDs(ids []int) []int {
|
|
result := slices.Clone(ids)
|
|
slices.Sort(result)
|
|
return result
|
|
}
|