interval_tree_test.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. // Copyright 2016 The etcd Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package adt
  15. import (
  16. "math/rand"
  17. "testing"
  18. "time"
  19. )
  20. func TestIntervalTreeContains(t *testing.T) {
  21. ivt := &IntervalTree{}
  22. ivt.Insert(NewStringInterval("1", "3"), 123)
  23. if ivt.Contains(NewStringPoint("0")) {
  24. t.Errorf("contains 0")
  25. }
  26. if !ivt.Contains(NewStringPoint("1")) {
  27. t.Errorf("missing 1")
  28. }
  29. if !ivt.Contains(NewStringPoint("11")) {
  30. t.Errorf("missing 11")
  31. }
  32. if !ivt.Contains(NewStringPoint("2")) {
  33. t.Errorf("missing 2")
  34. }
  35. if ivt.Contains(NewStringPoint("3")) {
  36. t.Errorf("contains 3")
  37. }
  38. }
  39. func TestIntervalTreeStringAffine(t *testing.T) {
  40. ivt := &IntervalTree{}
  41. ivt.Insert(NewStringAffineInterval("8", ""), 123)
  42. if !ivt.Contains(NewStringAffinePoint("9")) {
  43. t.Errorf("missing 9")
  44. }
  45. if ivt.Contains(NewStringAffinePoint("7")) {
  46. t.Errorf("contains 7")
  47. }
  48. }
  49. func TestIntervalTreeStab(t *testing.T) {
  50. ivt := &IntervalTree{}
  51. ivt.Insert(NewStringInterval("0", "1"), 123)
  52. ivt.Insert(NewStringInterval("0", "2"), 456)
  53. ivt.Insert(NewStringInterval("5", "6"), 789)
  54. ivt.Insert(NewStringInterval("6", "8"), 999)
  55. ivt.Insert(NewStringInterval("0", "3"), 0)
  56. if ivt.root.max.Compare(StringComparable("8")) != 0 {
  57. t.Fatalf("wrong root max got %v, expected 8", ivt.root.max)
  58. }
  59. if x := len(ivt.Stab(NewStringPoint("0"))); x != 3 {
  60. t.Errorf("got %d, expected 3", x)
  61. }
  62. if x := len(ivt.Stab(NewStringPoint("1"))); x != 2 {
  63. t.Errorf("got %d, expected 2", x)
  64. }
  65. if x := len(ivt.Stab(NewStringPoint("2"))); x != 1 {
  66. t.Errorf("got %d, expected 1", x)
  67. }
  68. if x := len(ivt.Stab(NewStringPoint("3"))); x != 0 {
  69. t.Errorf("got %d, expected 0", x)
  70. }
  71. if x := len(ivt.Stab(NewStringPoint("5"))); x != 1 {
  72. t.Errorf("got %d, expected 1", x)
  73. }
  74. if x := len(ivt.Stab(NewStringPoint("55"))); x != 1 {
  75. t.Errorf("got %d, expected 1", x)
  76. }
  77. if x := len(ivt.Stab(NewStringPoint("6"))); x != 1 {
  78. t.Errorf("got %d, expected 1", x)
  79. }
  80. }
  81. type xy struct {
  82. x int64
  83. y int64
  84. }
  85. func TestIntervalTreeRandom(t *testing.T) {
  86. // generate unique intervals
  87. ivs := make(map[xy]struct{})
  88. ivt := &IntervalTree{}
  89. maxv := 128
  90. rand.Seed(time.Now().UnixNano())
  91. for i := rand.Intn(maxv) + 1; i != 0; i-- {
  92. x, y := int64(rand.Intn(maxv)), int64(rand.Intn(maxv))
  93. if x > y {
  94. t := x
  95. x = y
  96. y = t
  97. } else if x == y {
  98. y++
  99. }
  100. iv := xy{x, y}
  101. if _, ok := ivs[iv]; ok {
  102. // don't double insert
  103. continue
  104. }
  105. ivt.Insert(NewInt64Interval(x, y), 123)
  106. ivs[iv] = struct{}{}
  107. }
  108. for ab := range ivs {
  109. for xy := range ivs {
  110. v := xy.x + int64(rand.Intn(int(xy.y-xy.x)))
  111. if slen := len(ivt.Stab(NewInt64Point(v))); slen == 0 {
  112. t.Fatalf("expected %v stab non-zero for [%+v)", v, xy)
  113. }
  114. if !ivt.Contains(NewInt64Point(v)) {
  115. t.Fatalf("did not get %d as expected for [%+v)", v, xy)
  116. }
  117. }
  118. if !ivt.Delete(NewInt64Interval(ab.x, ab.y)) {
  119. t.Errorf("did not delete %v as expected", ab)
  120. }
  121. delete(ivs, ab)
  122. }
  123. if ivt.Len() != 0 {
  124. t.Errorf("got ivt.Len() = %v, expected 0", ivt.Len())
  125. }
  126. }
  127. // TestIntervalTreeSortedVisit tests that intervals are visited in sorted order.
  128. func TestIntervalTreeSortedVisit(t *testing.T) {
  129. tests := []struct {
  130. ivls []Interval
  131. visitRange Interval
  132. }{
  133. {
  134. ivls: []Interval{NewInt64Interval(1, 10), NewInt64Interval(2, 5), NewInt64Interval(3, 6)},
  135. visitRange: NewInt64Interval(0, 100),
  136. },
  137. {
  138. ivls: []Interval{NewInt64Interval(1, 10), NewInt64Interval(10, 12), NewInt64Interval(3, 6)},
  139. visitRange: NewInt64Interval(0, 100),
  140. },
  141. {
  142. ivls: []Interval{NewInt64Interval(2, 3), NewInt64Interval(3, 4), NewInt64Interval(6, 7), NewInt64Interval(5, 6)},
  143. visitRange: NewInt64Interval(0, 100),
  144. },
  145. {
  146. ivls: []Interval{
  147. NewInt64Interval(2, 3),
  148. NewInt64Interval(2, 4),
  149. NewInt64Interval(3, 7),
  150. NewInt64Interval(2, 5),
  151. NewInt64Interval(3, 8),
  152. NewInt64Interval(3, 5),
  153. },
  154. visitRange: NewInt64Interval(0, 100),
  155. },
  156. }
  157. for i, tt := range tests {
  158. ivt := &IntervalTree{}
  159. for _, ivl := range tt.ivls {
  160. ivt.Insert(ivl, struct{}{})
  161. }
  162. last := tt.ivls[0].Begin
  163. count := 0
  164. chk := func(iv *IntervalValue) bool {
  165. if last.Compare(iv.Ivl.Begin) > 0 {
  166. t.Errorf("#%d: expected less than %d, got interval %+v", i, last, iv.Ivl)
  167. }
  168. last = iv.Ivl.Begin
  169. count++
  170. return true
  171. }
  172. ivt.Visit(tt.visitRange, chk)
  173. if count != len(tt.ivls) {
  174. t.Errorf("#%d: did not cover all intervals. expected %d, got %d", i, len(tt.ivls), count)
  175. }
  176. }
  177. }
  178. // TestIntervalTreeVisitExit tests that visiting can be stopped.
  179. func TestIntervalTreeVisitExit(t *testing.T) {
  180. ivls := []Interval{NewInt64Interval(1, 10), NewInt64Interval(2, 5), NewInt64Interval(3, 6), NewInt64Interval(4, 8)}
  181. ivlRange := NewInt64Interval(0, 100)
  182. tests := []struct {
  183. f IntervalVisitor
  184. wcount int
  185. }{
  186. {
  187. f: func(n *IntervalValue) bool { return false },
  188. wcount: 1,
  189. },
  190. {
  191. f: func(n *IntervalValue) bool { return n.Ivl.Begin.Compare(ivls[0].Begin) <= 0 },
  192. wcount: 2,
  193. },
  194. {
  195. f: func(n *IntervalValue) bool { return n.Ivl.Begin.Compare(ivls[2].Begin) < 0 },
  196. wcount: 3,
  197. },
  198. {
  199. f: func(n *IntervalValue) bool { return true },
  200. wcount: 4,
  201. },
  202. }
  203. for i, tt := range tests {
  204. ivt := &IntervalTree{}
  205. for _, ivl := range ivls {
  206. ivt.Insert(ivl, struct{}{})
  207. }
  208. count := 0
  209. ivt.Visit(ivlRange, func(n *IntervalValue) bool {
  210. count++
  211. return tt.f(n)
  212. })
  213. if count != tt.wcount {
  214. t.Errorf("#%d: expected count %d, got %d", i, tt.wcount, count)
  215. }
  216. }
  217. }