test.js 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. var util = require('util')
  2. var tape = require('tape')
  3. var createIntervalTree = require('../interval-tree.js')
  4. function cmpInterval(a, b) {
  5. var d = a[0] - b[0]
  6. if(d) { return d }
  7. return a[1] - b[1]
  8. }
  9. tape('fuzz test', function(t) {
  10. function verifyTree(tree, intervals) {
  11. function testInterval(x) {
  12. var expected = []
  13. if(x[0] <= x[1])
  14. for(var j=0; j<intervals.length; ++j) {
  15. var y = intervals[j]
  16. if(x[1] >= y[0] && y[1] >= x[0]) {
  17. expected.push(y)
  18. }
  19. }
  20. expected.sort(cmpInterval)
  21. var actual = []
  22. tree.queryInterval(x[0], x[1], function(j) {
  23. actual.push(j)
  24. })
  25. actual.sort(cmpInterval)
  26. t.same(actual, expected, 'query interval: ' + x)
  27. }
  28. for(var i=0; i<intervals.length; ++i) {
  29. testInterval(intervals[i])
  30. }
  31. testInterval([-Infinity, Infinity])
  32. testInterval([0,0])
  33. testInterval([Infinity, -Infinity])
  34. for(var i=0; i<100; ++i) {
  35. testInterval([Math.random(), 2*Math.random()])
  36. }
  37. //Verify queryPoint
  38. function testPoint(p) {
  39. var expected = []
  40. for(var j=0; j<intervals.length; ++j) {
  41. var y = intervals[j]
  42. if(y[0] <= p && p <= y[1]) {
  43. expected.push(y)
  44. }
  45. }
  46. expected.sort(cmpInterval)
  47. var actual = []
  48. tree.queryPoint(p, function(y) {
  49. actual.push(y)
  50. })
  51. actual.sort(cmpInterval)
  52. t.same(actual, expected, 'query point: ' + p)
  53. }
  54. for(var i=0; i<intervals.length; ++i) {
  55. testPoint(intervals[i][0])
  56. testPoint(intervals[i][1])
  57. }
  58. testPoint(0)
  59. testPoint(-1)
  60. testPoint(1)
  61. testPoint(-Infinity)
  62. testPoint(Infinity)
  63. for(var i=0; i<100; ++i) {
  64. testPoint(Math.random())
  65. }
  66. //Check tree contents
  67. t.equals(tree.count, intervals.length, 'interval count ok')
  68. var treeIntervals = tree.intervals.slice()
  69. treeIntervals.sort(cmpInterval)
  70. var expectedIntervals = intervals.slice()
  71. expectedIntervals.sort(cmpInterval)
  72. t.same(treeIntervals, expectedIntervals, 'intervals same')
  73. //Check tree invariants
  74. function verifyNode(node, left, right) {
  75. if(!node) {
  76. return 0
  77. }
  78. var midp = node.mid
  79. t.ok(left < midp && midp < right, 'mid point in range: ' + node.mid + ' in ' + [left,right])
  80. //Verify left end points in ascending order
  81. var leftP = node.leftPoints.slice()
  82. for(var i=0; i<leftP.length; ++ i) {
  83. if(i > 0) {
  84. t.ok(leftP[i][0] >= leftP[i-1][0], 'order ok')
  85. }
  86. var y = leftP[i]
  87. t.ok(y[0] <= midp && midp <= y[1], 'interval ok')
  88. }
  89. //Verify right end points in ascending order
  90. var rightP = node.rightPoints.slice()
  91. for(var i=0; i<rightP.length; ++ i) {
  92. if(i > 0) {
  93. t.ok(rightP[i][1] >= rightP[i-1][1], 'order ok')
  94. }
  95. var y = rightP[i]
  96. t.ok(y[0] <= midp && midp <= y[1], 'interval ok')
  97. }
  98. leftP.sort(cmpInterval)
  99. rightP.sort(cmpInterval)
  100. t.same(leftP, rightP, 'intervals are consistent')
  101. var leftCount = verifyNode(node.left, left, node.mid)
  102. var rightCount = verifyNode(node.right, node.mid, right)
  103. var actualCount = leftCount + rightCount + leftP.length
  104. t.equals(node.count, actualCount, 'node count consistent')
  105. return actualCount
  106. }
  107. verifyNode(tree.root, -Infinity, Infinity)
  108. }
  109. //Check empty tree
  110. verifyTree(createIntervalTree(), [])
  111. //Try trees with uniformly distributed end points
  112. for(var count=0; count<10; ++count) {
  113. //Create empty tree and insert 100 intervals
  114. var intervals = []
  115. var tree = createIntervalTree()
  116. for(var i=0; i<100; ++i) {
  117. var a = Math.random()
  118. var b = a + Math.random()
  119. var x = [a,b]
  120. intervals.push(x)
  121. tree.insert(x)
  122. }
  123. verifyTree(tree, intervals)
  124. //Remove half the intervals
  125. for(var i=99; i>=50; --i) {
  126. tree.remove(intervals.pop())
  127. }
  128. verifyTree(tree, intervals)
  129. }
  130. //Trees with quantized end points
  131. for(var count=0; count<10; ++count) {
  132. //Create empty tree and insert 100 intervals
  133. var intervals = []
  134. var tree = createIntervalTree()
  135. for(var i=0; i<100; ++i) {
  136. var a = Math.floor(8.0*Math.random())/8.0
  137. var b = Math.max(a + Math.floor(8.0*Math.random())/8.0, 1.0)
  138. var x = [a,b]
  139. intervals.push(x)
  140. tree.insert(x)
  141. }
  142. verifyTree(tree, intervals)
  143. //Remove half the intervals
  144. for(var i=99; i>=50; --i) {
  145. tree.remove(intervals.pop())
  146. }
  147. verifyTree(tree, intervals)
  148. }
  149. var stackIntervals = []
  150. for(var i=0; i<100; ++i) {
  151. stackIntervals.push([i/200, 1.0-(i/200)])
  152. }
  153. var tree = createIntervalTree(stackIntervals)
  154. verifyTree(tree, stackIntervals)
  155. t.end()
  156. })
  157. tape('containment', function(t) {
  158. var tree = createIntervalTree([[0, 100]])
  159. var count = 0
  160. function incr() { count++ }
  161. tree.queryInterval(10, 20, incr)
  162. t.equals(count, 1)
  163. count = 0;
  164. tree.queryInterval(100, 100, incr)
  165. t.equals(count, 1)
  166. count = 0;
  167. tree.queryInterval(110, 111, incr)
  168. t.equals(count, 0)
  169. var tree = createIntervalTree([[0, 20], [30, 50]])
  170. count = 0
  171. tree.queryInterval(10, 15, incr)
  172. t.equals(count, 1)
  173. count = 0
  174. tree.queryInterval(25, 26, incr)
  175. t.equals(count, 0)
  176. count = 0
  177. tree.queryInterval(35, 40, incr)
  178. t.equals(count, 1)
  179. t.end()
  180. })