(.using [library [lux "*" [ffi {"+"}] ["_" test {"+" Test}] [abstract ["[0]" monad {"+" do}] ["[0]" enum] [\\specification ["$[0]" equivalence] ["$[0]" monoid]]] [control ["[0]" try {"+" Try}] ["[0]" exception {"+" Exception}]] [data [collection ["[0]" list ("[1]#[0]" functor)] [array [\\unsafe {"+"}]]]] [math ["[0]" random {"+" Random}] [number ["n" nat] ["[0]" i64]]]]] [\\library ["[0]" / ["!" \\unsafe]]]) (def: (succeed result) (-> (Try Bit) Bit) (case result {try.#Failure _} false {try.#Success output} output)) (def: .public (random size) (-> Nat (Random /.Binary)) (let [output (/.empty size)] (loop (again [idx 0]) (if (n.< size idx) (do random.monad [byte random.nat] (exec (try.trusted (/.has_8! idx byte output)) (again (++ idx)))) (# random.monad in output))))) (def: (throws? exception try) (All (_ e a) (-> (Exception e) (Try a) Bit)) (case try {try.#Failure error} (exception.match? exception error) {try.#Success _} false)) (def: (binary_io power read write value) (-> Nat (-> Nat /.Binary (Try Nat)) (-> Nat Nat /.Binary (Try Any)) Nat Bit) (let [bytes (i64.left_shifted power 1) binary (/.empty bytes) cap (case bytes 8 (-- 0) _ (|> 1 (i64.left_shifted (n.* 8 bytes)) --)) capped_value (i64.and cap value)] (and (..succeed (do try.monad [pre (read 0 binary) _ (write 0 value binary) post (read 0 binary)] (in (and (n.= 0 pre) (n.= capped_value post))))) (throws? /.index_out_of_bounds (read 1 binary)) (throws? /.index_out_of_bounds (write 1 value binary))))) (def: as_list (-> /.Binary (List Nat)) (/.mix (function (_ head tail) {.#Item head tail}) (list))) (def: test|unsafe Test (<| (_.covering !._) (_.for [!.Binary]) (do [! random.monad] [.let [gen_size (|> random.nat (# ! each (|>> (n.% 100) (n.max 8))))] size gen_size sample (..random size) value random.nat .let [gen_idx (|> random.nat (# ! each (n.% size)))] offset gen_idx length (# ! each (n.% (n.- offset size)) random.nat)] (`` (all _.and (_.for [!.=] ($equivalence.spec (function (_ left right) (!.= left right)) (..random size))) (_.cover [!.empty] (!.= (!.empty size) (!.empty size))) (_.cover [!.size] (|> (!.empty size) !.size (n.= size))) (~~ (template [ ] [(_.cover [ ] (let [bytes (i64.left_shifted 1) binary (!.empty bytes) cap (case bytes 8 (-- 0) _ (|> 1 (i64.left_shifted (n.* 8 bytes)) --)) capped_value (i64.and cap value) pre ( 0 binary) _ ( 0 value binary) post ( 0 binary)] (and (n.= 0 pre) (n.= capped_value post))))] [0 !.bits_8 !.has_8!] [1 !.bits_16 !.has_16!] [2 !.bits_32 !.has_32!] [3 !.bits_64 !.has_64!])) (_.cover [!.slice] (let [random_slice (!.slice offset length sample) idxs (is (List Nat) (case length 0 (list) _ (enum.range n.enum 0 (-- length)))) reader (function (_ binary idx) (!.bits_8 idx binary))] (and (n.= length (!.size random_slice)) (# (list.equivalence n.equivalence) = (list#each (|>> (n.+ offset) (reader sample)) idxs) (list#each (reader random_slice) idxs))))) (_.cover [!.copy!] (and (let [it (!.copy! size 0 sample 0 (!.empty size))] (and (not (same? sample it)) (!.= sample it))) (let [sample/0 (!.bits_8 0 sample) copy (!.copy! 1 0 sample 0 (!.empty 2)) copy/0 (!.bits_8 0 copy) copy/1 (!.bits_8 1 copy)] (and (n.= sample/0 copy/0) (n.= 0 copy/1))))) ))))) (def: .public test Test (<| (_.covering /._) (_.for [/.Binary]) (do [! random.monad] [.let [gen_size (|> random.nat (# ! each (|>> (n.% 100) (n.max 8))))] size gen_size sample (..random size) value random.nat .let [gen_idx (|> random.nat (# ! each (n.% size)))] offset (# ! each (n.max 1) gen_idx) length (# ! each (n.% (n.- offset size)) random.nat)] (all _.and (_.for [/.equivalence] ($equivalence.spec /.equivalence (..random size))) (_.for [/.monoid] ($monoid.spec /.equivalence /.monoid (..random size))) (_.cover [/.mix] (n.= (# list.mix mix n.+ 0 (..as_list sample)) (/.mix n.+ 0 sample))) (_.cover [/.empty] (# /.equivalence = (/.empty size) (/.empty size))) (_.cover [/.size] (|> (/.empty size) /.size (n.= size))) (_.for [/.index_out_of_bounds] (all _.and (_.cover [/.bits_8 /.has_8!] (..binary_io 0 /.bits_8 /.has_8! value)) (_.cover [/.bits_16 /.has_16!] (..binary_io 1 /.bits_16 /.has_16! value)) (_.cover [/.bits_32 /.has_32!] (..binary_io 2 /.bits_32 /.has_32! value)) (_.cover [/.bits_64 /.has_64!] (..binary_io 3 /.bits_64 /.has_64! value)))) (_.cover [/.slice] (let [random_slice (try.trusted (/.slice offset length sample)) idxs (is (List Nat) (case length 0 (list) _ (enum.range n.enum 0 (-- length)))) reader (function (_ binary idx) (/.bits_8 idx binary))] (and (n.= length (/.size random_slice)) (case [(monad.each try.monad (|>> (n.+ offset) (reader sample)) idxs) (monad.each try.monad (reader random_slice) idxs)] [{try.#Success binary_vals} {try.#Success slice_vals}] (# (list.equivalence n.equivalence) = binary_vals slice_vals) _ #0)))) (_.cover [/.slice_out_of_bounds] (and (throws? /.slice_out_of_bounds (/.slice size size sample)) (let [verdict (throws? /.slice_out_of_bounds (/.slice offset size sample))] (case offset 0 (not verdict) _ verdict)))) (_.cover [/.after] (and (# /.equivalence = sample (/.after 0 sample)) (# /.equivalence = (/.empty 0) (/.after size sample)) (n.= (n.- offset size) (/.size (/.after offset sample))) (case (list.reversed (..as_list sample)) {.#End} false {.#Item head tail} (n.= (list.mix n.+ 0 tail) (/.mix n.+ 0 (/.after 1 sample)))))) (_.cover [/.copy!] (and (case (/.copy! size 0 sample 0 (/.empty size)) {try.#Success output} (and (not (same? sample output)) (# /.equivalence = sample output)) {try.#Failure _} false) (succeed (do try.monad [sample/0 (/.bits_8 0 sample) copy (/.copy! 1 0 sample 0 (/.empty 2)) copy/0 (/.bits_8 0 copy) copy/1 (/.bits_8 1 copy)] (in (and (n.= sample/0 copy/0) (n.= 0 copy/1))))))) (_.cover [/.cannot_copy] (and (not (throws? /.cannot_copy (/.copy! size 0 sample 0 (/.empty size)))) (throws? /.cannot_copy (/.copy! (n.+ offset size) 0 sample 0 (/.empty size))) (throws? /.cannot_copy (/.copy! size offset sample 0 (/.empty size))) (throws? /.cannot_copy (/.copy! size 0 sample offset (/.empty size))))) ..test|unsafe ))))