From 83f18eb967cfaa4f3403f58f3f80bc4945218cd8 Mon Sep 17 00:00:00 2001 From: Eduardo Julian Date: Tue, 10 Jul 2018 20:42:57 -0400 Subject: - Re-named path "lux/data/coll/*" to "lux/data/collection/*". --- stdlib/test/test/lux/cli.lux | 2 +- stdlib/test/test/lux/concurrency/atom.lux | 2 +- stdlib/test/test/lux/concurrency/frp.lux | 2 +- stdlib/test/test/lux/concurrency/semaphore.lux | 2 +- stdlib/test/test/lux/concurrency/stm.lux | 2 +- stdlib/test/test/lux/control/continuation.lux | 2 +- stdlib/test/test/lux/control/interval.lux | 4 +- stdlib/test/test/lux/control/region.lux | 2 +- stdlib/test/test/lux/data/coll/array.lux | 140 ------------ stdlib/test/test/lux/data/coll/bits.lux | 80 ------- stdlib/test/test/lux/data/coll/dictionary.lux | 128 ----------- .../test/test/lux/data/coll/dictionary/ordered.lux | 88 -------- stdlib/test/test/lux/data/coll/list.lux | 235 --------------------- stdlib/test/test/lux/data/coll/queue.lux | 51 ----- stdlib/test/test/lux/data/coll/queue/priority.lux | 52 ----- stdlib/test/test/lux/data/coll/row.lux | 73 ------- stdlib/test/test/lux/data/coll/sequence.lux | 101 --------- stdlib/test/test/lux/data/coll/set.lux | 64 ------ stdlib/test/test/lux/data/coll/set/ordered.lux | 94 --------- stdlib/test/test/lux/data/coll/stack.lux | 45 ---- stdlib/test/test/lux/data/coll/tree/rose.lux | 47 ----- .../test/test/lux/data/coll/tree/rose/zipper.lux | 124 ----------- stdlib/test/test/lux/data/collection/array.lux | 140 ++++++++++++ stdlib/test/test/lux/data/collection/bits.lux | 80 +++++++ .../test/test/lux/data/collection/dictionary.lux | 128 +++++++++++ .../lux/data/collection/dictionary/ordered.lux | 88 ++++++++ stdlib/test/test/lux/data/collection/list.lux | 235 +++++++++++++++++++++ stdlib/test/test/lux/data/collection/queue.lux | 51 +++++ .../test/lux/data/collection/queue/priority.lux | 52 +++++ stdlib/test/test/lux/data/collection/row.lux | 73 +++++++ stdlib/test/test/lux/data/collection/sequence.lux | 101 +++++++++ stdlib/test/test/lux/data/collection/set.lux | 64 ++++++ .../test/test/lux/data/collection/set/ordered.lux | 94 +++++++++ stdlib/test/test/lux/data/collection/stack.lux | 45 ++++ stdlib/test/test/lux/data/collection/tree/rose.lux | 47 +++++ .../test/lux/data/collection/tree/rose/zipper.lux | 124 +++++++++++ stdlib/test/test/lux/data/format/json.lux | 6 +- stdlib/test/test/lux/data/format/xml.lux | 4 +- stdlib/test/test/lux/data/number/complex.lux | 2 +- stdlib/test/test/lux/data/sum.lux | 2 +- stdlib/test/test/lux/data/text.lux | 2 +- stdlib/test/test/lux/data/text/lexer.lux | 2 +- .../test/test/lux/lang/compiler/analysis/case.lux | 4 +- .../test/lux/lang/compiler/analysis/function.lux | 2 +- .../lang/compiler/analysis/procedure/common.lux | 2 +- .../lang/compiler/analysis/procedure/host.jvm.lux | 6 +- .../test/lux/lang/compiler/analysis/structure.lux | 4 +- .../test/lux/lang/compiler/synthesis/function.lux | 6 +- .../test/lux/lang/compiler/synthesis/structure.lux | 2 +- stdlib/test/test/lux/lang/syntax.lux | 4 +- stdlib/test/test/lux/lang/type.lux | 2 +- stdlib/test/test/lux/lang/type/check.lux | 4 +- stdlib/test/test/lux/macro/poly/equivalence.lux | 2 +- stdlib/test/test/lux/math/logic/fuzzy.lux | 4 +- stdlib/test/test/lux/math/random.lux | 14 +- stdlib/test/test/lux/type/implicit.lux | 2 +- stdlib/test/test/lux/type/object/interface.lux | 2 +- stdlib/test/test/lux/world/blob.lux | 2 +- 58 files changed, 1371 insertions(+), 1371 deletions(-) delete mode 100644 stdlib/test/test/lux/data/coll/array.lux delete mode 100644 stdlib/test/test/lux/data/coll/bits.lux delete mode 100644 stdlib/test/test/lux/data/coll/dictionary.lux delete mode 100644 stdlib/test/test/lux/data/coll/dictionary/ordered.lux delete mode 100644 stdlib/test/test/lux/data/coll/list.lux delete mode 100644 stdlib/test/test/lux/data/coll/queue.lux delete mode 100644 stdlib/test/test/lux/data/coll/queue/priority.lux delete mode 100644 stdlib/test/test/lux/data/coll/row.lux delete mode 100644 stdlib/test/test/lux/data/coll/sequence.lux delete mode 100644 stdlib/test/test/lux/data/coll/set.lux delete mode 100644 stdlib/test/test/lux/data/coll/set/ordered.lux delete mode 100644 stdlib/test/test/lux/data/coll/stack.lux delete mode 100644 stdlib/test/test/lux/data/coll/tree/rose.lux delete mode 100644 stdlib/test/test/lux/data/coll/tree/rose/zipper.lux create mode 100644 stdlib/test/test/lux/data/collection/array.lux create mode 100644 stdlib/test/test/lux/data/collection/bits.lux create mode 100644 stdlib/test/test/lux/data/collection/dictionary.lux create mode 100644 stdlib/test/test/lux/data/collection/dictionary/ordered.lux create mode 100644 stdlib/test/test/lux/data/collection/list.lux create mode 100644 stdlib/test/test/lux/data/collection/queue.lux create mode 100644 stdlib/test/test/lux/data/collection/queue/priority.lux create mode 100644 stdlib/test/test/lux/data/collection/row.lux create mode 100644 stdlib/test/test/lux/data/collection/sequence.lux create mode 100644 stdlib/test/test/lux/data/collection/set.lux create mode 100644 stdlib/test/test/lux/data/collection/set/ordered.lux create mode 100644 stdlib/test/test/lux/data/collection/stack.lux create mode 100644 stdlib/test/test/lux/data/collection/tree/rose.lux create mode 100644 stdlib/test/test/lux/data/collection/tree/rose/zipper.lux (limited to 'stdlib/test') diff --git a/stdlib/test/test/lux/cli.lux b/stdlib/test/test/lux/cli.lux index b8bc50e9e..bd0ed72d8 100644 --- a/stdlib/test/test/lux/cli.lux +++ b/stdlib/test/test/lux/cli.lux @@ -10,7 +10,7 @@ [number] [text "text/" Equivalence] text/format - (coll [list])) + (collection [list])) ["r" math/random] ["/" cli]) lux/test) diff --git a/stdlib/test/test/lux/concurrency/atom.lux b/stdlib/test/test/lux/concurrency/atom.lux index a4856252a..b6c220b28 100644 --- a/stdlib/test/test/lux/concurrency/atom.lux +++ b/stdlib/test/test/lux/concurrency/atom.lux @@ -3,7 +3,7 @@ (lux [io] (control ["M" monad #+ do Monad]) (data [number] - (coll [list "" Functor]) + (collection [list "" Functor]) text/format) (concurrency ["&" atom]) ["r" math/random]) diff --git a/stdlib/test/test/lux/concurrency/frp.lux b/stdlib/test/test/lux/concurrency/frp.lux index 8a1e04849..7760ad806 100644 --- a/stdlib/test/test/lux/concurrency/frp.lux +++ b/stdlib/test/test/lux/concurrency/frp.lux @@ -4,7 +4,7 @@ (control [monad #+ do Monad]) (data [number] text/format - (coll [list])) + (collection [list])) (concurrency [promise #+ "promise/" Monad] [frp #+ Channel] [atom #+ Atom atom])) diff --git a/stdlib/test/test/lux/concurrency/semaphore.lux b/stdlib/test/test/lux/concurrency/semaphore.lux index 0100ee2ac..294f2c5e2 100644 --- a/stdlib/test/test/lux/concurrency/semaphore.lux +++ b/stdlib/test/test/lux/concurrency/semaphore.lux @@ -4,7 +4,7 @@ (data [maybe] [text "text/" Equivalence Monoid] text/format - (coll [list "list/" Functor])) + (collection [list "list/" Functor])) (concurrency ["/" semaphore] [promise #+ Promise] [atom #+ Atom]) diff --git a/stdlib/test/test/lux/concurrency/stm.lux b/stdlib/test/test/lux/concurrency/stm.lux index 4bebfa3e7..23dbb6850 100644 --- a/stdlib/test/test/lux/concurrency/stm.lux +++ b/stdlib/test/test/lux/concurrency/stm.lux @@ -4,7 +4,7 @@ (control ["M" monad #+ do Monad]) (data [number] [maybe] - (coll [list "" Functor "List/" Fold]) + (collection [list "" Functor "List/" Fold]) text/format) (concurrency [atom #+ Atom atom] ["&" stm] diff --git a/stdlib/test/test/lux/control/continuation.lux b/stdlib/test/test/lux/control/continuation.lux index bda63e3e1..c5fa339d0 100644 --- a/stdlib/test/test/lux/control/continuation.lux +++ b/stdlib/test/test/lux/control/continuation.lux @@ -7,7 +7,7 @@ text/format [number] [product] - (coll [list])) + (collection [list])) ["r" math/random]) lux/test) diff --git a/stdlib/test/test/lux/control/interval.lux b/stdlib/test/test/lux/control/interval.lux index 6b6e96789..99dd14b4e 100644 --- a/stdlib/test/test/lux/control/interval.lux +++ b/stdlib/test/test/lux/control/interval.lux @@ -8,8 +8,8 @@ ["r" math/random] (data text/format [number] - (coll ["S" set] - ["L" list])))) + (collection ["S" set] + ["L" list])))) (context: "Equivalence." (<| (times +100) diff --git a/stdlib/test/test/lux/control/region.lux b/stdlib/test/test/lux/control/region.lux index 48b2b1b7f..d0a2fb11d 100644 --- a/stdlib/test/test/lux/control/region.lux +++ b/stdlib/test/test/lux/control/region.lux @@ -5,7 +5,7 @@ [thread #+ Thread] ["ex" exception #+ exception:]) (data ["e" error #+ Error] - (coll [list]) + (collection [list]) text/format) ["r" math/random]) lux/test) diff --git a/stdlib/test/test/lux/data/coll/array.lux b/stdlib/test/test/lux/data/coll/array.lux deleted file mode 100644 index c29baefc3..000000000 --- a/stdlib/test/test/lux/data/coll/array.lux +++ /dev/null @@ -1,140 +0,0 @@ -(.module: - lux - (lux (control [monad #+ do Monad] - pipe) - [io] - (data (coll ["@" array] - [list]) - [number] - [maybe]) - ["r" math/random]) - lux/test) - -(def: bounded-size - (r.Random Nat) - (|> r.nat - (:: r.Monad map (|>> (n/% +100) (n/+ +1))))) - -(context: "Arrays and their copies" - (<| (times +100) - (do @ - [size bounded-size - original (r.array size r.nat) - #let [clone (@.clone original) - copy (: (Array Nat) - (@.new size)) - manual-copy (: (Array Nat) - (@.new size))]] - ($_ seq - (test "Size function must correctly return size of array." - (n/= size (@.size original))) - (test "Cloning an array should yield and identical array, but not the same one." - (and (:: (@.Equivalence number.Equivalence) = original clone) - (not (is? original clone)))) - (test "Full-range manual copies should give the same result as cloning." - (exec (@.copy size +0 original +0 copy) - (and (:: (@.Equivalence number.Equivalence) = original copy) - (not (is? original copy))))) - (test "Array folding should go over all values." - (exec (:: @.Fold fold - (function (_ x idx) - (exec (@.write idx x manual-copy) - (inc idx))) - +0 - original) - (:: (@.Equivalence number.Equivalence) = original manual-copy))) - (test "Transformations between (full) arrays and lists shouldn't cause lose or change any values." - (|> original - @.to-list @.from-list - (:: (@.Equivalence number.Equivalence) = original))) - )))) - -(context: "Array mutation" - (<| (times +100) - (do @ - [size bounded-size - idx (:: @ map (n/% size) r.nat) - array (|> (r.array size r.nat) - (r.filter (|>> @.to-list (list.any? n/odd?)))) - #let [value (maybe.assume (@.read idx array))]] - ($_ seq - (test "Shouldn't be able to find a value in an unoccupied cell." - (case (@.read idx (@.delete idx array)) - (#.Some _) false - #.None true)) - (test "You should be able to access values put into the array." - (case (@.read idx (@.write idx value array)) - (#.Some value') (n/= value' value) - #.None false)) - (test "All cells should be occupied on a full array." - (and (n/= size (@.occupied array)) - (n/= +0 (@.vacant array)))) - (test "Filtering mutates the array to remove invalid values." - (exec (@.filter n/even? array) - (and (n/< size (@.occupied array)) - (n/> +0 (@.vacant array)) - (n/= size (n/+ (@.occupied array) - (@.vacant array)))))) - )))) - -(context: "Finding values." - (<| (times +100) - (do @ - [size bounded-size - array (|> (r.array size r.nat) - (r.filter (|>> @.to-list (list.any? n/even?))))] - ($_ seq - (test "Can find values inside arrays." - (|> (@.find n/even? array) - (case> (#.Some _) true - #.None false))) - (test "Can find values inside arrays (with access to indices)." - (|> (@.find+ (function (_ idx n) - (and (n/even? n) - (n/< size idx))) - array) - (case> (#.Some _) true - #.None false))))))) - -(context: "Functor" - (<| (times +100) - (do @ - [size bounded-size - array (r.array size r.nat)] - (let [(^open) @.Functor - (^open) (@.Equivalence number.Equivalence)] - ($_ seq - (test "Functor shouldn't alter original array." - (let [copy (map id array)] - (and (= array copy) - (not (is? array copy))))) - (test "Functor should go over all available array elements." - (let [there (map inc array) - back-again (map dec there)] - (and (not (= array there)) - (= array back-again))))))))) - -(context: "Monoid" - (<| (times +100) - (do @ - [sizeL bounded-size - sizeR bounded-size - left (r.array sizeL r.nat) - right (r.array sizeR r.nat) - #let [(^open) @.Monoid - (^open) (@.Equivalence number.Equivalence) - fusion (compose left right)]] - ($_ seq - (test "Appending two arrays should produce a new one twice as large." - (n/= (n/+ sizeL sizeR) (@.size fusion))) - (test "First elements of fused array should equal the first array." - (|> (: (Array Nat) - (@.new sizeL)) - (@.copy sizeL +0 fusion +0) - (= left))) - (test "Last elements of fused array should equal the second array." - (|> (: (Array Nat) - (@.new sizeR)) - (@.copy sizeR sizeL fusion +0) - (= right))) - )))) diff --git a/stdlib/test/test/lux/data/coll/bits.lux b/stdlib/test/test/lux/data/coll/bits.lux deleted file mode 100644 index 0fbe2edb2..000000000 --- a/stdlib/test/test/lux/data/coll/bits.lux +++ /dev/null @@ -1,80 +0,0 @@ -(.module: - lux - (lux (control [monad #+ do] - [predicate]) - (data (coll ["/" bits])) - ["r" math/random]) - lux/test - (test (lux (control ["_eq" equivalence])))) - -(def: (size min max) - (-> Nat Nat (r.Random Nat)) - (|> r.nat - (:: r.Monad map (|>> (n/% max) (n/max min))))) - -(def: bits - (r.Random /.Bits) - (do r.Monad - [size (size +1 +1_000) - idx (|> r.nat (:: @ map (n/% size)))] - (wrap (|> /.empty (/.set idx))))) - -(context: "Bits." - (<| (times +100) - (do @ - [size (size +1 +1_000) - idx (|> r.nat (:: @ map (n/% size))) - sample bits] - ($_ seq - (test "Can set individual bits." - (and (|> /.empty (/.get idx) not) - (|> /.empty (/.set idx) (/.get idx)))) - (test "Can clear individual bits." - (|> /.empty (/.set idx) (/.clear idx) (/.get idx) not)) - (test "Can flip individual bits." - (and (|> /.empty (/.flip idx) (/.get idx)) - (|> /.empty (/.flip idx) (/.flip idx) (/.get idx) not))) - - (test "Bits (only) grow when (and as much as) necessary." - (and (n/= +0 (/.capacity /.empty)) - (|> /.empty (/.set idx) /.capacity - (n/- idx) - (predicate.union (n/>= +0) - (n/< /.chunk-size))))) - (test "Bits (must) shrink when (and as much as) possible." - (let [grown (/.flip idx /.empty)] - (and (n/> +0 (/.capacity grown)) - (is? /.empty (/.flip idx grown))))) - - (test "Intersection can be detected when there are set bits in common." - (and (not (/.intersects? /.empty - /.empty)) - (/.intersects? (/.set idx /.empty) - (/.set idx /.empty)) - (not (/.intersects? (/.set (inc idx) /.empty) - (/.set idx /.empty))))) - (test "Cannot intersect with one's opposite." - (not (/.intersects? sample (/.not sample)))) - - (test "'and' with oneself changes nothing" - (:: /.Equivalence = sample (/.and sample sample))) - (test "'and' with one's opposite yields the empty bit-set." - (is? /.empty (/.and sample (/.not sample)))) - - (test "'or' with one's opposite fully saturates a bit-set." - (n/= (/.size (/.or sample (/.not sample))) - (/.capacity sample))) - - (test "'xor' with oneself yields the empty bit-set." - (is? /.empty (/.xor sample sample))) - (test "'xor' with one's opposite fully saturates a bit-set." - (n/= (/.size (/.xor sample (/.not sample))) - (/.capacity sample))) - - (test "Double negation results in original bit-set." - (:: /.Equivalence = sample (/.not (/.not sample)))) - (test "Negation does not affect the empty bit-set." - (is? /.empty (/.not /.empty))) - - (_eq.spec /.Equivalence ..bits) - )))) diff --git a/stdlib/test/test/lux/data/coll/dictionary.lux b/stdlib/test/test/lux/data/coll/dictionary.lux deleted file mode 100644 index 9c652ee7a..000000000 --- a/stdlib/test/test/lux/data/coll/dictionary.lux +++ /dev/null @@ -1,128 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad] - ["eq" equivalence]) - (data [text] - text/format - [number] - [maybe] - (coll ["&" dictionary] - [list "list/" Fold Functor])) - ["r" math/random]) - lux/test) - -(context: "Dictionaries." - (<| (times +100) - (do @ - [#let [capped-nat (:: r.Monad map (n/% +100) r.nat)] - size capped-nat - dict (r.dictionary number.Hash size r.nat capped-nat) - non-key (|> r.nat (r.filter (function (_ key) (not (&.contains? key dict))))) - test-val (|> r.nat (r.filter (function (_ val) (not (list.member? number.Equivalence (&.values dict) val)))))] - ($_ seq - (test "Size function should correctly represent Dictionary size." - (n/= size (&.size dict))) - - (test "Dictionaries of size 0 should be considered empty." - (if (n/= +0 size) - (&.empty? dict) - (not (&.empty? dict)))) - - (test "The functions 'entries', 'keys' and 'values' should be synchronized." - (:: (list.Equivalence (eq.product number.Equivalence number.Equivalence)) = - (&.entries dict) - (list.zip2 (&.keys dict) - (&.values dict)))) - - (test "Dictionary should be able to recognize it's own keys." - (list.every? (function (_ key) (&.contains? key dict)) - (&.keys dict))) - - (test "Should be able to get every key." - (list.every? (function (_ key) (case (&.get key dict) - (#.Some _) true - _ false)) - (&.keys dict))) - - (test "Shouldn't be able to access non-existant keys." - (case (&.get non-key dict) - (#.Some _) false - _ true)) - - (test "Should be able to put and then get a value." - (case (&.get non-key (&.put non-key test-val dict)) - (#.Some v) (n/= test-val v) - _ true)) - - (test "Should be able to put~ and then get a value." - (case (&.get non-key (&.put~ non-key test-val dict)) - (#.Some v) (n/= test-val v) - _ true)) - - (test "Shouldn't be able to put~ an existing key." - (or (n/= +0 size) - (let [first-key (|> dict &.keys list.head maybe.assume)] - (case (&.get first-key (&.put~ first-key test-val dict)) - (#.Some v) (not (n/= test-val v)) - _ true)))) - - (test "Removing a key should make it's value inaccessible." - (let [base (&.put non-key test-val dict)] - (and (&.contains? non-key base) - (not (&.contains? non-key (&.remove non-key base)))))) - - (test "Should be possible to update values via their keys." - (let [base (&.put non-key test-val dict) - updt (&.update non-key inc base)] - (case [(&.get non-key base) (&.get non-key updt)] - [(#.Some x) (#.Some y)] - (n/= (inc x) y) - - _ - false))) - - (test "Additions and removals to a Dictionary should affect its size." - (let [plus (&.put non-key test-val dict) - base (&.remove non-key plus)] - (and (n/= (inc (&.size dict)) (&.size plus)) - (n/= (dec (&.size plus)) (&.size base))))) - - (test "A Dictionary should equal itself & going to<->from lists shouldn't change that." - (let [(^open) (&.Equivalence number.Equivalence)] - (and (= dict dict) - (|> dict &.entries (&.from-list number.Hash) (= dict))))) - - (test "Merging a Dictionary to itself changes nothing." - (let [(^open) (&.Equivalence number.Equivalence)] - (= dict (&.merge dict dict)))) - - (test "If you merge, and the second dict has overlapping keys, it should overwrite yours." - (let [dict' (|> dict &.entries - (list/map (function (_ [k v]) [k (inc v)])) - (&.from-list number.Hash)) - (^open) (&.Equivalence number.Equivalence)] - (= dict' (&.merge dict' dict)))) - - (test "Can merge values in such a way that they become combined." - (list.every? (function (_ [x x*2]) (n/= (n/* +2 x) x*2)) - (list.zip2 (&.values dict) - (&.values (&.merge-with n/+ dict dict))))) - - (test "Should be able to select subset of keys from dict." - (|> dict - (&.put non-key test-val) - (&.select (list non-key)) - &.size - (n/= +1))) - - (test "Should be able to re-bind existing values to different keys." - (or (n/= +0 size) - (let [first-key (|> dict &.keys list.head maybe.assume) - rebound (&.re-bind first-key non-key dict)] - (and (n/= (&.size dict) (&.size rebound)) - (&.contains? non-key rebound) - (not (&.contains? first-key rebound)) - (n/= (maybe.assume (&.get first-key dict)) - (maybe.assume (&.get non-key rebound))))))) - )))) diff --git a/stdlib/test/test/lux/data/coll/dictionary/ordered.lux b/stdlib/test/test/lux/data/coll/dictionary/ordered.lux deleted file mode 100644 index 548fd7f83..000000000 --- a/stdlib/test/test/lux/data/coll/dictionary/ordered.lux +++ /dev/null @@ -1,88 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad] - [equivalence #+ Equivalence]) - (data [product] - [number] - (coll ["s" set] - ["dict" dictionary] - (dictionary ["&" ordered]) - [list "L/" Functor])) - ["r" math/random]) - lux/test) - -(context: "Dictionary" - (<| (times +100) - (do @ - [size (|> r.nat (:: @ map (n/% +100))) - keys (r.set number.Hash size r.nat) - values (r.set number.Hash size r.nat) - extra-key (|> r.nat (r.filter (|>> (s.member? keys) not))) - extra-value r.nat - #let [pairs (list.zip2 (s.to-list keys) - (s.to-list values)) - sample (&.from-list number.Order pairs) - sorted-pairs (list.sort (function (_ [left _] [right _]) - (n/< left right)) - pairs) - sorted-values (L/map product.right sorted-pairs) - (^open "&/") (&.Equivalence number.Equivalence)]] - ($_ seq - (test "Can query the size of a dictionary." - (n/= size (&.size sample))) - - (test "Can query value for minimum key." - (case [(&.min sample) (list.head sorted-values)] - [#.None #.None] - true - - [(#.Some reference) (#.Some sample)] - (n/= reference sample) - - _ - false)) - - (test "Can query value for maximum key." - (case [(&.max sample) (list.last sorted-values)] - [#.None #.None] - true - - [(#.Some reference) (#.Some sample)] - (n/= reference sample) - - _ - false)) - - (test "Converting dictionaries to/from lists cannot change their values." - (|> sample - &.entries (&.from-list number.Order) - (&/= sample))) - - (test "Order is preserved." - (let [(^open "L/") (list.Equivalence (: (Equivalence [Nat Nat]) - (function (_ [kr vr] [ks vs]) - (and (n/= kr ks) - (n/= vr vs)))))] - (L/= (&.entries sample) - sorted-pairs))) - - (test "Every key in a dictionary must be identifiable." - (list.every? (function (_ key) (&.contains? key sample)) - (&.keys sample))) - - (test "Can add and remove elements in a dictionary." - (and (not (&.contains? extra-key sample)) - (let [sample' (&.put extra-key extra-value sample) - sample'' (&.remove extra-key sample')] - (and (&.contains? extra-key sample') - (not (&.contains? extra-key sample'')) - (case [(&.get extra-key sample') - (&.get extra-key sample'')] - [(#.Some found) #.None] - (n/= extra-value found) - - _ - false))) - )) - )))) diff --git a/stdlib/test/test/lux/data/coll/list.lux b/stdlib/test/test/lux/data/coll/list.lux deleted file mode 100644 index d57b19b9c..000000000 --- a/stdlib/test/test/lux/data/coll/list.lux +++ /dev/null @@ -1,235 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad] - pipe) - (data (coll ["&" list]) - [number] - [bool] - [product] - [maybe]) - ["r" math/random]) - lux/test) - -(def: bounded-size - (r.Random Nat) - (|> r.nat - (:: r.Monad map (|>> (n/% +100) (n/+ +10))))) - -(context: "Lists: Part 1" - (<| (times +100) - (do @ - [size bounded-size - idx (:: @ map (n/% size) r.nat) - sample (r.list size r.nat) - other-size bounded-size - other-sample (r.list other-size r.nat) - separator r.nat - #let [(^open) (&.Equivalence number.Equivalence) - (^open "&/") &.Functor]] - ($_ seq - (test "The size function should correctly portray the size of the list." - (n/= size (&.size sample))) - - (test "The repeat function should produce as many elements as asked of it." - (n/= size (&.size (&.repeat size [])))) - - (test "Reversing a list does not change it's size." - (n/= (&.size sample) - (&.size (&.reverse sample)))) - - (test "Reversing a list twice results in the original list." - (= sample - (&.reverse (&.reverse sample)))) - - (test "Filtering by a predicate and its complement should result in a number of elements equal to the original list." - (and (n/= (&.size sample) - (n/+ (&.size (&.filter n/even? sample)) - (&.size (&.filter (bool.complement n/even?) sample)))) - (let [[plus minus] (&.partition n/even? sample)] - (n/= (&.size sample) - (n/+ (&.size plus) - (&.size minus)))))) - - (test "If every element in a list satisfies a predicate, there can't be any that satisfy its complement." - (if (&.every? n/even? sample) - (and (not (&.any? (bool.complement n/even?) sample)) - (&.empty? (&.filter (bool.complement n/even?) sample))) - (&.any? (bool.complement n/even?) sample))) - - (test "Any element of the list can be considered its member." - (let [elem (maybe.assume (&.nth idx sample))] - (&.member? number.Equivalence sample elem))) - )))) - -(context: "Lists: Part 2" - (<| (times +100) - (do @ - [size bounded-size - idx (:: @ map (n/% size) r.nat) - sample (r.list size r.nat) - other-size bounded-size - other-sample (r.list other-size r.nat) - separator r.nat - #let [(^open) (&.Equivalence number.Equivalence) - (^open "&/") &.Functor]] - ($_ seq - (test "Appending the head and the tail should yield the original list." - (let [head (maybe.assume (&.head sample)) - tail (maybe.assume (&.tail sample))] - (= sample - (#.Cons head tail)))) - - (test "Appending the inits and the last should yield the original list." - (let [(^open) &.Monoid - inits (maybe.assume (&.inits sample)) - last (maybe.assume (&.last sample))] - (= sample - (compose inits (list last))))) - - (test "Functor should go over every element of the list." - (let [(^open) &.Functor - there (map inc sample) - back-again (map dec there)] - (and (not (= sample there)) - (= sample back-again)))) - - (test "Splitting a list into chunks and re-appending them should yield the original list." - (let [(^open) &.Monoid - [left right] (&.split idx sample) - [left' right'] (&.split-with n/even? sample)] - (and (= sample - (compose left right)) - (= sample - (compose left' right')) - (= sample - (compose (&.take idx sample) - (&.drop idx sample))) - (= sample - (compose (&.take-while n/even? sample) - (&.drop-while n/even? sample))) - ))) - - (test "Segmenting the list in pairs should yield as many elements as N/2." - (n/= (n// +2 size) - (&.size (&.as-pairs sample)))) - - (test "Sorting a list shouldn't change it's size." - (n/= (&.size sample) - (&.size (&.sort n/< sample)))) - - (test "Sorting a list with one order should yield the reverse of sorting it with the opposite order." - (= (&.sort n/< sample) - (&.reverse (&.sort n/> sample)))) - )))) - -(context: "Lists: Part 3" - (<| (times +100) - (do @ - [size bounded-size - idx (:: @ map (n/% size) r.nat) - sample (r.list size r.nat) - other-size bounded-size - other-sample (r.list other-size r.nat) - separator r.nat - from (|> r.nat (:: @ map (n/% +10))) - to (|> r.nat (:: @ map (n/% +10))) - #let [(^open) (&.Equivalence number.Equivalence) - (^open "&/") &.Functor]] - ($_ seq - (test "If you zip 2 lists, the result's size will be that of the smaller list." - (n/= (&.size (&.zip2 sample other-sample)) - (n/min (&.size sample) (&.size other-sample)))) - - (test "I can pair-up elements of a list in order." - (let [(^open) &.Functor - zipped (&.zip2 sample other-sample) - num-zipper (&.size zipped)] - (and (|> zipped (map product.left) (= (&.take num-zipper sample))) - (|> zipped (map product.right) (= (&.take num-zipper other-sample)))))) - - (test "You can generate indices for any size, and they will be in ascending order." - (let [(^open) &.Functor - indices (&.indices size)] - (and (n/= size (&.size indices)) - (= indices - (&.sort n/< indices)) - (&.every? (n/= (dec size)) - (&.zip2-with n/+ - indices - (&.sort n/> indices))) - ))) - - (test "The 'interpose' function places a value between every member of a list." - (let [(^open) &.Functor - sample+ (&.interpose separator sample)] - (and (n/= (|> size (n/* +2) dec) - (&.size sample+)) - (|> sample+ &.as-pairs (map product.right) (&.every? (n/= separator)))))) - - (test "List append is a monoid." - (let [(^open) &.Monoid] - (and (= sample (compose identity sample)) - (= sample (compose sample identity)) - (let [[left right] (&.split size (compose sample other-sample))] - (and (= sample left) - (= other-sample right)))))) - - (test "Apply allows you to create singleton lists, and apply lists of functions to lists of values." - (let [(^open) &.Monad - (^open) &.Apply] - (and (= (list separator) (wrap separator)) - (= (map inc sample) - (apply (wrap inc) sample))))) - - (test "List concatenation is a monad." - (let [(^open) &.Monad - (^open) &.Monoid] - (= (compose sample other-sample) - (join (list sample other-sample))))) - - (test "You can find any value that satisfies some criterium, if such values exist in the list." - (case (&.find n/even? sample) - (#.Some found) - (and (n/even? found) - (&.any? n/even? sample) - (not (&.every? (bool.complement n/even?) sample))) - - #.None - (and (not (&.any? n/even? sample)) - (&.every? (bool.complement n/even?) sample)))) - - (test "You can iteratively construct a list, generating values until you're done." - (= (&.n/range +0 (dec size)) - (&.iterate (function (_ n) (if (n/< size n) (#.Some (inc n)) #.None)) - +0))) - - (test "Can enumerate all elements in a list." - (let [enum-sample (&.enumerate sample)] - (and (= (&.indices (&.size enum-sample)) - (&/map product.left enum-sample)) - (= sample - (&/map product.right enum-sample))))) - - (test "Ranges can be constructed forward and backwards." - (and (let [(^open "list/") (&.Equivalence number.Equivalence)] - (list/= (&.n/range from to) - (&.reverse (&.n/range to from)))) - (let [(^open "list/") (&.Equivalence number.Equivalence) - from (.int from) - to (.int to)] - (list/= (&.i/range from to) - (&.reverse (&.i/range to from)))))) - )))) - -## TODO: Add again once new-luxc becomes the standard compiler. -(context: "Monad transformer" - (let [lift (&.lift io.Monad) - (^open "io/") io.Monad] - (test "Can add list functionality to any monad." - (|> (io.run (do (&.ListT io.Monad) - [a (lift (io/wrap 123)) - b (wrap 456)] - (wrap (i/+ a b)))) - (case> (^ (list 579)) true - _ false))))) diff --git a/stdlib/test/test/lux/data/coll/queue.lux b/stdlib/test/test/lux/data/coll/queue.lux deleted file mode 100644 index 12d924963..000000000 --- a/stdlib/test/test/lux/data/coll/queue.lux +++ /dev/null @@ -1,51 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad]) - (data (coll ["&" queue]) - [number]) - ["r" math/random]) - lux/test) - -(context: "Queues" - (<| (times +100) - (do @ - [size (:: @ map (n/% +100) r.nat) - sample (r.queue size r.nat) - non-member (|> r.nat - (r.filter (|>> (&.member? number.Equivalence sample) not)))] - ($_ seq - (test "I can query the size of a queue (and empty queues have size 0)." - (if (n/= +0 size) - (&.empty? sample) - (n/= size (&.size sample)))) - - (test "Enqueueing and dequeing affects the size of queues." - (and (n/= (inc size) (&.size (&.push non-member sample))) - (or (&.empty? sample) - (n/= (dec size) (&.size (&.pop sample)))) - (n/= size (&.size (&.pop (&.push non-member sample)))))) - - (test "Transforming to/from list can't change the queue." - (let [(^open "&/") (&.Equivalence number.Equivalence)] - (|> sample - &.to-list &.from-list - (&/= sample)))) - - (test "I can always peek at a non-empty queue." - (case (&.peek sample) - #.None (&.empty? sample) - (#.Some _) true)) - - (test "I can query whether an element belongs to a queue." - (and (not (&.member? number.Equivalence sample non-member)) - (&.member? number.Equivalence (&.push non-member sample) - non-member) - (case (&.peek sample) - #.None - (&.empty? sample) - - (#.Some first) - (and (&.member? number.Equivalence sample first) - (not (&.member? number.Equivalence (&.pop sample) first)))))) - )))) diff --git a/stdlib/test/test/lux/data/coll/queue/priority.lux b/stdlib/test/test/lux/data/coll/queue/priority.lux deleted file mode 100644 index 17664056c..000000000 --- a/stdlib/test/test/lux/data/coll/queue/priority.lux +++ /dev/null @@ -1,52 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad]) - (data (coll (queue ["&" priority])) - [number] - [maybe]) - ["r" math/random]) - lux/test) - -(def: (gen-queue size) - (-> Nat (r.Random (&.Queue Nat))) - (do r.Monad - [inputs (r.list size r.nat)] - (monad.fold @ (function (_ head tail) - (do @ - [priority r.nat] - (wrap (&.push priority head tail)))) - &.empty - inputs))) - -(context: "Queues" - (<| (times +100) - (do @ - [size (|> r.nat (:: @ map (n/% +100))) - sample (gen-queue size) - non-member-priority r.nat - non-member (|> r.nat (r.filter (|>> (&.member? number.Equivalence sample) not)))] - ($_ seq - (test "I can query the size of a queue (and empty queues have size 0)." - (n/= size (&.size sample))) - - (test "Enqueueing and dequeing affects the size of queues." - (and (n/= (inc size) - (&.size (&.push non-member-priority non-member sample))) - (or (n/= +0 (&.size sample)) - (n/= (dec size) - (&.size (&.pop sample)))))) - - (test "I can query whether an element belongs to a queue." - (and (and (not (&.member? number.Equivalence sample non-member)) - (&.member? number.Equivalence - (&.push non-member-priority non-member sample) - non-member)) - (or (n/= +0 (&.size sample)) - (and (&.member? number.Equivalence - sample - (maybe.assume (&.peek sample))) - (not (&.member? number.Equivalence - (&.pop sample) - (maybe.assume (&.peek sample)))))))) - )))) diff --git a/stdlib/test/test/lux/data/coll/row.lux b/stdlib/test/test/lux/data/coll/row.lux deleted file mode 100644 index 643dcbe24..000000000 --- a/stdlib/test/test/lux/data/coll/row.lux +++ /dev/null @@ -1,73 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad]) - (data (coll ["&" row] - [list "list/" Fold]) - [number] - [maybe]) - ["r" math/random]) - lux/test) - -(context: "Rows" - (<| (times +100) - (do @ - [size (|> r.nat (:: @ map (|>> (n/% +100) (n/max +1)))) - idx (|> r.nat (:: @ map (n/% size))) - sample (r.row size r.nat) - other-sample (r.row size r.nat) - non-member (|> r.nat (r.filter (|>> (&.member? number.Equivalence sample) not))) - #let [(^open "&/") (&.Equivalence number.Equivalence) - (^open "&/") &.Apply - (^open "&/") &.Monad - (^open "&/") &.Fold - (^open "&/") &.Monoid]] - ($_ seq - (test "Can query size of row." - (if (&.empty? sample) - (and (n/= +0 size) - (n/= +0 (&.size sample))) - (n/= size (&.size sample)))) - - (test "Can add and remove elements to rows." - (and (n/= (inc size) (&.size (&.add non-member sample))) - (n/= (dec size) (&.size (&.pop sample))))) - - (test "Can put and get elements into rows." - (|> sample - (&.put idx non-member) - (&.nth idx) - maybe.assume - (is? non-member))) - - (test "Can update elements of rows." - (|> sample - (&.put idx non-member) (&.update idx inc) - (&.nth idx) maybe.assume - (n/= (inc non-member)))) - - (test "Can safely transform to/from lists." - (|> sample &.to-list &.from-list (&/= sample))) - - (test "Can identify members of a row." - (and (not (&.member? number.Equivalence sample non-member)) - (&.member? number.Equivalence (&.add non-member sample) non-member))) - - (test "Can fold over elements of row." - (n/= (list/fold n/+ +0 (&.to-list sample)) - (&/fold n/+ +0 sample))) - - (test "Functor goes over every element." - (let [there (&/map inc sample) - back-again (&/map dec there)] - (and (not (&/= sample there)) - (&/= sample back-again)))) - - (test "Apply allows you to create singleton rows, and apply rows of functions to rows of values." - (and (&/= (&.row non-member) (&/wrap non-member)) - (&/= (&/map inc sample) (&/apply (&/wrap inc) sample)))) - - (test "Row concatenation is a monad." - (&/= (&/compose sample other-sample) - (&/join (&.row sample other-sample)))) - )))) diff --git a/stdlib/test/test/lux/data/coll/sequence.lux b/stdlib/test/test/lux/data/coll/sequence.lux deleted file mode 100644 index d1e91bcd1..000000000 --- a/stdlib/test/test/lux/data/coll/sequence.lux +++ /dev/null @@ -1,101 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad] - comonad) - (data [maybe] - [text "Text/" Monoid] - text/format - (coll [list] - ["&" sequence]) - [number "Nat/" Codec]) - ["r" math/random]) - lux/test) - -(context: "Sequences" - (<| (times +100) - (do @ - [size (|> r.nat (:: @ map (|>> (n/% +100) (n/max +2)))) - offset (|> r.nat (:: @ map (n/% +100))) - factor (|> r.nat (:: @ map (|>> (n/% +100) (n/max +2)))) - elem r.nat - cycle-seed (r.list size r.nat) - cycle-sample-idx (|> r.nat (:: @ map (n/% +1000))) - #let [(^open "List/") (list.Equivalence number.Equivalence) - sample0 (&.iterate inc +0) - sample1 (&.iterate inc offset)]] - ($_ seq - (test "Can move along a sequence and take slices off it." - (and (and (List/= (list.n/range +0 (dec size)) - (&.take size sample0)) - (List/= (list.n/range offset (dec (n/+ offset size))) - (&.take size (&.drop offset sample0))) - (let [[drops takes] (&.split size sample0)] - (and (List/= (list.n/range +0 (dec size)) - drops) - (List/= (list.n/range size (dec (n/* +2 size))) - (&.take size takes))))) - (and (List/= (list.n/range +0 (dec size)) - (&.take-while (n/< size) sample0)) - (List/= (list.n/range offset (dec (n/+ offset size))) - (&.take-while (n/< (n/+ offset size)) - (&.drop-while (n/< offset) sample0))) - (let [[drops takes] (&.split-while (n/< size) sample0)] - (and (List/= (list.n/range +0 (dec size)) - drops) - (List/= (list.n/range size (dec (n/* +2 size))) - (&.take-while (n/< (n/* +2 size)) takes))))) - )) - - (test "Can repeat any element and infinite number of times." - (n/= elem (&.nth offset (&.repeat elem)))) - - (test "Can obtain the head & tail of a sequence." - (and (n/= offset (&.head sample1)) - (List/= (list.n/range (inc offset) (n/+ offset size)) - (&.take size (&.tail sample1))))) - - (test "Can filter sequences." - (and (n/= (n/* +2 offset) - (&.nth offset - (&.filter n/even? sample0))) - (let [[evens odds] (&.partition n/even? (&.iterate inc +0))] - (and (n/= (n/* +2 offset) - (&.nth offset evens)) - (n/= (inc (n/* +2 offset)) - (&.nth offset odds)))))) - - (test "Functor goes over 'all' elements in a sequence." - (let [(^open "&/") &.Functor - there (&/map (n/* factor) sample0) - back-again (&/map (n// factor) there)] - (and (not (List/= (&.take size sample0) - (&.take size there))) - (List/= (&.take size sample0) - (&.take size back-again))))) - - (test "CoMonad produces a value for every element in a sequence." - (let [(^open "&/") &.Functor] - (List/= (&.take size (&/map (n/* factor) sample1)) - (&.take size - (be &.CoMonad - [inputs sample1] - (n/* factor (&.head inputs))))))) - - (test "'unfold' generalizes 'iterate'." - (let [(^open "&/") &.Functor - (^open "List/") (list.Equivalence text.Equivalence)] - (List/= (&.take size - (&/map Nat/encode (&.iterate inc offset))) - (&.take size - (&.unfold (function (_ n) [(inc n) (Nat/encode n)]) - offset))))) - - (test "Can cycle over the same elements as an infinite sequence." - (|> (&.cycle cycle-seed) - maybe.assume - (&.nth cycle-sample-idx) - (n/= (|> cycle-seed - (list.nth (n/% size cycle-sample-idx)) - maybe.assume)))) - )))) diff --git a/stdlib/test/test/lux/data/coll/set.lux b/stdlib/test/test/lux/data/coll/set.lux deleted file mode 100644 index 6b341ee3a..000000000 --- a/stdlib/test/test/lux/data/coll/set.lux +++ /dev/null @@ -1,64 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad]) - (data (coll ["&" set #+ Set] - [list "" Fold]) - [number]) - ["r" math/random]) - lux/test) - -(def: gen-nat - (r.Random Nat) - (|> r.nat - (:: r.Monad map (n/% +100)))) - -(context: "Sets" - (<| (times +100) - (do @ - [sizeL gen-nat - sizeR gen-nat - setL (r.set number.Hash sizeL gen-nat) - setR (r.set number.Hash sizeR gen-nat) - non-member (|> gen-nat - (r.filter (|>> (&.member? setL) not))) - #let [(^open "&/") &.Equivalence]] - ($_ seq - (test "I can query the size of a set." - (and (n/= sizeL (&.size setL)) - (n/= sizeR (&.size setR)))) - - (test "Converting sets to/from lists can't change their values." - (|> setL - &.to-list (&.from-list number.Hash) - (&/= setL))) - - (test "Every set is a sub-set of the union of itself with another." - (let [setLR (&.union setL setR)] - (and (&.sub? setLR setL) - (&.sub? setLR setR)))) - - (test "Every set is a super-set of the intersection of itself with another." - (let [setLR (&.intersection setL setR)] - (and (&.super? setLR setL) - (&.super? setLR setR)))) - - (test "Union with the empty set leaves a set unchanged." - (&/= setL - (&.union (&.new number.Hash) - setL))) - - (test "Intersection with the empty set results in the empty set." - (let [empty-set (&.new number.Hash)] - (&/= empty-set - (&.intersection empty-set setL)))) - - (test "After substracting a set A from another B, no member of A can be a member of B." - (let [sub (&.difference setR setL)] - (not (list.any? (&.member? sub) (&.to-list setR))))) - - (test "Every member of a set must be identifiable." - (and (not (&.member? setL non-member)) - (&.member? (&.add non-member setL) non-member) - (not (&.member? (&.remove non-member (&.add non-member setL)) non-member)))) - )))) diff --git a/stdlib/test/test/lux/data/coll/set/ordered.lux b/stdlib/test/test/lux/data/coll/set/ordered.lux deleted file mode 100644 index 6833bf4a6..000000000 --- a/stdlib/test/test/lux/data/coll/set/ordered.lux +++ /dev/null @@ -1,94 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad]) - (data (coll [set] - (set ["&" ordered]) - [list "" Fold]) - [number] - text/format) - ["r" math/random]) - lux/test) - -(def: gen-nat - (r.Random Nat) - (|> r.nat - (:: r.Monad map (n/% +100)))) - -(context: "Sets" - (<| (times +100) - (do @ - [sizeL gen-nat - sizeR gen-nat - listL (|> (r.set number.Hash sizeL gen-nat) (:: @ map set.to-list)) - listR (|> (r.set number.Hash sizeR gen-nat) (:: @ map set.to-list)) - #let [(^open "&/") &.Equivalence - setL (&.from-list number.Order listL) - setR (&.from-list number.Order listR) - sortedL (list.sort n/< listL) - minL (list.head sortedL) - maxL (list.last sortedL)]] - ($_ seq - (test "I can query the size of a set." - (n/= sizeL (&.size setL))) - - (test "Can query minimum value." - (case [(&.min setL) minL] - [#.None #.None] - true - - [(#.Some reference) (#.Some sample)] - (n/= reference sample) - - _ - false)) - - (test "Can query maximum value." - (case [(&.max setL) maxL] - [#.None #.None] - true - - [(#.Some reference) (#.Some sample)] - (n/= reference sample) - - _ - false)) - - (test "Converting sets to/from lists can't change their values." - (|> setL - &.to-list (&.from-list number.Order) - (&/= setL))) - - (test "Order is preserved." - (let [listL (&.to-list setL) - (^open "L/") (list.Equivalence number.Equivalence)] - (L/= listL - (list.sort n/< listL)))) - - (test "Every set is a sub-set of the union of itself with another." - (let [setLR (&.union setL setR)] - (and (&.sub? setLR setL) - (&.sub? setLR setR)))) - - (test "Every set is a super-set of the intersection of itself with another." - (let [setLR (&.intersection setL setR)] - (and (&.super? setLR setL) - (&.super? setLR setR)))) - - (test "Union with the empty set leaves a set unchanged." - (&/= setL - (&.union (&.new number.Order) - setL))) - - (test "Intersection with the empty set results in the empty set." - (let [empty-set (&.new number.Order)] - (&/= empty-set - (&.intersection empty-set setL)))) - - (test "After substracting a set A from another B, no member of A can be a member of B." - (let [sub (&.difference setR setL)] - (not (list.any? (&.member? sub) (&.to-list setR))))) - - (test "Every member of a set must be identifiable." - (list.every? (&.member? setL) (&.to-list setL))) - )))) diff --git a/stdlib/test/test/lux/data/coll/stack.lux b/stdlib/test/test/lux/data/coll/stack.lux deleted file mode 100644 index 9a5b1b438..000000000 --- a/stdlib/test/test/lux/data/coll/stack.lux +++ /dev/null @@ -1,45 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad]) - (data (coll ["&" stack] - [list "" Fold]) - [number] - [maybe]) - ["r" math/random]) - lux/test) - -(def: gen-nat - (r.Random Nat) - (|> r.nat - (:: r.Monad map (n/% +100)))) - -(context: "Stacks" - (<| (times +100) - (do @ - [size gen-nat - sample (r.stack size gen-nat) - new-top gen-nat] - ($_ seq - (test "Can query the size of a stack." - (n/= size (&.size sample))) - - (test "Can peek inside non-empty stacks." - (case (&.peek sample) - #.None (&.empty? sample) - (#.Some _) (not (&.empty? sample)))) - - (test "Popping empty stacks doesn't change anything. - But, if they're non-empty, the top of the stack is removed." - (let [sample' (&.pop sample)] - (or (n/= (&.size sample) (inc (&.size sample'))) - (and (&.empty? sample) (&.empty? sample'))) - )) - - (test "Pushing onto a stack always increases it by 1, adding a new value at the top." - (and (is? sample - (&.pop (&.push new-top sample))) - (n/= (inc (&.size sample)) (&.size (&.push new-top sample))) - (|> (&.push new-top sample) &.peek maybe.assume - (is? new-top)))) - )))) diff --git a/stdlib/test/test/lux/data/coll/tree/rose.lux b/stdlib/test/test/lux/data/coll/tree/rose.lux deleted file mode 100644 index 133f2ef20..000000000 --- a/stdlib/test/test/lux/data/coll/tree/rose.lux +++ /dev/null @@ -1,47 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad]) - (data [product] - [number] - [text "T/" Equivalence] - text/format - (coll (tree ["&" rose]) - [list "L/" Monad Fold])) - ["r" math/random]) - lux/test) - -(def: gen-tree - (r.Random [Nat (&.Tree Nat)]) - (r.rec - (function (_ gen-tree) - (r.either (:: r.Monad map (|>> &.leaf [+1]) r.nat) - (do r.Monad - [value r.nat - num-children (|> r.nat (:: @ map (n/% +3))) - children' (r.list num-children gen-tree) - #let [size' (L/fold n/+ +0 (L/map product.left children')) - children (L/map product.right children')]] - (wrap [(inc size') - (&.branch value children)])) - )))) - -(context: "Trees" - (<| (times +100) - (do @ - [[size sample] gen-tree - #let [(^open "&/") (&.Equivalence number.Equivalence) - (^open "&/") &.Fold - concat (function (_ addition partial) (format partial (%n addition)))]] - ($_ seq - (test "Can compare trees for equivalence." - (&/= sample sample)) - - (test "Can flatten a tree to get all the nodes as a flat tree." - (n/= size - (list.size (&.flatten sample)))) - - (test "Can fold trees." - (T/= (&/fold concat "" sample) - (L/fold concat "" (&.flatten sample)))) - )))) diff --git a/stdlib/test/test/lux/data/coll/tree/rose/zipper.lux b/stdlib/test/test/lux/data/coll/tree/rose/zipper.lux deleted file mode 100644 index 0f5eff838..000000000 --- a/stdlib/test/test/lux/data/coll/tree/rose/zipper.lux +++ /dev/null @@ -1,124 +0,0 @@ -(.module: - lux - (lux [io] - (control [monad #+ do Monad] - pipe) - (data (coll [list "list/" Fold Functor] - (tree [rose] - (rose ["&" zipper]))) - [text] - text/format - [number] - [maybe]) - ["r" math/random]) - lux/test) - -(def: gen-tree - (r.Random (rose.Tree Nat)) - (r.rec (function (_ gen-tree) - (do r.Monad - ## Each branch can have, at most, 1 child. - [size (|> r.nat (:: @ map (n/% +2)))] - (r.seq r.nat - (r.list size gen-tree)))))) - -(def: (to-end zipper) - (All [a] (-> (&.Zipper a) (&.Zipper a))) - (loop [zipper zipper] - (if (&.end? zipper) - zipper - (recur (&.next zipper))))) - -(context: "Zippers." - (<| (times +100) - (do @ - [sample gen-tree - new-val r.nat - pre-val r.nat - post-val r.nat - #let [(^open "tree/") (rose.Equivalence number.Equivalence) - (^open "list/") (list.Equivalence number.Equivalence)]] - ($_ seq - (test "Trees can be converted to/from zippers." - (|> sample - &.zip &.unzip - (tree/= sample))) - - (test "Creating a zipper gives you a root node." - (|> sample &.zip &.root?)) - - (test "Can move down inside branches. Can move up from lower nodes." - (let [zipper (&.zip sample)] - (if (&.branch? zipper) - (let [child (|> zipper &.down)] - (and (not (tree/= sample (&.unzip child))) - (|> child &.up (is? zipper) not) - (|> child &.root (is? zipper) not))) - (and (&.leaf? zipper) - (|> zipper (&.prepend-child new-val) &.branch?))))) - - (test "Can prepend and append children." - (let [zipper (&.zip sample)] - (if (&.branch? zipper) - (let [mid-val (|> zipper &.down &.value) - zipper (|> zipper - (&.prepend-child pre-val) - (&.append-child post-val))] - (and (|> zipper &.down &.value (is? pre-val)) - (|> zipper &.down &.right &.value (is? mid-val)) - (|> zipper &.down &.right &.right &.value (is? post-val)) - (|> zipper &.down &.rightmost &.leftmost &.value (is? pre-val)) - (|> zipper &.down &.right &.left &.value (is? pre-val)) - (|> zipper &.down &.rightmost &.value (is? post-val)))) - true))) - - (test "Can insert children around a node (unless it's root)." - (let [zipper (&.zip sample)] - (if (&.branch? zipper) - (let [mid-val (|> zipper &.down &.value) - zipper (|> zipper - &.down - (&.insert-left pre-val) - maybe.assume - (&.insert-right post-val) - maybe.assume - &.up)] - (and (|> zipper &.down &.value (is? pre-val)) - (|> zipper &.down &.right &.value (is? mid-val)) - (|> zipper &.down &.right &.right &.value (is? post-val)) - (|> zipper &.down &.rightmost &.leftmost &.value (is? pre-val)) - (|> zipper &.down &.right &.left &.value (is? pre-val)) - (|> zipper &.down &.rightmost &.value (is? post-val)))) - (and (|> zipper (&.insert-left pre-val) (case> (#.Some _) false - #.None true)) - (|> zipper (&.insert-right post-val) (case> (#.Some _) false - #.None true)))))) - - (test "Can set and update the value of a node." - (|> sample &.zip (&.set new-val) &.value (n/= new-val))) - - (test "Zipper traversal follows the outline of the tree depth-first." - (list/= (rose.flatten sample) - (loop [zipper (&.zip sample)] - (if (&.end? zipper) - (list (&.value zipper)) - (#.Cons (&.value zipper) - (recur (&.next zipper))))))) - - (test "Backwards zipper traversal yield reverse tree flatten." - (list/= (list.reverse (rose.flatten sample)) - (loop [zipper (to-end (&.zip sample))] - (if (&.root? zipper) - (list (&.value zipper)) - (#.Cons (&.value zipper) - (recur (&.prev zipper))))))) - - (test "Can remove nodes (except root nodes)." - (let [zipper (&.zip sample)] - (if (&.branch? zipper) - (and (|> zipper &.down &.root? not) - (|> zipper &.down &.remove (case> #.None false - (#.Some node) (&.root? node)))) - (|> zipper &.remove (case> #.None true - (#.Some _) false))))) - )))) diff --git a/stdlib/test/test/lux/data/collection/array.lux b/stdlib/test/test/lux/data/collection/array.lux new file mode 100644 index 000000000..1e083676c --- /dev/null +++ b/stdlib/test/test/lux/data/collection/array.lux @@ -0,0 +1,140 @@ +(.module: + lux + (lux (control [monad #+ do Monad] + pipe) + [io] + (data (collection ["@" array] + [list]) + [number] + [maybe]) + ["r" math/random]) + lux/test) + +(def: bounded-size + (r.Random Nat) + (|> r.nat + (:: r.Monad map (|>> (n/% +100) (n/+ +1))))) + +(context: "Arrays and their copies" + (<| (times +100) + (do @ + [size bounded-size + original (r.array size r.nat) + #let [clone (@.clone original) + copy (: (Array Nat) + (@.new size)) + manual-copy (: (Array Nat) + (@.new size))]] + ($_ seq + (test "Size function must correctly return size of array." + (n/= size (@.size original))) + (test "Cloning an array should yield and identical array, but not the same one." + (and (:: (@.Equivalence number.Equivalence) = original clone) + (not (is? original clone)))) + (test "Full-range manual copies should give the same result as cloning." + (exec (@.copy size +0 original +0 copy) + (and (:: (@.Equivalence number.Equivalence) = original copy) + (not (is? original copy))))) + (test "Array folding should go over all values." + (exec (:: @.Fold fold + (function (_ x idx) + (exec (@.write idx x manual-copy) + (inc idx))) + +0 + original) + (:: (@.Equivalence number.Equivalence) = original manual-copy))) + (test "Transformations between (full) arrays and lists shouldn't cause lose or change any values." + (|> original + @.to-list @.from-list + (:: (@.Equivalence number.Equivalence) = original))) + )))) + +(context: "Array mutation" + (<| (times +100) + (do @ + [size bounded-size + idx (:: @ map (n/% size) r.nat) + array (|> (r.array size r.nat) + (r.filter (|>> @.to-list (list.any? n/odd?)))) + #let [value (maybe.assume (@.read idx array))]] + ($_ seq + (test "Shouldn't be able to find a value in an unoccupied cell." + (case (@.read idx (@.delete idx array)) + (#.Some _) false + #.None true)) + (test "You should be able to access values put into the array." + (case (@.read idx (@.write idx value array)) + (#.Some value') (n/= value' value) + #.None false)) + (test "All cells should be occupied on a full array." + (and (n/= size (@.occupied array)) + (n/= +0 (@.vacant array)))) + (test "Filtering mutates the array to remove invalid values." + (exec (@.filter n/even? array) + (and (n/< size (@.occupied array)) + (n/> +0 (@.vacant array)) + (n/= size (n/+ (@.occupied array) + (@.vacant array)))))) + )))) + +(context: "Finding values." + (<| (times +100) + (do @ + [size bounded-size + array (|> (r.array size r.nat) + (r.filter (|>> @.to-list (list.any? n/even?))))] + ($_ seq + (test "Can find values inside arrays." + (|> (@.find n/even? array) + (case> (#.Some _) true + #.None false))) + (test "Can find values inside arrays (with access to indices)." + (|> (@.find+ (function (_ idx n) + (and (n/even? n) + (n/< size idx))) + array) + (case> (#.Some _) true + #.None false))))))) + +(context: "Functor" + (<| (times +100) + (do @ + [size bounded-size + array (r.array size r.nat)] + (let [(^open) @.Functor + (^open) (@.Equivalence number.Equivalence)] + ($_ seq + (test "Functor shouldn't alter original array." + (let [copy (map id array)] + (and (= array copy) + (not (is? array copy))))) + (test "Functor should go over all available array elements." + (let [there (map inc array) + back-again (map dec there)] + (and (not (= array there)) + (= array back-again))))))))) + +(context: "Monoid" + (<| (times +100) + (do @ + [sizeL bounded-size + sizeR bounded-size + left (r.array sizeL r.nat) + right (r.array sizeR r.nat) + #let [(^open) @.Monoid + (^open) (@.Equivalence number.Equivalence) + fusion (compose left right)]] + ($_ seq + (test "Appending two arrays should produce a new one twice as large." + (n/= (n/+ sizeL sizeR) (@.size fusion))) + (test "First elements of fused array should equal the first array." + (|> (: (Array Nat) + (@.new sizeL)) + (@.copy sizeL +0 fusion +0) + (= left))) + (test "Last elements of fused array should equal the second array." + (|> (: (Array Nat) + (@.new sizeR)) + (@.copy sizeR sizeL fusion +0) + (= right))) + )))) diff --git a/stdlib/test/test/lux/data/collection/bits.lux b/stdlib/test/test/lux/data/collection/bits.lux new file mode 100644 index 000000000..bef677ad5 --- /dev/null +++ b/stdlib/test/test/lux/data/collection/bits.lux @@ -0,0 +1,80 @@ +(.module: + lux + (lux (control [monad #+ do] + [predicate]) + (data (collection ["/" bits])) + ["r" math/random]) + lux/test + (test (lux (control ["_eq" equivalence])))) + +(def: (size min max) + (-> Nat Nat (r.Random Nat)) + (|> r.nat + (:: r.Monad map (|>> (n/% max) (n/max min))))) + +(def: bits + (r.Random /.Bits) + (do r.Monad + [size (size +1 +1_000) + idx (|> r.nat (:: @ map (n/% size)))] + (wrap (|> /.empty (/.set idx))))) + +(context: "Bits." + (<| (times +100) + (do @ + [size (size +1 +1_000) + idx (|> r.nat (:: @ map (n/% size))) + sample bits] + ($_ seq + (test "Can set individual bits." + (and (|> /.empty (/.get idx) not) + (|> /.empty (/.set idx) (/.get idx)))) + (test "Can clear individual bits." + (|> /.empty (/.set idx) (/.clear idx) (/.get idx) not)) + (test "Can flip individual bits." + (and (|> /.empty (/.flip idx) (/.get idx)) + (|> /.empty (/.flip idx) (/.flip idx) (/.get idx) not))) + + (test "Bits (only) grow when (and as much as) necessary." + (and (n/= +0 (/.capacity /.empty)) + (|> /.empty (/.set idx) /.capacity + (n/- idx) + (predicate.union (n/>= +0) + (n/< /.chunk-size))))) + (test "Bits (must) shrink when (and as much as) possible." + (let [grown (/.flip idx /.empty)] + (and (n/> +0 (/.capacity grown)) + (is? /.empty (/.flip idx grown))))) + + (test "Intersection can be detected when there are set bits in common." + (and (not (/.intersects? /.empty + /.empty)) + (/.intersects? (/.set idx /.empty) + (/.set idx /.empty)) + (not (/.intersects? (/.set (inc idx) /.empty) + (/.set idx /.empty))))) + (test "Cannot intersect with one's opposite." + (not (/.intersects? sample (/.not sample)))) + + (test "'and' with oneself changes nothing" + (:: /.Equivalence = sample (/.and sample sample))) + (test "'and' with one's opposite yields the empty bit-set." + (is? /.empty (/.and sample (/.not sample)))) + + (test "'or' with one's opposite fully saturates a bit-set." + (n/= (/.size (/.or sample (/.not sample))) + (/.capacity sample))) + + (test "'xor' with oneself yields the empty bit-set." + (is? /.empty (/.xor sample sample))) + (test "'xor' with one's opposite fully saturates a bit-set." + (n/= (/.size (/.xor sample (/.not sample))) + (/.capacity sample))) + + (test "Double negation results in original bit-set." + (:: /.Equivalence = sample (/.not (/.not sample)))) + (test "Negation does not affect the empty bit-set." + (is? /.empty (/.not /.empty))) + + (_eq.spec /.Equivalence ..bits) + )))) diff --git a/stdlib/test/test/lux/data/collection/dictionary.lux b/stdlib/test/test/lux/data/collection/dictionary.lux new file mode 100644 index 000000000..5b18c863f --- /dev/null +++ b/stdlib/test/test/lux/data/collection/dictionary.lux @@ -0,0 +1,128 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad] + ["eq" equivalence]) + (data [text] + text/format + [number] + [maybe] + (collection ["&" dictionary] + [list "list/" Fold Functor])) + ["r" math/random]) + lux/test) + +(context: "Dictionaries." + (<| (times +100) + (do @ + [#let [capped-nat (:: r.Monad map (n/% +100) r.nat)] + size capped-nat + dict (r.dictionary number.Hash size r.nat capped-nat) + non-key (|> r.nat (r.filter (function (_ key) (not (&.contains? key dict))))) + test-val (|> r.nat (r.filter (function (_ val) (not (list.member? number.Equivalence (&.values dict) val)))))] + ($_ seq + (test "Size function should correctly represent Dictionary size." + (n/= size (&.size dict))) + + (test "Dictionaries of size 0 should be considered empty." + (if (n/= +0 size) + (&.empty? dict) + (not (&.empty? dict)))) + + (test "The functions 'entries', 'keys' and 'values' should be synchronized." + (:: (list.Equivalence (eq.product number.Equivalence number.Equivalence)) = + (&.entries dict) + (list.zip2 (&.keys dict) + (&.values dict)))) + + (test "Dictionary should be able to recognize it's own keys." + (list.every? (function (_ key) (&.contains? key dict)) + (&.keys dict))) + + (test "Should be able to get every key." + (list.every? (function (_ key) (case (&.get key dict) + (#.Some _) true + _ false)) + (&.keys dict))) + + (test "Shouldn't be able to access non-existant keys." + (case (&.get non-key dict) + (#.Some _) false + _ true)) + + (test "Should be able to put and then get a value." + (case (&.get non-key (&.put non-key test-val dict)) + (#.Some v) (n/= test-val v) + _ true)) + + (test "Should be able to put~ and then get a value." + (case (&.get non-key (&.put~ non-key test-val dict)) + (#.Some v) (n/= test-val v) + _ true)) + + (test "Shouldn't be able to put~ an existing key." + (or (n/= +0 size) + (let [first-key (|> dict &.keys list.head maybe.assume)] + (case (&.get first-key (&.put~ first-key test-val dict)) + (#.Some v) (not (n/= test-val v)) + _ true)))) + + (test "Removing a key should make it's value inaccessible." + (let [base (&.put non-key test-val dict)] + (and (&.contains? non-key base) + (not (&.contains? non-key (&.remove non-key base)))))) + + (test "Should be possible to update values via their keys." + (let [base (&.put non-key test-val dict) + updt (&.update non-key inc base)] + (case [(&.get non-key base) (&.get non-key updt)] + [(#.Some x) (#.Some y)] + (n/= (inc x) y) + + _ + false))) + + (test "Additions and removals to a Dictionary should affect its size." + (let [plus (&.put non-key test-val dict) + base (&.remove non-key plus)] + (and (n/= (inc (&.size dict)) (&.size plus)) + (n/= (dec (&.size plus)) (&.size base))))) + + (test "A Dictionary should equal itself & going to<->from lists shouldn't change that." + (let [(^open) (&.Equivalence number.Equivalence)] + (and (= dict dict) + (|> dict &.entries (&.from-list number.Hash) (= dict))))) + + (test "Merging a Dictionary to itself changes nothing." + (let [(^open) (&.Equivalence number.Equivalence)] + (= dict (&.merge dict dict)))) + + (test "If you merge, and the second dict has overlapping keys, it should overwrite yours." + (let [dict' (|> dict &.entries + (list/map (function (_ [k v]) [k (inc v)])) + (&.from-list number.Hash)) + (^open) (&.Equivalence number.Equivalence)] + (= dict' (&.merge dict' dict)))) + + (test "Can merge values in such a way that they become combined." + (list.every? (function (_ [x x*2]) (n/= (n/* +2 x) x*2)) + (list.zip2 (&.values dict) + (&.values (&.merge-with n/+ dict dict))))) + + (test "Should be able to select subset of keys from dict." + (|> dict + (&.put non-key test-val) + (&.select (list non-key)) + &.size + (n/= +1))) + + (test "Should be able to re-bind existing values to different keys." + (or (n/= +0 size) + (let [first-key (|> dict &.keys list.head maybe.assume) + rebound (&.re-bind first-key non-key dict)] + (and (n/= (&.size dict) (&.size rebound)) + (&.contains? non-key rebound) + (not (&.contains? first-key rebound)) + (n/= (maybe.assume (&.get first-key dict)) + (maybe.assume (&.get non-key rebound))))))) + )))) diff --git a/stdlib/test/test/lux/data/collection/dictionary/ordered.lux b/stdlib/test/test/lux/data/collection/dictionary/ordered.lux new file mode 100644 index 000000000..a5b680037 --- /dev/null +++ b/stdlib/test/test/lux/data/collection/dictionary/ordered.lux @@ -0,0 +1,88 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad] + [equivalence #+ Equivalence]) + (data [product] + [number] + (collection ["s" set] + ["dict" dictionary] + (dictionary ["&" ordered]) + [list "L/" Functor])) + ["r" math/random]) + lux/test) + +(context: "Dictionary" + (<| (times +100) + (do @ + [size (|> r.nat (:: @ map (n/% +100))) + keys (r.set number.Hash size r.nat) + values (r.set number.Hash size r.nat) + extra-key (|> r.nat (r.filter (|>> (s.member? keys) not))) + extra-value r.nat + #let [pairs (list.zip2 (s.to-list keys) + (s.to-list values)) + sample (&.from-list number.Order pairs) + sorted-pairs (list.sort (function (_ [left _] [right _]) + (n/< left right)) + pairs) + sorted-values (L/map product.right sorted-pairs) + (^open "&/") (&.Equivalence number.Equivalence)]] + ($_ seq + (test "Can query the size of a dictionary." + (n/= size (&.size sample))) + + (test "Can query value for minimum key." + (case [(&.min sample) (list.head sorted-values)] + [#.None #.None] + true + + [(#.Some reference) (#.Some sample)] + (n/= reference sample) + + _ + false)) + + (test "Can query value for maximum key." + (case [(&.max sample) (list.last sorted-values)] + [#.None #.None] + true + + [(#.Some reference) (#.Some sample)] + (n/= reference sample) + + _ + false)) + + (test "Converting dictionaries to/from lists cannot change their values." + (|> sample + &.entries (&.from-list number.Order) + (&/= sample))) + + (test "Order is preserved." + (let [(^open "L/") (list.Equivalence (: (Equivalence [Nat Nat]) + (function (_ [kr vr] [ks vs]) + (and (n/= kr ks) + (n/= vr vs)))))] + (L/= (&.entries sample) + sorted-pairs))) + + (test "Every key in a dictionary must be identifiable." + (list.every? (function (_ key) (&.contains? key sample)) + (&.keys sample))) + + (test "Can add and remove elements in a dictionary." + (and (not (&.contains? extra-key sample)) + (let [sample' (&.put extra-key extra-value sample) + sample'' (&.remove extra-key sample')] + (and (&.contains? extra-key sample') + (not (&.contains? extra-key sample'')) + (case [(&.get extra-key sample') + (&.get extra-key sample'')] + [(#.Some found) #.None] + (n/= extra-value found) + + _ + false))) + )) + )))) diff --git a/stdlib/test/test/lux/data/collection/list.lux b/stdlib/test/test/lux/data/collection/list.lux new file mode 100644 index 000000000..90d3cfc67 --- /dev/null +++ b/stdlib/test/test/lux/data/collection/list.lux @@ -0,0 +1,235 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad] + pipe) + (data (collection ["&" list]) + [number] + [bool] + [product] + [maybe]) + ["r" math/random]) + lux/test) + +(def: bounded-size + (r.Random Nat) + (|> r.nat + (:: r.Monad map (|>> (n/% +100) (n/+ +10))))) + +(context: "Lists: Part 1" + (<| (times +100) + (do @ + [size bounded-size + idx (:: @ map (n/% size) r.nat) + sample (r.list size r.nat) + other-size bounded-size + other-sample (r.list other-size r.nat) + separator r.nat + #let [(^open) (&.Equivalence number.Equivalence) + (^open "&/") &.Functor]] + ($_ seq + (test "The size function should correctly portray the size of the list." + (n/= size (&.size sample))) + + (test "The repeat function should produce as many elements as asked of it." + (n/= size (&.size (&.repeat size [])))) + + (test "Reversing a list does not change it's size." + (n/= (&.size sample) + (&.size (&.reverse sample)))) + + (test "Reversing a list twice results in the original list." + (= sample + (&.reverse (&.reverse sample)))) + + (test "Filtering by a predicate and its complement should result in a number of elements equal to the original list." + (and (n/= (&.size sample) + (n/+ (&.size (&.filter n/even? sample)) + (&.size (&.filter (bool.complement n/even?) sample)))) + (let [[plus minus] (&.partition n/even? sample)] + (n/= (&.size sample) + (n/+ (&.size plus) + (&.size minus)))))) + + (test "If every element in a list satisfies a predicate, there can't be any that satisfy its complement." + (if (&.every? n/even? sample) + (and (not (&.any? (bool.complement n/even?) sample)) + (&.empty? (&.filter (bool.complement n/even?) sample))) + (&.any? (bool.complement n/even?) sample))) + + (test "Any element of the list can be considered its member." + (let [elem (maybe.assume (&.nth idx sample))] + (&.member? number.Equivalence sample elem))) + )))) + +(context: "Lists: Part 2" + (<| (times +100) + (do @ + [size bounded-size + idx (:: @ map (n/% size) r.nat) + sample (r.list size r.nat) + other-size bounded-size + other-sample (r.list other-size r.nat) + separator r.nat + #let [(^open) (&.Equivalence number.Equivalence) + (^open "&/") &.Functor]] + ($_ seq + (test "Appending the head and the tail should yield the original list." + (let [head (maybe.assume (&.head sample)) + tail (maybe.assume (&.tail sample))] + (= sample + (#.Cons head tail)))) + + (test "Appending the inits and the last should yield the original list." + (let [(^open) &.Monoid + inits (maybe.assume (&.inits sample)) + last (maybe.assume (&.last sample))] + (= sample + (compose inits (list last))))) + + (test "Functor should go over every element of the list." + (let [(^open) &.Functor + there (map inc sample) + back-again (map dec there)] + (and (not (= sample there)) + (= sample back-again)))) + + (test "Splitting a list into chunks and re-appending them should yield the original list." + (let [(^open) &.Monoid + [left right] (&.split idx sample) + [left' right'] (&.split-with n/even? sample)] + (and (= sample + (compose left right)) + (= sample + (compose left' right')) + (= sample + (compose (&.take idx sample) + (&.drop idx sample))) + (= sample + (compose (&.take-while n/even? sample) + (&.drop-while n/even? sample))) + ))) + + (test "Segmenting the list in pairs should yield as many elements as N/2." + (n/= (n// +2 size) + (&.size (&.as-pairs sample)))) + + (test "Sorting a list shouldn't change it's size." + (n/= (&.size sample) + (&.size (&.sort n/< sample)))) + + (test "Sorting a list with one order should yield the reverse of sorting it with the opposite order." + (= (&.sort n/< sample) + (&.reverse (&.sort n/> sample)))) + )))) + +(context: "Lists: Part 3" + (<| (times +100) + (do @ + [size bounded-size + idx (:: @ map (n/% size) r.nat) + sample (r.list size r.nat) + other-size bounded-size + other-sample (r.list other-size r.nat) + separator r.nat + from (|> r.nat (:: @ map (n/% +10))) + to (|> r.nat (:: @ map (n/% +10))) + #let [(^open) (&.Equivalence number.Equivalence) + (^open "&/") &.Functor]] + ($_ seq + (test "If you zip 2 lists, the result's size will be that of the smaller list." + (n/= (&.size (&.zip2 sample other-sample)) + (n/min (&.size sample) (&.size other-sample)))) + + (test "I can pair-up elements of a list in order." + (let [(^open) &.Functor + zipped (&.zip2 sample other-sample) + num-zipper (&.size zipped)] + (and (|> zipped (map product.left) (= (&.take num-zipper sample))) + (|> zipped (map product.right) (= (&.take num-zipper other-sample)))))) + + (test "You can generate indices for any size, and they will be in ascending order." + (let [(^open) &.Functor + indices (&.indices size)] + (and (n/= size (&.size indices)) + (= indices + (&.sort n/< indices)) + (&.every? (n/= (dec size)) + (&.zip2-with n/+ + indices + (&.sort n/> indices))) + ))) + + (test "The 'interpose' function places a value between every member of a list." + (let [(^open) &.Functor + sample+ (&.interpose separator sample)] + (and (n/= (|> size (n/* +2) dec) + (&.size sample+)) + (|> sample+ &.as-pairs (map product.right) (&.every? (n/= separator)))))) + + (test "List append is a monoid." + (let [(^open) &.Monoid] + (and (= sample (compose identity sample)) + (= sample (compose sample identity)) + (let [[left right] (&.split size (compose sample other-sample))] + (and (= sample left) + (= other-sample right)))))) + + (test "Apply allows you to create singleton lists, and apply lists of functions to lists of values." + (let [(^open) &.Monad + (^open) &.Apply] + (and (= (list separator) (wrap separator)) + (= (map inc sample) + (apply (wrap inc) sample))))) + + (test "List concatenation is a monad." + (let [(^open) &.Monad + (^open) &.Monoid] + (= (compose sample other-sample) + (join (list sample other-sample))))) + + (test "You can find any value that satisfies some criterium, if such values exist in the list." + (case (&.find n/even? sample) + (#.Some found) + (and (n/even? found) + (&.any? n/even? sample) + (not (&.every? (bool.complement n/even?) sample))) + + #.None + (and (not (&.any? n/even? sample)) + (&.every? (bool.complement n/even?) sample)))) + + (test "You can iteratively construct a list, generating values until you're done." + (= (&.n/range +0 (dec size)) + (&.iterate (function (_ n) (if (n/< size n) (#.Some (inc n)) #.None)) + +0))) + + (test "Can enumerate all elements in a list." + (let [enum-sample (&.enumerate sample)] + (and (= (&.indices (&.size enum-sample)) + (&/map product.left enum-sample)) + (= sample + (&/map product.right enum-sample))))) + + (test "Ranges can be constructed forward and backwards." + (and (let [(^open "list/") (&.Equivalence number.Equivalence)] + (list/= (&.n/range from to) + (&.reverse (&.n/range to from)))) + (let [(^open "list/") (&.Equivalence number.Equivalence) + from (.int from) + to (.int to)] + (list/= (&.i/range from to) + (&.reverse (&.i/range to from)))))) + )))) + +## TODO: Add again once new-luxc becomes the standard compiler. +(context: "Monad transformer" + (let [lift (&.lift io.Monad) + (^open "io/") io.Monad] + (test "Can add list functionality to any monad." + (|> (io.run (do (&.ListT io.Monad) + [a (lift (io/wrap 123)) + b (wrap 456)] + (wrap (i/+ a b)))) + (case> (^ (list 579)) true + _ false))))) diff --git a/stdlib/test/test/lux/data/collection/queue.lux b/stdlib/test/test/lux/data/collection/queue.lux new file mode 100644 index 000000000..8160c9d82 --- /dev/null +++ b/stdlib/test/test/lux/data/collection/queue.lux @@ -0,0 +1,51 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad]) + (data (collection ["&" queue]) + [number]) + ["r" math/random]) + lux/test) + +(context: "Queues" + (<| (times +100) + (do @ + [size (:: @ map (n/% +100) r.nat) + sample (r.queue size r.nat) + non-member (|> r.nat + (r.filter (|>> (&.member? number.Equivalence sample) not)))] + ($_ seq + (test "I can query the size of a queue (and empty queues have size 0)." + (if (n/= +0 size) + (&.empty? sample) + (n/= size (&.size sample)))) + + (test "Enqueueing and dequeing affects the size of queues." + (and (n/= (inc size) (&.size (&.push non-member sample))) + (or (&.empty? sample) + (n/= (dec size) (&.size (&.pop sample)))) + (n/= size (&.size (&.pop (&.push non-member sample)))))) + + (test "Transforming to/from list can't change the queue." + (let [(^open "&/") (&.Equivalence number.Equivalence)] + (|> sample + &.to-list &.from-list + (&/= sample)))) + + (test "I can always peek at a non-empty queue." + (case (&.peek sample) + #.None (&.empty? sample) + (#.Some _) true)) + + (test "I can query whether an element belongs to a queue." + (and (not (&.member? number.Equivalence sample non-member)) + (&.member? number.Equivalence (&.push non-member sample) + non-member) + (case (&.peek sample) + #.None + (&.empty? sample) + + (#.Some first) + (and (&.member? number.Equivalence sample first) + (not (&.member? number.Equivalence (&.pop sample) first)))))) + )))) diff --git a/stdlib/test/test/lux/data/collection/queue/priority.lux b/stdlib/test/test/lux/data/collection/queue/priority.lux new file mode 100644 index 000000000..d1880a735 --- /dev/null +++ b/stdlib/test/test/lux/data/collection/queue/priority.lux @@ -0,0 +1,52 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad]) + (data (collection (queue ["&" priority])) + [number] + [maybe]) + ["r" math/random]) + lux/test) + +(def: (gen-queue size) + (-> Nat (r.Random (&.Queue Nat))) + (do r.Monad + [inputs (r.list size r.nat)] + (monad.fold @ (function (_ head tail) + (do @ + [priority r.nat] + (wrap (&.push priority head tail)))) + &.empty + inputs))) + +(context: "Queues" + (<| (times +100) + (do @ + [size (|> r.nat (:: @ map (n/% +100))) + sample (gen-queue size) + non-member-priority r.nat + non-member (|> r.nat (r.filter (|>> (&.member? number.Equivalence sample) not)))] + ($_ seq + (test "I can query the size of a queue (and empty queues have size 0)." + (n/= size (&.size sample))) + + (test "Enqueueing and dequeing affects the size of queues." + (and (n/= (inc size) + (&.size (&.push non-member-priority non-member sample))) + (or (n/= +0 (&.size sample)) + (n/= (dec size) + (&.size (&.pop sample)))))) + + (test "I can query whether an element belongs to a queue." + (and (and (not (&.member? number.Equivalence sample non-member)) + (&.member? number.Equivalence + (&.push non-member-priority non-member sample) + non-member)) + (or (n/= +0 (&.size sample)) + (and (&.member? number.Equivalence + sample + (maybe.assume (&.peek sample))) + (not (&.member? number.Equivalence + (&.pop sample) + (maybe.assume (&.peek sample)))))))) + )))) diff --git a/stdlib/test/test/lux/data/collection/row.lux b/stdlib/test/test/lux/data/collection/row.lux new file mode 100644 index 000000000..709d8b44e --- /dev/null +++ b/stdlib/test/test/lux/data/collection/row.lux @@ -0,0 +1,73 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad]) + (data (collection ["&" row] + [list "list/" Fold]) + [number] + [maybe]) + ["r" math/random]) + lux/test) + +(context: "Rows" + (<| (times +100) + (do @ + [size (|> r.nat (:: @ map (|>> (n/% +100) (n/max +1)))) + idx (|> r.nat (:: @ map (n/% size))) + sample (r.row size r.nat) + other-sample (r.row size r.nat) + non-member (|> r.nat (r.filter (|>> (&.member? number.Equivalence sample) not))) + #let [(^open "&/") (&.Equivalence number.Equivalence) + (^open "&/") &.Apply + (^open "&/") &.Monad + (^open "&/") &.Fold + (^open "&/") &.Monoid]] + ($_ seq + (test "Can query size of row." + (if (&.empty? sample) + (and (n/= +0 size) + (n/= +0 (&.size sample))) + (n/= size (&.size sample)))) + + (test "Can add and remove elements to rows." + (and (n/= (inc size) (&.size (&.add non-member sample))) + (n/= (dec size) (&.size (&.pop sample))))) + + (test "Can put and get elements into rows." + (|> sample + (&.put idx non-member) + (&.nth idx) + maybe.assume + (is? non-member))) + + (test "Can update elements of rows." + (|> sample + (&.put idx non-member) (&.update idx inc) + (&.nth idx) maybe.assume + (n/= (inc non-member)))) + + (test "Can safely transform to/from lists." + (|> sample &.to-list &.from-list (&/= sample))) + + (test "Can identify members of a row." + (and (not (&.member? number.Equivalence sample non-member)) + (&.member? number.Equivalence (&.add non-member sample) non-member))) + + (test "Can fold over elements of row." + (n/= (list/fold n/+ +0 (&.to-list sample)) + (&/fold n/+ +0 sample))) + + (test "Functor goes over every element." + (let [there (&/map inc sample) + back-again (&/map dec there)] + (and (not (&/= sample there)) + (&/= sample back-again)))) + + (test "Apply allows you to create singleton rows, and apply rows of functions to rows of values." + (and (&/= (&.row non-member) (&/wrap non-member)) + (&/= (&/map inc sample) (&/apply (&/wrap inc) sample)))) + + (test "Row concatenation is a monad." + (&/= (&/compose sample other-sample) + (&/join (&.row sample other-sample)))) + )))) diff --git a/stdlib/test/test/lux/data/collection/sequence.lux b/stdlib/test/test/lux/data/collection/sequence.lux new file mode 100644 index 000000000..a168d749f --- /dev/null +++ b/stdlib/test/test/lux/data/collection/sequence.lux @@ -0,0 +1,101 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad] + comonad) + (data [maybe] + [text "Text/" Monoid] + text/format + (collection [list] + ["&" sequence]) + [number "Nat/" Codec]) + ["r" math/random]) + lux/test) + +(context: "Sequences" + (<| (times +100) + (do @ + [size (|> r.nat (:: @ map (|>> (n/% +100) (n/max +2)))) + offset (|> r.nat (:: @ map (n/% +100))) + factor (|> r.nat (:: @ map (|>> (n/% +100) (n/max +2)))) + elem r.nat + cycle-seed (r.list size r.nat) + cycle-sample-idx (|> r.nat (:: @ map (n/% +1000))) + #let [(^open "List/") (list.Equivalence number.Equivalence) + sample0 (&.iterate inc +0) + sample1 (&.iterate inc offset)]] + ($_ seq + (test "Can move along a sequence and take slices off it." + (and (and (List/= (list.n/range +0 (dec size)) + (&.take size sample0)) + (List/= (list.n/range offset (dec (n/+ offset size))) + (&.take size (&.drop offset sample0))) + (let [[drops takes] (&.split size sample0)] + (and (List/= (list.n/range +0 (dec size)) + drops) + (List/= (list.n/range size (dec (n/* +2 size))) + (&.take size takes))))) + (and (List/= (list.n/range +0 (dec size)) + (&.take-while (n/< size) sample0)) + (List/= (list.n/range offset (dec (n/+ offset size))) + (&.take-while (n/< (n/+ offset size)) + (&.drop-while (n/< offset) sample0))) + (let [[drops takes] (&.split-while (n/< size) sample0)] + (and (List/= (list.n/range +0 (dec size)) + drops) + (List/= (list.n/range size (dec (n/* +2 size))) + (&.take-while (n/< (n/* +2 size)) takes))))) + )) + + (test "Can repeat any element and infinite number of times." + (n/= elem (&.nth offset (&.repeat elem)))) + + (test "Can obtain the head & tail of a sequence." + (and (n/= offset (&.head sample1)) + (List/= (list.n/range (inc offset) (n/+ offset size)) + (&.take size (&.tail sample1))))) + + (test "Can filter sequences." + (and (n/= (n/* +2 offset) + (&.nth offset + (&.filter n/even? sample0))) + (let [[evens odds] (&.partition n/even? (&.iterate inc +0))] + (and (n/= (n/* +2 offset) + (&.nth offset evens)) + (n/= (inc (n/* +2 offset)) + (&.nth offset odds)))))) + + (test "Functor goes over 'all' elements in a sequence." + (let [(^open "&/") &.Functor + there (&/map (n/* factor) sample0) + back-again (&/map (n// factor) there)] + (and (not (List/= (&.take size sample0) + (&.take size there))) + (List/= (&.take size sample0) + (&.take size back-again))))) + + (test "CoMonad produces a value for every element in a sequence." + (let [(^open "&/") &.Functor] + (List/= (&.take size (&/map (n/* factor) sample1)) + (&.take size + (be &.CoMonad + [inputs sample1] + (n/* factor (&.head inputs))))))) + + (test "'unfold' generalizes 'iterate'." + (let [(^open "&/") &.Functor + (^open "List/") (list.Equivalence text.Equivalence)] + (List/= (&.take size + (&/map Nat/encode (&.iterate inc offset))) + (&.take size + (&.unfold (function (_ n) [(inc n) (Nat/encode n)]) + offset))))) + + (test "Can cycle over the same elements as an infinite sequence." + (|> (&.cycle cycle-seed) + maybe.assume + (&.nth cycle-sample-idx) + (n/= (|> cycle-seed + (list.nth (n/% size cycle-sample-idx)) + maybe.assume)))) + )))) diff --git a/stdlib/test/test/lux/data/collection/set.lux b/stdlib/test/test/lux/data/collection/set.lux new file mode 100644 index 000000000..346f1a39b --- /dev/null +++ b/stdlib/test/test/lux/data/collection/set.lux @@ -0,0 +1,64 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad]) + (data (collection ["&" set #+ Set] + [list "" Fold]) + [number]) + ["r" math/random]) + lux/test) + +(def: gen-nat + (r.Random Nat) + (|> r.nat + (:: r.Monad map (n/% +100)))) + +(context: "Sets" + (<| (times +100) + (do @ + [sizeL gen-nat + sizeR gen-nat + setL (r.set number.Hash sizeL gen-nat) + setR (r.set number.Hash sizeR gen-nat) + non-member (|> gen-nat + (r.filter (|>> (&.member? setL) not))) + #let [(^open "&/") &.Equivalence]] + ($_ seq + (test "I can query the size of a set." + (and (n/= sizeL (&.size setL)) + (n/= sizeR (&.size setR)))) + + (test "Converting sets to/from lists can't change their values." + (|> setL + &.to-list (&.from-list number.Hash) + (&/= setL))) + + (test "Every set is a sub-set of the union of itself with another." + (let [setLR (&.union setL setR)] + (and (&.sub? setLR setL) + (&.sub? setLR setR)))) + + (test "Every set is a super-set of the intersection of itself with another." + (let [setLR (&.intersection setL setR)] + (and (&.super? setLR setL) + (&.super? setLR setR)))) + + (test "Union with the empty set leaves a set unchanged." + (&/= setL + (&.union (&.new number.Hash) + setL))) + + (test "Intersection with the empty set results in the empty set." + (let [empty-set (&.new number.Hash)] + (&/= empty-set + (&.intersection empty-set setL)))) + + (test "After substracting a set A from another B, no member of A can be a member of B." + (let [sub (&.difference setR setL)] + (not (list.any? (&.member? sub) (&.to-list setR))))) + + (test "Every member of a set must be identifiable." + (and (not (&.member? setL non-member)) + (&.member? (&.add non-member setL) non-member) + (not (&.member? (&.remove non-member (&.add non-member setL)) non-member)))) + )))) diff --git a/stdlib/test/test/lux/data/collection/set/ordered.lux b/stdlib/test/test/lux/data/collection/set/ordered.lux new file mode 100644 index 000000000..455ea5cb2 --- /dev/null +++ b/stdlib/test/test/lux/data/collection/set/ordered.lux @@ -0,0 +1,94 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad]) + (data (collection [set] + (set ["&" ordered]) + [list "" Fold]) + [number] + text/format) + ["r" math/random]) + lux/test) + +(def: gen-nat + (r.Random Nat) + (|> r.nat + (:: r.Monad map (n/% +100)))) + +(context: "Sets" + (<| (times +100) + (do @ + [sizeL gen-nat + sizeR gen-nat + listL (|> (r.set number.Hash sizeL gen-nat) (:: @ map set.to-list)) + listR (|> (r.set number.Hash sizeR gen-nat) (:: @ map set.to-list)) + #let [(^open "&/") &.Equivalence + setL (&.from-list number.Order listL) + setR (&.from-list number.Order listR) + sortedL (list.sort n/< listL) + minL (list.head sortedL) + maxL (list.last sortedL)]] + ($_ seq + (test "I can query the size of a set." + (n/= sizeL (&.size setL))) + + (test "Can query minimum value." + (case [(&.min setL) minL] + [#.None #.None] + true + + [(#.Some reference) (#.Some sample)] + (n/= reference sample) + + _ + false)) + + (test "Can query maximum value." + (case [(&.max setL) maxL] + [#.None #.None] + true + + [(#.Some reference) (#.Some sample)] + (n/= reference sample) + + _ + false)) + + (test "Converting sets to/from lists can't change their values." + (|> setL + &.to-list (&.from-list number.Order) + (&/= setL))) + + (test "Order is preserved." + (let [listL (&.to-list setL) + (^open "L/") (list.Equivalence number.Equivalence)] + (L/= listL + (list.sort n/< listL)))) + + (test "Every set is a sub-set of the union of itself with another." + (let [setLR (&.union setL setR)] + (and (&.sub? setLR setL) + (&.sub? setLR setR)))) + + (test "Every set is a super-set of the intersection of itself with another." + (let [setLR (&.intersection setL setR)] + (and (&.super? setLR setL) + (&.super? setLR setR)))) + + (test "Union with the empty set leaves a set unchanged." + (&/= setL + (&.union (&.new number.Order) + setL))) + + (test "Intersection with the empty set results in the empty set." + (let [empty-set (&.new number.Order)] + (&/= empty-set + (&.intersection empty-set setL)))) + + (test "After substracting a set A from another B, no member of A can be a member of B." + (let [sub (&.difference setR setL)] + (not (list.any? (&.member? sub) (&.to-list setR))))) + + (test "Every member of a set must be identifiable." + (list.every? (&.member? setL) (&.to-list setL))) + )))) diff --git a/stdlib/test/test/lux/data/collection/stack.lux b/stdlib/test/test/lux/data/collection/stack.lux new file mode 100644 index 000000000..c4e5f58a3 --- /dev/null +++ b/stdlib/test/test/lux/data/collection/stack.lux @@ -0,0 +1,45 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad]) + (data (collection ["&" stack] + [list "" Fold]) + [number] + [maybe]) + ["r" math/random]) + lux/test) + +(def: gen-nat + (r.Random Nat) + (|> r.nat + (:: r.Monad map (n/% +100)))) + +(context: "Stacks" + (<| (times +100) + (do @ + [size gen-nat + sample (r.stack size gen-nat) + new-top gen-nat] + ($_ seq + (test "Can query the size of a stack." + (n/= size (&.size sample))) + + (test "Can peek inside non-empty stacks." + (case (&.peek sample) + #.None (&.empty? sample) + (#.Some _) (not (&.empty? sample)))) + + (test "Popping empty stacks doesn't change anything. + But, if they're non-empty, the top of the stack is removed." + (let [sample' (&.pop sample)] + (or (n/= (&.size sample) (inc (&.size sample'))) + (and (&.empty? sample) (&.empty? sample'))) + )) + + (test "Pushing onto a stack always increases it by 1, adding a new value at the top." + (and (is? sample + (&.pop (&.push new-top sample))) + (n/= (inc (&.size sample)) (&.size (&.push new-top sample))) + (|> (&.push new-top sample) &.peek maybe.assume + (is? new-top)))) + )))) diff --git a/stdlib/test/test/lux/data/collection/tree/rose.lux b/stdlib/test/test/lux/data/collection/tree/rose.lux new file mode 100644 index 000000000..b83c3e675 --- /dev/null +++ b/stdlib/test/test/lux/data/collection/tree/rose.lux @@ -0,0 +1,47 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad]) + (data [product] + [number] + [text "T/" Equivalence] + text/format + (collection (tree ["&" rose]) + [list "L/" Monad Fold])) + ["r" math/random]) + lux/test) + +(def: gen-tree + (r.Random [Nat (&.Tree Nat)]) + (r.rec + (function (_ gen-tree) + (r.either (:: r.Monad map (|>> &.leaf [+1]) r.nat) + (do r.Monad + [value r.nat + num-children (|> r.nat (:: @ map (n/% +3))) + children' (r.list num-children gen-tree) + #let [size' (L/fold n/+ +0 (L/map product.left children')) + children (L/map product.right children')]] + (wrap [(inc size') + (&.branch value children)])) + )))) + +(context: "Trees" + (<| (times +100) + (do @ + [[size sample] gen-tree + #let [(^open "&/") (&.Equivalence number.Equivalence) + (^open "&/") &.Fold + concat (function (_ addition partial) (format partial (%n addition)))]] + ($_ seq + (test "Can compare trees for equivalence." + (&/= sample sample)) + + (test "Can flatten a tree to get all the nodes as a flat tree." + (n/= size + (list.size (&.flatten sample)))) + + (test "Can fold trees." + (T/= (&/fold concat "" sample) + (L/fold concat "" (&.flatten sample)))) + )))) diff --git a/stdlib/test/test/lux/data/collection/tree/rose/zipper.lux b/stdlib/test/test/lux/data/collection/tree/rose/zipper.lux new file mode 100644 index 000000000..3a1a9ed7a --- /dev/null +++ b/stdlib/test/test/lux/data/collection/tree/rose/zipper.lux @@ -0,0 +1,124 @@ +(.module: + lux + (lux [io] + (control [monad #+ do Monad] + pipe) + (data (collection [list "list/" Fold Functor] + (tree [rose] + (rose ["&" zipper]))) + [text] + text/format + [number] + [maybe]) + ["r" math/random]) + lux/test) + +(def: gen-tree + (r.Random (rose.Tree Nat)) + (r.rec (function (_ gen-tree) + (do r.Monad + ## Each branch can have, at most, 1 child. + [size (|> r.nat (:: @ map (n/% +2)))] + (r.seq r.nat + (r.list size gen-tree)))))) + +(def: (to-end zipper) + (All [a] (-> (&.Zipper a) (&.Zipper a))) + (loop [zipper zipper] + (if (&.end? zipper) + zipper + (recur (&.next zipper))))) + +(context: "Zippers." + (<| (times +100) + (do @ + [sample gen-tree + new-val r.nat + pre-val r.nat + post-val r.nat + #let [(^open "tree/") (rose.Equivalence number.Equivalence) + (^open "list/") (list.Equivalence number.Equivalence)]] + ($_ seq + (test "Trees can be converted to/from zippers." + (|> sample + &.zip &.unzip + (tree/= sample))) + + (test "Creating a zipper gives you a root node." + (|> sample &.zip &.root?)) + + (test "Can move down inside branches. Can move up from lower nodes." + (let [zipper (&.zip sample)] + (if (&.branch? zipper) + (let [child (|> zipper &.down)] + (and (not (tree/= sample (&.unzip child))) + (|> child &.up (is? zipper) not) + (|> child &.root (is? zipper) not))) + (and (&.leaf? zipper) + (|> zipper (&.prepend-child new-val) &.branch?))))) + + (test "Can prepend and append children." + (let [zipper (&.zip sample)] + (if (&.branch? zipper) + (let [mid-val (|> zipper &.down &.value) + zipper (|> zipper + (&.prepend-child pre-val) + (&.append-child post-val))] + (and (|> zipper &.down &.value (is? pre-val)) + (|> zipper &.down &.right &.value (is? mid-val)) + (|> zipper &.down &.right &.right &.value (is? post-val)) + (|> zipper &.down &.rightmost &.leftmost &.value (is? pre-val)) + (|> zipper &.down &.right &.left &.value (is? pre-val)) + (|> zipper &.down &.rightmost &.value (is? post-val)))) + true))) + + (test "Can insert children around a node (unless it's root)." + (let [zipper (&.zip sample)] + (if (&.branch? zipper) + (let [mid-val (|> zipper &.down &.value) + zipper (|> zipper + &.down + (&.insert-left pre-val) + maybe.assume + (&.insert-right post-val) + maybe.assume + &.up)] + (and (|> zipper &.down &.value (is? pre-val)) + (|> zipper &.down &.right &.value (is? mid-val)) + (|> zipper &.down &.right &.right &.value (is? post-val)) + (|> zipper &.down &.rightmost &.leftmost &.value (is? pre-val)) + (|> zipper &.down &.right &.left &.value (is? pre-val)) + (|> zipper &.down &.rightmost &.value (is? post-val)))) + (and (|> zipper (&.insert-left pre-val) (case> (#.Some _) false + #.None true)) + (|> zipper (&.insert-right post-val) (case> (#.Some _) false + #.None true)))))) + + (test "Can set and update the value of a node." + (|> sample &.zip (&.set new-val) &.value (n/= new-val))) + + (test "Zipper traversal follows the outline of the tree depth-first." + (list/= (rose.flatten sample) + (loop [zipper (&.zip sample)] + (if (&.end? zipper) + (list (&.value zipper)) + (#.Cons (&.value zipper) + (recur (&.next zipper))))))) + + (test "Backwards zipper traversal yield reverse tree flatten." + (list/= (list.reverse (rose.flatten sample)) + (loop [zipper (to-end (&.zip sample))] + (if (&.root? zipper) + (list (&.value zipper)) + (#.Cons (&.value zipper) + (recur (&.prev zipper))))))) + + (test "Can remove nodes (except root nodes)." + (let [zipper (&.zip sample)] + (if (&.branch? zipper) + (and (|> zipper &.down &.root? not) + (|> zipper &.down &.remove (case> #.None false + (#.Some node) (&.root? node)))) + (|> zipper &.remove (case> #.None true + (#.Some _) false))))) + )))) diff --git a/stdlib/test/test/lux/data/format/json.lux b/stdlib/test/test/lux/data/format/json.lux index 02a82bc63..40aaf97d2 100644 --- a/stdlib/test/test/lux/data/format/json.lux +++ b/stdlib/test/test/lux/data/format/json.lux @@ -13,9 +13,9 @@ [maybe] [number] (format ["@" json]) - (coll [row #+ row] - ["d" dictionary] - [list])) + (collection [row #+ row] + ["d" dictionary] + [list])) [macro #+ with-gensyms] (macro [code] [syntax #+ syntax:] diff --git a/stdlib/test/test/lux/data/format/xml.lux b/stdlib/test/test/lux/data/format/xml.lux index dd82c2e14..a6f57d6b1 100644 --- a/stdlib/test/test/lux/data/format/xml.lux +++ b/stdlib/test/test/lux/data/format/xml.lux @@ -10,8 +10,8 @@ ["E" error] [maybe] (format ["&" xml]) - (coll ["dict" dictionary] - [list "list/" Functor])) + (collection ["dict" dictionary] + [list "list/" Functor])) ["r" math/random "r/" Monad] test) ) diff --git a/stdlib/test/test/lux/data/number/complex.lux b/stdlib/test/test/lux/data/number/complex.lux index 6219eedcc..d75cbc428 100644 --- a/stdlib/test/test/lux/data/number/complex.lux +++ b/stdlib/test/test/lux/data/number/complex.lux @@ -7,7 +7,7 @@ [number "frac/" Number] ["&" number/complex] text/format - (coll [list "list/" Functor])) + (collection [list "list/" Functor])) [math] ["r" math/random]) lux/test) diff --git a/stdlib/test/test/lux/data/sum.lux b/stdlib/test/test/lux/data/sum.lux index 47e68e220..6ef7ce2bc 100644 --- a/stdlib/test/test/lux/data/sum.lux +++ b/stdlib/test/test/lux/data/sum.lux @@ -6,7 +6,7 @@ (data sum [text "Text/" Monoid] [number] - (coll [list]))) + (collection [list]))) lux/test) (context: "Sum operations" diff --git a/stdlib/test/test/lux/data/text.lux b/stdlib/test/test/lux/data/text.lux index 23d6f8d9b..9c5f317f8 100644 --- a/stdlib/test/test/lux/data/text.lux +++ b/stdlib/test/test/lux/data/text.lux @@ -6,7 +6,7 @@ (data ["&" text] text/format [number] - (coll [list])) + (collection [list])) ["r" math/random]) lux/test) diff --git a/stdlib/test/test/lux/data/text/lexer.lux b/stdlib/test/test/lux/data/text/lexer.lux index d1d05074f..31b9dcc40 100644 --- a/stdlib/test/test/lux/data/text/lexer.lux +++ b/stdlib/test/test/lux/data/text/lexer.lux @@ -8,7 +8,7 @@ [text "text/" Equivalence] text/format ["&" text/lexer] - (coll [list])) + (collection [list])) ["r" math/random]) lux/test) diff --git a/stdlib/test/test/lux/lang/compiler/analysis/case.lux b/stdlib/test/test/lux/lang/compiler/analysis/case.lux index 2088a775b..5baf47fc0 100644 --- a/stdlib/test/test/lux/lang/compiler/analysis/case.lux +++ b/stdlib/test/test/lux/lang/compiler/analysis/case.lux @@ -9,8 +9,8 @@ [maybe] [text "T/" Equivalence] text/format - (coll [list "list/" Monad] - [set])) + (collection [list "list/" Monad] + [set])) ["r" math/random "r/" Monad] [macro #+ Monad] (macro [code]) diff --git a/stdlib/test/test/lux/lang/compiler/analysis/function.lux b/stdlib/test/test/lux/lang/compiler/analysis/function.lux index b8c5d23b6..315972d28 100644 --- a/stdlib/test/test/lux/lang/compiler/analysis/function.lux +++ b/stdlib/test/test/lux/lang/compiler/analysis/function.lux @@ -8,7 +8,7 @@ [product] [text "text/" Equivalence] text/format - (coll [list "list/" Functor])) + (collection [list "list/" Functor])) ["r" math/random "r/" Monad] [macro] (macro [code]) diff --git a/stdlib/test/test/lux/lang/compiler/analysis/procedure/common.lux b/stdlib/test/test/lux/lang/compiler/analysis/procedure/common.lux index 1651feaf9..377a48478 100644 --- a/stdlib/test/test/lux/lang/compiler/analysis/procedure/common.lux +++ b/stdlib/test/test/lux/lang/compiler/analysis/procedure/common.lux @@ -7,7 +7,7 @@ (data text/format ["e" error] [product] - (coll [array])) + (collection [array])) ["r" math/random "r/" Monad] [macro #+ Monad] (macro [code]) diff --git a/stdlib/test/test/lux/lang/compiler/analysis/procedure/host.jvm.lux b/stdlib/test/test/lux/lang/compiler/analysis/procedure/host.jvm.lux index 7aa527c93..3d3dc41d5 100644 --- a/stdlib/test/test/lux/lang/compiler/analysis/procedure/host.jvm.lux +++ b/stdlib/test/test/lux/lang/compiler/analysis/procedure/host.jvm.lux @@ -9,9 +9,9 @@ [maybe] [text "text/" Equivalence] text/format - (coll [array] - [list "list/" Fold] - ["dict" dictionary])) + (collection [array] + [list "list/" Fold] + ["dict" dictionary])) ["r" math/random "r/" Monad] [macro #+ Monad] (macro [code]) diff --git a/stdlib/test/test/lux/lang/compiler/analysis/structure.lux b/stdlib/test/test/lux/lang/compiler/analysis/structure.lux index 0fc97dfbe..4b43d150f 100644 --- a/stdlib/test/test/lux/lang/compiler/analysis/structure.lux +++ b/stdlib/test/test/lux/lang/compiler/analysis/structure.lux @@ -9,8 +9,8 @@ [maybe] [text] text/format - (coll [list "list/" Functor] - [set])) + (collection [list "list/" Functor] + [set])) ["r" math/random "r/" Monad] [macro] (macro [code]) diff --git a/stdlib/test/test/lux/lang/compiler/synthesis/function.lux b/stdlib/test/test/lux/lang/compiler/synthesis/function.lux index 44df282b9..008062e5e 100644 --- a/stdlib/test/test/lux/lang/compiler/synthesis/function.lux +++ b/stdlib/test/test/lux/lang/compiler/synthesis/function.lux @@ -8,9 +8,9 @@ [error] [number] text/format - (coll [list "list/" Functor Fold] - ["dict" dictionary #+ Dictionary] - [set])) + (collection [list "list/" Functor Fold] + ["dict" dictionary #+ Dictionary] + [set])) (lang ["///." reference #+ Variable "variable/" Equivalence] ["///." compiler] [".L" analysis #+ Arity Analysis] diff --git a/stdlib/test/test/lux/lang/compiler/synthesis/structure.lux b/stdlib/test/test/lux/lang/compiler/synthesis/structure.lux index eb970d3a3..b3e4d6b67 100644 --- a/stdlib/test/test/lux/lang/compiler/synthesis/structure.lux +++ b/stdlib/test/test/lux/lang/compiler/synthesis/structure.lux @@ -6,7 +6,7 @@ (data [bool "bool/" Equivalence] [product] [error] - (coll [list])) + (collection [list])) (lang ["///." compiler] [".L" analysis] ["//" synthesis #+ Synthesis] diff --git a/stdlib/test/test/lux/lang/syntax.lux b/stdlib/test/test/lux/lang/syntax.lux index f3066368e..9c2be5dd2 100644 --- a/stdlib/test/test/lux/lang/syntax.lux +++ b/stdlib/test/test/lux/lang/syntax.lux @@ -7,8 +7,8 @@ [text] (text format ["l" lexer]) - (coll [list] - ["dict" dictionary #+ Dictionary])) + (collection [list] + ["dict" dictionary #+ Dictionary])) ["r" math/random "r/" Monad] (macro [code]) (lang ["&" syntax]) diff --git a/stdlib/test/test/lux/lang/type.lux b/stdlib/test/test/lux/lang/type.lux index 26f59f7b1..0a5b42461 100644 --- a/stdlib/test/test/lux/lang/type.lux +++ b/stdlib/test/test/lux/lang/type.lux @@ -7,7 +7,7 @@ text/format [number] [maybe] - (coll [list])) + (collection [list])) ["r" math/random] (lang ["&" type])) lux/test) diff --git a/stdlib/test/test/lux/lang/type/check.lux b/stdlib/test/test/lux/lang/type/check.lux index 7a65782de..889f05bd8 100644 --- a/stdlib/test/test/lux/lang/type/check.lux +++ b/stdlib/test/test/lux/lang/type/check.lux @@ -8,8 +8,8 @@ [number] [text "text/" Monoid Equivalence] text/format - (coll [list "list/" Functor] - [set])) + (collection [list "list/" Functor] + [set])) ["r" math/random] (lang [type "type/" Equivalence] ["@" type/check])) diff --git a/stdlib/test/test/lux/macro/poly/equivalence.lux b/stdlib/test/test/lux/macro/poly/equivalence.lux index f37ad04b5..fc86cb597 100644 --- a/stdlib/test/test/lux/macro/poly/equivalence.lux +++ b/stdlib/test/test/lux/macro/poly/equivalence.lux @@ -8,7 +8,7 @@ [number "int/" Number] [text] [maybe] - (coll [list])) + (collection [list])) ["r" math/random] [macro] (macro [poly #+ derived:] diff --git a/stdlib/test/test/lux/math/logic/fuzzy.lux b/stdlib/test/test/lux/math/logic/fuzzy.lux index d4a8ced61..a73df0c37 100644 --- a/stdlib/test/test/lux/math/logic/fuzzy.lux +++ b/stdlib/test/test/lux/math/logic/fuzzy.lux @@ -2,8 +2,8 @@ lux (lux [io] (control [monad #+ do Monad]) - (data (coll [list] - [set]) + (data (collection [list] + [set]) [bool "B/" Equivalence] [number] text/format) diff --git a/stdlib/test/test/lux/math/random.lux b/stdlib/test/test/lux/math/random.lux index 1e85636d5..a7e2f583d 100644 --- a/stdlib/test/test/lux/math/random.lux +++ b/stdlib/test/test/lux/math/random.lux @@ -4,13 +4,13 @@ (control [monad #+ do Monad]) (data [number] text/format - (coll [list] - [row] - [array] - [queue] - [stack] - [set] - ["dict" dictionary])) + (collection [list] + [row] + [array] + [queue] + [stack] + [set] + ["dict" dictionary])) (math ["r" random])) lux/test) diff --git a/stdlib/test/test/lux/type/implicit.lux b/stdlib/test/test/lux/type/implicit.lux index 30f20b073..001185a2e 100644 --- a/stdlib/test/test/lux/type/implicit.lux +++ b/stdlib/test/test/lux/type/implicit.lux @@ -6,7 +6,7 @@ [monad #+ do Monad]) (data [number] [bool "bool/" Equivalence] - (coll [list])) + (collection [list])) ["r" math/random] (type implicit)) lux/test) diff --git a/stdlib/test/test/lux/type/object/interface.lux b/stdlib/test/test/lux/type/object/interface.lux index 7e2bddcdb..e7afc5f64 100644 --- a/stdlib/test/test/lux/type/object/interface.lux +++ b/stdlib/test/test/lux/type/object/interface.lux @@ -1,6 +1,6 @@ (.module: lux - (lux (data (coll [list])) + (lux (data (collection [list])) (type (object interface)))) ## No parameters diff --git a/stdlib/test/test/lux/world/blob.lux b/stdlib/test/test/lux/world/blob.lux index 908a4050f..c0704d851 100644 --- a/stdlib/test/test/lux/world/blob.lux +++ b/stdlib/test/test/lux/world/blob.lux @@ -6,7 +6,7 @@ (data [bit] [number] ["e" error] - (coll [list])) + (collection [list])) (world ["/" blob]) ["r" math/random]) lux/test -- cgit v1.2.3