UNPKG

strange

Version:

Range aka interval object. Supports exclusive and infinite ranges. Comes with an interval tree (augmented binary search tree).

318 lines (267 loc) 10.5 kB
var Range = require("..") var RangeTree = require("../tree") describe("RangeTree", function() { describe(".prototype.search", function() { describe("given value", function() { it("must return an empty array if empty", function() { var tree = RangeTree.from([]) tree.search(42).must.be.empty() }) it("must return an empty array if not found within 1", function() { var tree = RangeTree.from([new Range(0, 10)]) tree.search(42).must.be.empty() }) it("must return an empty array if with exclusive left boundary", function() { var tree = RangeTree.from([new Range(0, 10, "(]")]) tree.search(0).must.be.empty() }) it("must return an empty array if with exclusive right boundary", function() { var tree = RangeTree.from([new Range(0, 10, "[)")]) tree.search(10).must.be.empty() }) it("must return an empty array if not found within 3", function() { var ranges = [new Range(0, 10), new Range(15, 25), new Range(30, 40)] var tree = RangeTree.from(ranges) tree.search(42).must.be.empty() }) it("must return range if within 1", function() { var tree = RangeTree.from([new Range(0, 10)]) tree.search(5).must.eql([new Range(0, 10)]) }) it("must return range if within 2", function() { var tree = RangeTree.from([new Range(0, 10), new Range(20, 30)]) tree.search(5).must.eql([new Range(0, 10)]) tree.search(25).must.eql([new Range(20, 30)]) }) it("must return range if within 3", function() { var ranges = [new Range(0, 10), new Range(20, 30), new Range(40, 50)] var tree = RangeTree.from(ranges) tree.search(5).must.eql([new Range(0, 10)]) tree.search(25).must.eql([new Range(20, 30)]) tree.search(45).must.eql([new Range(40, 50)]) }) it("must return range if multiple with equal begin", function() { var tree = RangeTree.from([ new Range(0, 20), new Range(10, 25), new Range(15, 35), new Range(15, 40), ]) tree.search(37).must.eql([new Range(15, 40)]) }) it("must return multiple ranges if within 3", function() { var ranges = [new Range(0, 20), new Range(15, 35), new Range(30, 40)] var tree = RangeTree.from(ranges) tree.search(35).must.eql([new Range(15, 35), new Range(30, 40)]) }) it("must return multiple ranges with equal begin", function() { // Use plenty of ranges to ensure a naive dividing tree construction // puts the duplicate ranges further apart. var tree = RangeTree.from([ new Range(0, 20), new Range(10, 25), new Range(15, 35), new Range(15, 40), new Range(35, 40), new Range(35, 50) ]) tree.search(30).must.eql([new Range(15, 35), new Range(15, 40)]) }) it("must return multiple ranges if on two sides", function() { var tree = RangeTree.from([ new Range(0, 15), new Range(5, 5), new Range(10, 25) ]) tree.search(13).must.eql([new Range(0, 15), new Range(10, 25)]) }) it("must return multiple ranges if all equal", function() { var tree = RangeTree.from([new Range(5, 15), new Range(5, 15)]) tree.search(10).must.eql([new Range(5, 15), new Range(5, 15)]) }) it("must return multiple ranges if one equal but exclusive", function() { var tree = RangeTree.from([ new Range(5, 15), new Range(5, 10, "[)"), new Range(10, 15, "(]"), new Range(10, 20) ]) tree.search(10).must.eql([new Range(5, 15), new Range(10, 20)]) }) it("must return multiple ranges ordered by ascending end", function() { var tree = RangeTree.from([ new Range(0, 10), new Range(0, 15), new Range(0, 5) ]) tree.search(5).must.eql([ new Range(0, 5), new Range(0, 10), new Range(0, 15) ]) }) // This was a bug noticed on Jan 15, 2017 where an empty range caused // none to be matched. it("must return range if one empty", function() { var tree = RangeTree.from([new Range, new Range(0, 10)]) tree.search(5).must.eql([new Range(0, 10)]) }) }) describe("given range", function() { it("must return an empty array if empty", function() { var tree = RangeTree.from([]) tree.search(new Range(42, 69)).must.be.empty() }) it("must return an empty array if not found within 1", function() { var tree = RangeTree.from([new Range(0, 10)]) tree.search(new Range(42, 69)).must.be.empty() }) it("must return an empty array if with exclusive left boundary", function() { var tree = RangeTree.from([new Range(0, 10, "(]")]) tree.search(new Range(-10, 0)).must.be.empty() }) it("must return an empty array if with exclusive right boundary", function() { var tree = RangeTree.from([new Range(0, 10, "[)")]) tree.search(new Range(10, 20)).must.be.empty() }) it("must return an empty array if not found within 3", function() { var ranges = [new Range(0, 10), new Range(15, 25), new Range(30, 40)] var tree = RangeTree.from(ranges) tree.search(new Range(42, 69)).must.be.empty() }) it("must return range if within 1", function() { var tree = RangeTree.from([new Range(0, 10)]) tree.search(new Range(2, 7)).must.eql([new Range(0, 10)]) }) it("must return range if within 2", function() { var tree = RangeTree.from([new Range(0, 10), new Range(20, 30)]) tree.search(new Range(2, 7)).must.eql([new Range(0, 10)]) tree.search(new Range(22, 27)).must.eql([new Range(20, 30)]) }) it("must return range if within 3", function() { var ranges = [new Range(0, 10), new Range(20, 30), new Range(40, 50)] var tree = RangeTree.from(ranges) tree.search(new Range(2, 7)).must.eql([new Range(0, 10)]) tree.search(new Range(22, 27)).must.eql([new Range(20, 30)]) tree.search(new Range(42, 47)).must.eql([new Range(40, 50)]) }) it("must return range if multiple with equal begin", function() { var tree = RangeTree.from([ new Range(0, 20), new Range(10, 25), new Range(15, 35), new Range(15, 40), ]) tree.search(new Range(37, 39)).must.eql([new Range(15, 40)]) }) it("must return multiple ranges if within 3", function() { var ranges = [new Range(0, 20), new Range(15, 35), new Range(30, 40)] var tree = RangeTree.from(ranges) tree.search(new Range(32, 37)).must.eql([ new Range(15, 35), new Range(30, 40) ]) }) it("must return multiple ranges with equal begin", function() { // Use plenty of ranges to ensure a naive dividing tree construction // puts the duplicate ranges further apart. var tree = RangeTree.from([ new Range(0, 20), new Range(10, 25), new Range(15, 35), new Range(15, 40), new Range(35, 40), new Range(35, 50) ]) tree.search(new Range(30, 32)).must.eql([ new Range(15, 35), new Range(15, 40) ]) }) it("must return multiple ranges if on two sides", function() { var tree = RangeTree.from([ new Range(0, 15), new Range(5, 5), new Range(10, 25) ]) tree.search(new Range(6, 13)).must.eql([ new Range(0, 15), new Range(10, 25) ]) }) it("must return multiple ranges if all equal", function() { var tree = RangeTree.from([new Range(5, 15), new Range(5, 15)]) tree.search(new Range(7, 13)).must.eql([ new Range(5, 15), new Range(5, 15) ]) }) it("must return multiple ranges if one equal but exclusive", function() { var tree = RangeTree.from([ new Range(5, 15), new Range(5, 10, "[)"), new Range(10, 15, "(]"), new Range(10, 20) ]) tree.search(new Range(10, 10)).must.eql([ new Range(5, 15), new Range(10, 20) ]) }) it("must return multiple ranges ordered by ascending end", function() { var tree = RangeTree.from([ new Range(0, 10), new Range(0, 15), new Range(0, 5) ]) tree.search(new Range(3, 7)).must.eql([ new Range(0, 5), new Range(0, 10), new Range(0, 15) ]) }) // This was a bug #2 (https://github.com/moll/js-strange/issues/2) where // a node's total range end was not set properly because it considered // the range(s) to the right of it to always end farther. it("must return range farther than later ranges", function() { var tree = RangeTree.from([ new Range(-5, 5), new Range(0, 15), new Range(5, 10) ]) tree.search(new Range(12, 13)).must.eql([new Range(0, 15)]) }) // The original bug report for the bug above had long timestamps that // I normalized below. Keeping them here as more insurance. it("must return range farther than later ranges in original bug report", function() { var tree = RangeTree.from([ new Range(10, 20, "[)"), new Range(20, 30, "[)"), new Range(30, 40, "[)"), new Range(40, 50, "[)"), new Range(50, 60, "[)"), new Range(80, 100, "[)"), new Range(85, 86, "[)"), ]) var matches = tree.search(new Range(90, 95, "[)")) matches.must.eql([new Range(80, 100, "[)")]) }) it("must not return ranges if exclusive", function() { var tree = RangeTree.from([ new Range(0, 10, "[)"), new Range(20, 30, "(]") ]) tree.search(new Range(10, 20)).must.eql([]) }) it("must not return ranges if exclusive and side by side", function() { var tree = RangeTree.from([new Range(0, 10, "[)")]) tree.search(new Range(10, 15, "[)")).must.eql([]) }) }) }) })