mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
adt: Visit() interval trees in sorted order and terminate early
For all intervals [x, y), Visit will visit intervals in ascending order sorted by x. Also fixes a bug where Visit would not terminate the search when requested by the visitor function.
This commit is contained in:
@@ -136,3 +136,98 @@ func TestIntervalTreeRandom(t *testing.T) {
|
||||
t.Errorf("got ivt.Len() = %v, expected 0", ivt.Len())
|
||||
}
|
||||
}
|
||||
|
||||
// TestIntervalTreeSortedVisit tests that intervals are visited in sorted order.
|
||||
func TestIntervalTreeSortedVisit(t *testing.T) {
|
||||
tests := []struct {
|
||||
ivls []Interval
|
||||
visitRange Interval
|
||||
}{
|
||||
{
|
||||
ivls: []Interval{NewInt64Interval(1, 10), NewInt64Interval(2, 5), NewInt64Interval(3, 6)},
|
||||
visitRange: NewInt64Interval(0, 100),
|
||||
},
|
||||
{
|
||||
ivls: []Interval{NewInt64Interval(1, 10), NewInt64Interval(10, 12), NewInt64Interval(3, 6)},
|
||||
visitRange: NewInt64Interval(0, 100),
|
||||
},
|
||||
{
|
||||
ivls: []Interval{NewInt64Interval(2, 3), NewInt64Interval(3, 4), NewInt64Interval(6, 7), NewInt64Interval(5, 6)},
|
||||
visitRange: NewInt64Interval(0, 100),
|
||||
},
|
||||
{
|
||||
ivls: []Interval{
|
||||
NewInt64Interval(2, 3),
|
||||
NewInt64Interval(2, 4),
|
||||
NewInt64Interval(3, 7),
|
||||
NewInt64Interval(2, 5),
|
||||
NewInt64Interval(3, 8),
|
||||
NewInt64Interval(3, 5),
|
||||
},
|
||||
visitRange: NewInt64Interval(0, 100),
|
||||
},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
ivt := &IntervalTree{}
|
||||
for _, ivl := range tt.ivls {
|
||||
ivt.Insert(ivl, struct{}{})
|
||||
}
|
||||
last := tt.ivls[0].Begin
|
||||
count := 0
|
||||
chk := func(iv *IntervalValue) bool {
|
||||
if last.Compare(iv.Ivl.Begin) > 0 {
|
||||
t.Errorf("#%d: expected less than %d, got interval %+v", i, last, iv.Ivl)
|
||||
}
|
||||
last = iv.Ivl.Begin
|
||||
count++
|
||||
return true
|
||||
}
|
||||
ivt.Visit(tt.visitRange, chk)
|
||||
if count != len(tt.ivls) {
|
||||
t.Errorf("#%d: did not cover all intervals. expected %d, got %d", i, len(tt.ivls), count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestIntervalTreeVisitExit tests that visiting can be stopped.
|
||||
func TestIntervalTreeVisitExit(t *testing.T) {
|
||||
ivls := []Interval{NewInt64Interval(1, 10), NewInt64Interval(2, 5), NewInt64Interval(3, 6), NewInt64Interval(4, 8)}
|
||||
ivlRange := NewInt64Interval(0, 100)
|
||||
tests := []struct {
|
||||
f IntervalVisitor
|
||||
|
||||
wcount int
|
||||
}{
|
||||
{
|
||||
f: func(n *IntervalValue) bool { return false },
|
||||
wcount: 1,
|
||||
},
|
||||
{
|
||||
f: func(n *IntervalValue) bool { return n.Ivl.Begin.Compare(ivls[0].Begin) <= 0 },
|
||||
wcount: 2,
|
||||
},
|
||||
{
|
||||
f: func(n *IntervalValue) bool { return n.Ivl.Begin.Compare(ivls[2].Begin) < 0 },
|
||||
wcount: 3,
|
||||
},
|
||||
{
|
||||
f: func(n *IntervalValue) bool { return true },
|
||||
wcount: 4,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
ivt := &IntervalTree{}
|
||||
for _, ivl := range ivls {
|
||||
ivt.Insert(ivl, struct{}{})
|
||||
}
|
||||
count := 0
|
||||
ivt.Visit(ivlRange, func(n *IntervalValue) bool {
|
||||
count++
|
||||
return tt.f(n)
|
||||
})
|
||||
if count != tt.wcount {
|
||||
t.Errorf("#%d: expected count %d, got %d", i, tt.wcount, count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user