(.using [library [lux "*" ["_" test {"+" Test}] [abstract [monad {"+" do}] ["[0]" enum] [\\specification ["$[0]" equivalence] ["$[0]" hash] ["$[0]" monoid] ["$[0]" mix] ["$[0]" functor] ["$[0]" apply] ["$[0]" monad]]] [control pipe ["[0]" io] ["[0]" maybe] ["[0]" function]] [data ["[0]" bit] ["[0]" product] ["[0]" text ("[1]#[0]" equivalence)] [collection ["[0]" set]]] [math ["[0]" random {"+" Random}] [number ["n" nat] ["[0]" int]]]]] [\\library ["[0]" / ("[1]#[0]" monad)]]) (def: bounded_size (Random Nat) (# random.monad each (n.% 100) random.nat)) (def: random (Random (List Nat)) (do [! random.monad] [size ..bounded_size] (|> random.nat (random.set n.hash size) (# ! each set.list)))) (def: signatures Test ($_ _.and (_.for [/.equivalence] ($equivalence.spec (/.equivalence n.equivalence) ..random)) (_.for [/.hash] (|> random.nat (# random.monad each (|>> list)) ($hash.spec (/.hash n.hash)))) (_.for [/.monoid] ($monoid.spec (/.equivalence n.equivalence) /.monoid ..random)) (_.for [/.mix] ($mix.spec /#in /.equivalence /.mix)) (_.for [/.functor] ($functor.spec /#in /.equivalence /.functor)) (_.for [/.apply] ($apply.spec /#in /.equivalence /.apply)) (_.for [/.monad] ($monad.spec /#in /.equivalence /.monad)) (do [! random.monad] [parameter random.nat subject random.nat] (let [lifted (/.lifted io.monad) (^open "io#[0]") io.monad expected (n.+ parameter subject)] (_.cover [/.with /.lifted] (|> (io.run! (do (/.with io.monad) [a (lifted (io#in parameter)) b (in subject)] (in (n.+ a b)))) (case> (^ (list actual)) (n.= expected actual) _ false))))) )) (def: whole Test (do [! random.monad] [size ..bounded_size .let [(^open "/#[0]") (/.equivalence n.equivalence)] sample (# ! each set.list (random.set n.hash size random.nat))] ($_ _.and (_.cover [/.size] (n.= size (/.size sample))) (_.cover [/.empty?] (# bit.equivalence = (/.empty? sample) (n.= 0 (/.size sample)))) (_.cover [/.repeated] (n.= size (/.size (/.repeated size [])))) (_.cover [/.reversed] (or (n.< 2 (/.size sample)) (let [not_same! (not (/#= sample (/.reversed sample))) self_symmetry! (/#= sample (/.reversed (/.reversed sample)))] (and not_same! self_symmetry!)))) (_.cover [/.every? /.any?] (if (/.every? n.even? sample) (not (/.any? (bit.complement n.even?) sample)) (/.any? (bit.complement n.even?) sample))) (_.cover [/.sorted] (let [<<< n.< size_preservation! (n.= (/.size sample) (/.size (/.sorted <<< sample))) symmetry! (/#= (/.sorted <<< sample) (/.reversed (/.sorted (function.flipped <<<) sample)))] (and size_preservation! symmetry!))) ))) (def: indices Test (let [(^open "/#[0]") (/.equivalence n.equivalence) (^open "/#[0]") /.functor] (do [! random.monad] [sample ..random .let [size (/.size sample)]] ($_ _.and (_.cover [/.indices] (let [indices (/.indices size) expected_amount! (n.= size (/.size indices)) already_sorted! (/#= indices (/.sorted n.< indices)) expected_numbers! (/.every? (n.= (-- size)) (/.zipped_with/2 n.+ indices (/.sorted n.> indices)))] (and expected_amount! already_sorted! expected_numbers!))) (_.cover [/.enumeration] (let [enumeration (/.enumeration sample) has_correct_indices! (/#= (/.indices (/.size enumeration)) (/#each product.left enumeration)) has_correct_values! (/#= sample (/#each product.right enumeration))] (and has_correct_indices! has_correct_values!))) (_.cover [/.item] (/.every? (function (_ [index expected]) (case (/.item index sample) {.#Some actual} (n.= expected actual) {.#None} false)) (/.enumeration sample))) (do ! [index (case size 0 random.nat _ (# ! each (n.% size) random.nat)) .let [changed? (/#= sample (/.revised index ++ sample)) same? (/#= sample (/.revised size ++ sample))]] (_.cover [/.revised] (case size 0 (and changed? same?) _ (not changed?)))) )))) (def: slice Test (let [(^open "/#[0]") (/.equivalence n.equivalence) (^open "/#[0]") /.monoid] (do [! random.monad] [sample (random.only (|>> /.size (n.> 0)) ..random) .let [size (/.size sample)] idx (# ! each (n.% size) random.nat) sub_size (# ! each (|>> (n.% size) ++) random.nat)] ($_ _.and (_.cover [/.only] (let [positives (/.only n.even? sample) negatives (/.only (bit.complement n.even?) sample)] (and (/.every? n.even? positives) (not (/.any? n.even? negatives)) (n.= (/.size sample) (n.+ (/.size positives) (/.size negatives)))))) (_.cover [/.partition] (let [[positives negatives] (/.partition n.even? sample)] (and (/#= (/.only n.even? sample) positives) (/#= (/.only (bit.complement n.even?) sample) negatives)))) (_.cover [/.split_at] (let [[left right] (/.split_at idx sample)] (/#= sample (/#composite left right)))) (_.cover [/.split_when] (let [[left right] (/.split_when n.even? sample)] (/#= sample (/#composite left right)))) (_.cover [/.first /.after] (/#= sample (/#composite (/.first idx sample) (/.after idx sample)))) (_.cover [/.while /.until] (/#= sample (/#composite (/.while n.even? sample) (/.until n.even? sample)))) (_.cover [/.sub] (let [subs (/.sub sub_size sample)] (and (/.every? (|>> /.size (n.<= sub_size)) subs) (/#= sample (/.together subs))))) )))) (def: member Test (let [(^open "/#[0]") (/.equivalence n.equivalence)] (do [! random.monad] [sample ..random] (`` ($_ _.and (_.cover [/.member?] (/.every? (/.member? n.equivalence sample) sample)) (~~ (template [
] [($_ _.and (_.cover [] (case [(sample) ( sample)] [{.#Item expected _} {.#Some actual}] (n.= expected actual) [{.#End} {.#None}] true _ false)) (_.cover [] (case [( sample) (sample)] [{.#Item _ expected} {.#Some actual}] (/#= ( expected) actual) [{.#End} {.#None}] true _ false)) )] [/.head /.tail |>] [/.last /.inits /.reversed] )) ))))) (def: grouping Test (let [(^open "/#[0]") (/.equivalence n.equivalence) (^open "/#[0]") /.functor (^open "/#[0]") /.monoid +/2 (: (-> Nat Nat Nat) (function (_ left right) ($_ n.+ left right))) +/3 (: (-> Nat Nat Nat Nat) (function (_ left mid right) ($_ n.+ left mid right)))] (do [! random.monad] [sample/0 ..random sample/1 ..random sample/2 ..random] ($_ _.and (_.cover [/.pairs] (let [even_sized? (|> sample/0 /.size (n.% 2) (n.= 0))] (case (/.pairs sample/0) {.#Some pairs/0} (and even_sized? (n.= (n./ 2 (/.size sample/0)) (/.size pairs/0))) {.#None} (not even_sized?)))) (_.cover [/.zipped/2] (let [zipped (/.zipped/2 sample/0 sample/1) zipped::size (/.size zipped) size_of_smaller_list! (n.= zipped::size (n.min (/.size sample/0) (/.size sample/1))) can_extract_values! (and (/#= (/.first zipped::size sample/0) (/#each product.left zipped)) (/#= (/.first zipped::size sample/1) (/#each product.right zipped)))] (and size_of_smaller_list! can_extract_values!))) (_.cover [/.zipped/3] (let [zipped (/.zipped/3 sample/0 sample/1 sample/2) zipped::size (/.size zipped) size_of_smaller_list! (n.= zipped::size ($_ n.min (/.size sample/0) (/.size sample/1) (/.size sample/2))) can_extract_values! (and (/#= (/.first zipped::size sample/0) (/#each product.left zipped)) (/#= (/.first zipped::size sample/1) (/#each (|>> product.right product.left) zipped)) (/#= (/.first zipped::size sample/2) (/#each (|>> product.right product.right) zipped)))] (and size_of_smaller_list! can_extract_values!))) (_.cover [/.zipped] (and (# (/.equivalence (product.equivalence n.equivalence n.equivalence)) = (/.zipped/2 sample/0 sample/1) ((/.zipped 2) sample/0 sample/1)) (# (/.equivalence ($_ product.equivalence n.equivalence n.equivalence n.equivalence)) = (/.zipped/3 sample/0 sample/1 sample/2) ((/.zipped 3) sample/0 sample/1 sample/2)))) (_.cover [/.zipped_with/2] (/#= (/#each (function (_ [left right]) (+/2 left right)) (/.zipped/2 sample/0 sample/1)) (/.zipped_with/2 +/2 sample/0 sample/1))) (_.cover [/.zipped_with/3] (/#= (/#each (function (_ [left mid right]) (+/3 left mid right)) (/.zipped/3 sample/0 sample/1 sample/2)) (/.zipped_with/3 +/3 sample/0 sample/1 sample/2))) (_.cover [/.zipped_with] (and (/#= (/.zipped_with/2 +/2 sample/0 sample/1) ((/.zipped_with 2) +/2 sample/0 sample/1)) (/#= (/.zipped_with/3 +/3 sample/0 sample/1 sample/2) ((/.zipped_with 3) +/3 sample/0 sample/1 sample/2)))) (_.cover [/.together] (and (/#= (/#composite sample/0 sample/1) (/.together (list sample/0 sample/1))) (/#= ($_ /#composite sample/0 sample/1 sample/2) (/.together (list sample/0 sample/1 sample/2))))) )))) (def: search Test (let [(^open "/#[0]") /.functor choice (: (-> Nat (Maybe Text)) (function (_ value) (if (n.even? value) {.#Some (# n.decimal encoded value)} {.#None})))] (do [! random.monad] [sample ..random] ($_ _.and (_.cover [/.one] (case [(|> sample (/.only n.even?) (/#each (# n.decimal encoded)) /.head) (/.one choice sample)] [{.#Some expected} {.#Some actual}] (text#= expected actual) [{.#None} {.#None}] true _ false)) (_.cover [/.all] (# (/.equivalence text.equivalence) = (|> sample (/.only n.even?) (/#each (# n.decimal encoded))) (/.all choice sample))) (_.cover [/.example] (case (/.example n.even? sample) {.#Some found} (n.even? found) {.#None} (not (/.any? n.even? sample)))) )))) (def: .public test Test (<| (_.covering /._) (_.for [.List]) (let [(^open "/#[0]") (/.equivalence n.equivalence) (^open "/#[0]") /.functor] (do [! random.monad] [sample ..random separator random.nat] ($_ _.and ..signatures ..whole ..indices ..slice ..member ..grouping ..search (_.cover [/.interposed] (or (/.empty? sample) (let [sample+ (/.interposed separator sample)] (and (n.= (|> (/.size sample) (n.* 2) --) (/.size sample+)) (|> sample+ /.pairs (maybe.else (list)) (/.every? (|>> product.right (n.= separator)))))))) (_.cover [/.iterations] (or (/.empty? sample) (let [size (/.size sample)] (/#= (/.indices size) (/.iterations (function (_ index) (if (n.< size index) {.#Some (++ index)} {.#None})) 0))))) (_.cover [/.mixes] (/#= (/#each (function (_ index) (# /.mix mix n.+ 0 (/.first index sample))) (/.indices (++ (/.size sample)))) (/.mixes n.+ 0 sample))) (do random.monad [expected random.nat .let [(^open "/#[0]") (/.equivalence n.equivalence)]] (_.cover [/.when] (and (/#= (list expected) (/.when true (list expected))) (/#= (list) (/.when false (list expected)))))) )))))