diff options
Diffstat (limited to 'stdlib/source/test/lux/control/interval.lux')
-rw-r--r-- | stdlib/source/test/lux/control/interval.lux | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/stdlib/source/test/lux/control/interval.lux b/stdlib/source/test/lux/control/interval.lux new file mode 100644 index 000000000..6d00a36e9 --- /dev/null +++ b/stdlib/source/test/lux/control/interval.lux @@ -0,0 +1,235 @@ +(.module: + lux/test + [lux #* + [control + ["M" monad (#+ do Monad)] + pipe + ["&" interval]] + [math + ["r" random]] + [data + ["." number] + [collection + ["S" set] + ["L" list]]]]) + +(context: "Equivalence." + (<| (times 100) + (do @ + [bottom r.int + top r.int + #let [(^open "&/.") &.equivalence]] + ($_ seq + (test "Every interval is equal to itself." + (and (let [self (&.between number.enum bottom top)] + (&/= self self)) + (let [self (&.between number.enum top bottom)] + (&/= self self)) + (let [self (&.singleton number.enum bottom)] + (&/= self self)))))))) + +(context: "Boundaries" + (<| (times 100) + (do @ + [bottom r.int + top r.int + #let [interval (&.between number.enum bottom top)]] + ($_ seq + (test "Every boundary value belongs to it's interval." + (and (&.within? interval bottom) + (&.within? interval top))) + (test "Every interval starts with its bottom." + (&.starts-with? bottom interval)) + (test "Every interval ends with its top." + (&.ends-with? top interval)) + (test "The boundary values border the interval." + (and (&.borders? interval bottom) + (&.borders? interval top))) + )))) + +(def: (list-to-4tuple list) + (-> (List Int) [Int Int Int Int]) + (case list + (^ (list x0 x1 x2 x3)) + [x0 x1 x2 x3] + + _ + (undefined))) + + +(do-template [<name> <cmp>] + [(def: <name> + (r.Random (&.Interval Int)) + (do r.monad + [bottom r.int + top (|> r.int (r.filter (|>> (i/= bottom) not)))] + (if (<cmp> top bottom) + (wrap (&.between number.enum bottom top)) + (wrap (&.between number.enum top bottom)))))] + + [gen-inner i/<] + [gen-outer i/>] + ) + +(def: gen-singleton + (r.Random (&.Interval Int)) + (do r.monad + [point r.int] + (wrap (&.singleton number.enum point)))) + +(def: gen-interval + (r.Random (&.Interval Int)) + ($_ r.either + gen-inner + gen-outer + gen-singleton)) + +(context: "Unions" + (<| (times 100) + (do @ + [some-interval gen-interval + left-inner gen-inner + right-inner gen-inner + left-singleton gen-singleton + right-singleton gen-singleton + left-outer gen-outer + right-outer gen-outer + #let [(^open "&/.") &.equivalence]] + ($_ seq + (test "The union of an interval to itself yields the same interval." + (&/= some-interval (&.union some-interval some-interval))) + (test "The union of 2 inner intervals is another inner interval." + (&.inner? (&.union left-inner right-inner))) + (test "The union of 2 outer intervals yields an inner interval when their complements don't overlap, and an outer when they do." + (if (&.overlaps? (&.complement left-outer) (&.complement right-outer)) + (&.outer? (&.union left-outer right-outer)) + (&.inner? (&.union left-outer right-outer)))) + )))) + +(context: "Intersections" + (<| (times 100) + (do @ + [some-interval gen-interval + left-inner gen-inner + right-inner gen-inner + left-singleton gen-singleton + right-singleton gen-singleton + left-outer gen-outer + right-outer gen-outer + #let [(^open "&/.") &.equivalence]] + ($_ seq + (test "The intersection of an interval to itself yields the same interval." + (&/= some-interval (&.intersection some-interval some-interval))) + (test "The intersection of 2 inner intervals yields an inner interval when they overlap, and an outer when they don't." + (if (&.overlaps? left-inner right-inner) + (&.inner? (&.intersection left-inner right-inner)) + (&.outer? (&.intersection left-inner right-inner)))) + (test "The intersection of 2 outer intervals is another outer interval." + (&.outer? (&.intersection left-outer right-outer))) + )))) + +(context: "Complement" + (<| (times 100) + (do @ + [some-interval gen-interval + #let [(^open "&/.") &.equivalence]] + ($_ seq + (test "The complement of a complement is the same as the original." + (&/= some-interval (|> some-interval &.complement &.complement))) + (test "The complement of an interval does not overlap it." + (not (&.overlaps? some-interval (&.complement some-interval)))) + )))) + +(context: "Positioning/location" + (<| (times 100) + (do @ + [[l m r] (|> (r.set number.hash 3 r.int) + (:: @ map (|>> S.to-list + (L.sort i/<) + (case> (^ (list b t1 t2)) + [b t1 t2] + + _ + (undefined))))) + #let [left (&.singleton number.enum l) + right (&.singleton number.enum r)]] + ($_ seq + (test "'precedes?' and 'succeeds?' are symetric." + (and (&.precedes? right left) + (&.succeeds? left right))) + (test "Can check if an interval is before or after some element." + (and (&.before? m left) + (&.after? m right))) + )))) + +(context: "Touching intervals" + (<| (times 100) + (do @ + [[b t1 t2] (|> (r.set number.hash 3 r.int) + (:: @ map (|>> S.to-list + (L.sort i/<) + (case> (^ (list b t1 t2)) + [b t1 t2] + + _ + (undefined))))) + #let [int-left (&.between number.enum t1 t2) + int-right (&.between number.enum b t1)]] + ($_ seq + (test "An interval meets another if it's top is the other's bottom." + (&.meets? int-left int-right)) + (test "Two intervals touch one another if any one meets the other." + (&.touches? int-left int-right)) + (test "Can check if 2 intervals start together." + (&.starts? (&.between number.enum b t2) + (&.between number.enum b t1))) + (test "Can check if 2 intervals finish together." + (&.finishes? (&.between number.enum b t2) + (&.between number.enum t1 t2))) + )))) + +(context: "Nesting & overlap" + (<| (times 100) + (do @ + [some-interval gen-interval + [x0 x1 x2 x3] (|> (r.set number.hash 4 r.int) + (:: @ map (|>> S.to-list + (L.sort i/<) + (case> (^ (list x0 x1 x2 x3)) + [x0 x1 x2 x3] + + _ + (undefined)))))] + ($_ seq + (test "Every interval is nested into itself." + (&.nested? some-interval some-interval)) + (test "No interval overlaps with itself." + (not (&.overlaps? some-interval some-interval))) + (let [small-inner (&.between number.enum x1 x2) + large-inner (&.between number.enum x0 x3)] + (test "Inner intervals can be nested inside one another." + (and (&.nested? large-inner small-inner) + (not (&.nested? small-inner large-inner))))) + (let [left-inner (&.between number.enum x0 x2) + right-inner (&.between number.enum x1 x3)] + (test "Inner intervals can overlap one another." + (and (&.overlaps? left-inner right-inner) + (&.overlaps? right-inner left-inner)))) + (let [small-outer (&.between number.enum x2 x1) + large-outer (&.between number.enum x3 x0)] + (test "Outer intervals can be nested inside one another." + (and (&.nested? small-outer large-outer) + (not (&.nested? large-outer small-outer))))) + (let [left-inner (&.between number.enum x0 x1) + right-inner (&.between number.enum x2 x3) + outer (&.between number.enum x0 x3)] + (test "Inners can be nested inside outers." + (and (&.nested? outer left-inner) + (&.nested? outer right-inner)))) + (let [left-inner (&.between number.enum x0 x2) + right-inner (&.between number.enum x1 x3) + outer (&.between number.enum x1 x2)] + (test "Inners can overlap outers." + (and (&.overlaps? outer left-inner) + (&.overlaps? outer right-inner)))) + )))) |