(.module: [library [lux "*" ["_" test {"+" [Test]}] [abstract [monad {"+" [do]}] [\\specification ["$[0]" equivalence] ["$[0]" monoid] ["$[0]" mix] ["$[0]" functor {"+" [Injection]}]]] [control ["[0]" maybe]] [data ["[0]" bit] [collection ["[0]" list] ["[0]" set]]] [math ["[0]" random {"+" [Random]}] [number ["n" nat]]]]] [\\library ["[0]" / {"+" [Array]}]]) (def: injection (Injection Array) (|>> list /.of_list)) (def: bounded_size (Random Nat) (# random.monad each (|>> (n.% 100) (n.+ 1)) random.nat)) (def: structures Test (do [! random.monad] [size ..bounded_size] ($_ _.and (_.for [/.equivalence] ($equivalence.spec (/.equivalence n.equivalence) (random.array size random.nat))) (_.for [/.monoid] ($monoid.spec (/.equivalence n.equivalence) /.monoid (random.array size random.nat))) (_.for [/.functor] ($functor.spec ..injection /.equivalence /.functor)) (_.for [/.mix] ($mix.spec ..injection /.equivalence /.mix)) ))) (def: search Test (do [! random.monad] [size ..bounded_size base random.nat shift random.nat .let [expected (n.+ base shift)] the_array (random.array size random.nat)] ($_ _.and (_.cover [/.example] (# (maybe.equivalence n.equivalence) = (/.example n.even? the_array) (list.example n.even? (/.list {.#None} the_array)))) (_.cover [/.example+] (case [(/.example n.even? the_array) (/.example+ (function (_ idx member) (n.even? member)) the_array)] [{.#Some expected} {.#Some [idx actual]}] (case (/.read! idx the_array) {.#Some again} (and (n.= expected actual) (n.= actual again)) {.#None} false) [{.#None} {.#None}] true _ false)) (_.cover [/.every?] (# bit.equivalence = (list.every? n.even? (/.list {.#None} the_array)) (/.every? n.even? the_array))) (_.cover [/.any?] (# bit.equivalence = (list.any? n.even? (/.list {.#None} the_array)) (/.any? n.even? the_array))) ))) (def: .public test Test (<| (_.covering /._) (_.for [/.Array]) (do [! random.monad] [size ..bounded_size base random.nat shift random.nat dummy (random.only (|>> (n.= base) not) random.nat) .let [expected (n.+ base shift)] the_array (random.array size random.nat)] ($_ _.and ..structures ..search (_.cover [/.empty /.size] (n.= size (/.size (: (Array Nat) (/.empty size))))) (_.cover [/.type_name] (case /.Array (^ {.#Named _ {.#UnivQ _ {.#Primitive nominal_type (list {.#Parameter 1})}}}) (same? /.type_name nominal_type) _ false)) (_.cover [/.read! /.write!] (let [the_array (|> (/.empty 2) (: (Array Nat)) (/.write! 0 expected))] (case [(/.read! 0 the_array) (/.read! 1 the_array)] [{.#Some actual} {.#None}] (n.= expected actual) _ false))) (_.cover [/.delete!] (let [the_array (|> (/.empty 1) (: (Array Nat)) (/.write! 0 expected))] (case [(/.read! 0 the_array) (/.read! 0 (/.delete! 0 the_array))] [{.#Some actual} {.#None}] (n.= expected actual) _ false))) (_.cover [/.contains?] (let [the_array (|> (/.empty 2) (: (Array Nat)) (/.write! 0 expected))] (and (/.contains? 0 the_array) (not (/.contains? 1 the_array))))) (_.cover [/.update!] (let [the_array (|> (/.empty 1) (: (Array Nat)) (/.write! 0 base) (/.update! 0 (n.+ shift)))] (case (/.read! 0 the_array) {.#Some actual} (n.= expected actual) _ false))) (_.cover [/.upsert!] (let [the_array (|> (/.empty 2) (: (Array Nat)) (/.write! 0 base) (/.upsert! 0 dummy (n.+ shift)) (/.upsert! 1 base (n.+ shift)))] (case [(/.read! 0 the_array) (/.read! 1 the_array)] [{.#Some actual/0} {.#Some actual/1}] (and (n.= expected actual/0) (n.= expected actual/1)) _ false))) (do ! [occupancy (# ! each (n.% (++ size)) random.nat)] (_.cover [/.occupancy /.vacancy] (let [the_array (loop [output (: (Array Nat) (/.empty size)) idx 0] (if (n.< occupancy idx) (recur (/.write! idx expected output) (++ idx)) output))] (and (n.= occupancy (/.occupancy the_array)) (n.= size (n.+ (/.occupancy the_array) (/.vacancy the_array))))))) (do ! [the_list (random.list size random.nat) .let [the_array (/.clone the_array) members (|> the_array (/.list {.#None}) (set.of_list n.hash))] default (random.only (function (_ value) (not (or (n.even? value) (set.member? members value)))) random.nat)] (_.cover [/.of_list /.list] (and (|> the_list /.of_list (/.list {.#None}) (# (list.equivalence n.equivalence) = the_list)) (|> the_array (/.list {.#None}) /.of_list (# (/.equivalence n.equivalence) = the_array)) (exec (/.filter! n.even? the_array) (list.every? (function (_ value) (or (n.even? value) (same? default value))) (/.list {.#Some default} the_array)))))) (do ! [amount (# ! each (n.% (++ size)) random.nat)] (_.cover [/.copy!] (let [copy (: (Array Nat) (/.empty size))] (exec (/.copy! amount 0 the_array 0 copy) (# (list.equivalence n.equivalence) = (list.first amount (/.list {.#None} the_array)) (/.list {.#None} copy)))))) (_.cover [/.clone] (let [clone (/.clone the_array)] (and (not (same? the_array clone)) (# (/.equivalence n.equivalence) = the_array clone)))) (let [the_array (/.clone the_array) evens (|> the_array (/.list {.#None}) (list.only n.even?)) odds (|> the_array (/.list {.#None}) (list.only n.odd?))] (_.cover [/.filter!] (exec (/.filter! n.even? the_array) (and (n.= (list.size evens) (/.occupancy the_array)) (n.= (list.size odds) (/.vacancy the_array)) (|> the_array (/.list {.#None}) (# (list.equivalence n.equivalence) = evens)))))) ))))