(.require [library [lux (.except Variant Record #Bit #Text #Frac) [abstract [codec (.except)] [monad (.only do)] ["[0]" equivalence (.only Equivalence) ["[0]/[1]" \\polytypic]] [\\specification ["$[0]" equivalence]] ["[0]" codec ["[1]T" \\test]]] [control ["<>" parser] ["[0]" pipe] ["[0]" maybe] ["[0]" exception] ["[0]" try (.use "[1]#[0]" functor)]] [data ["[0]" product] ["[0]" bit] ["[0]" text (.only) ["%" \\format (.only format)]] [collection ["[0]" sequence (.only sequence) (.use "[1]#[0]" functor)] ["[0]" dictionary (.only Dictionary)] ["[0]" set] ["[0]" list (.use "[1]#[0]" functor)]]] [math ["[0]" random (.only Random) (.use "[1]#[0]" monad)] [number (.only hex) ["n" nat] ["[0]" i64] ["[0]" frac]]] ["[0]" meta (.only) ["@" target] ["[0]" code] ["[0]" macro (.only) ["^" pattern] ["[0]" syntax (.only syntax)]] [type ["[0]" unit]]] [world [time ["[0]" date] ["[0]" instant ["[0]/[1]" \\test]] ["[0]" duration ["[0]/[1]" \\test]]]] [test ["_" property (.only Test)]]]] ["[0]" \\polytypic] ["[0]" \\parser] [\\library ["[0]" / (.only JSON) (.use "[1]#[0]" equivalence)]]) (def !expect (template (_ ) [(when true _ false)])) (def safe_frac (Random Frac) (random.only (|>> frac.not_a_number? not) random.frac)) (def \\parser Test (<| (_.covering \\parser._) (_.for [\\parser.Parser]) (`` (all _.and (do [! random.monad] [expected (of ! each (|>> {/.#String}) (random.unicode 1))] (_.coverage [\\parser.result \\parser.any] (|> (\\parser.result \\parser.any expected) (!expect (^.multi {try.#Success actual} (of /.equivalence = expected actual)))))) (_.coverage [\\parser.null] (|> (\\parser.result \\parser.null {/.#Null}) (!expect {try.#Success _}))) (,, (with_template [ ] [(do [! random.monad] [expected dummy (|> (random.only (|>> (of = expected) not)))] (all _.and (_.coverage [] (|> (\\parser.result { expected}) (!expect (^.multi {try.#Success actual} (of = expected actual))))) (_.coverage [] (and (|> (\\parser.result ( expected) { expected}) (!expect {try.#Success .true})) (|> (\\parser.result ( expected) { dummy}) (!expect {try.#Success .false})))) (_.coverage [] (and (|> (\\parser.result ( expected) { expected}) (!expect {try.#Success _})) (|> (\\parser.result ( expected) { dummy}) (!expect {try.#Failure _}))))))] [\\parser.boolean \\parser.boolean? \\parser.this_boolean random.bit /.#Boolean bit.equivalence] [\\parser.number \\parser.number? \\parser.this_number ..safe_frac /.#Number frac.equivalence] [\\parser.string \\parser.string? \\parser.this_string (random.unicode 1) /.#String text.equivalence] )) (do [! random.monad] [expected (random.unicode 1) dummy random.bit] (_.coverage [\\parser.unexpected_value] (|> (\\parser.result \\parser.string {/.#Boolean dummy}) (!expect (^.multi {try.#Failure error} (exception.match? \\parser.unexpected_value error)))))) (do [! random.monad] [expected (random.unicode 1) dummy (|> (random.unicode 1) (random.only (|>> (of text.equivalence = expected) not)))] (_.coverage [\\parser.value_mismatch] (|> (\\parser.result (\\parser.this_string expected) {/.#String dummy}) (!expect (^.multi {try.#Failure error} (exception.match? \\parser.value_mismatch error)))))) (do [! random.monad] [expected (random.unicode 1)] (_.coverage [\\parser.nullable] (and (|> (\\parser.result (\\parser.nullable \\parser.string) {/.#Null}) (!expect (^.multi {try.#Success actual} (of (maybe.equivalence text.equivalence) = {.#None} actual)))) (|> (\\parser.result (\\parser.nullable \\parser.string) {/.#String expected}) (!expect (^.multi {try.#Success actual} (of (maybe.equivalence text.equivalence) = {.#Some expected} actual))))))) (do [! random.monad] [size (of ! each (n.% 10) random.nat) expected (|> (random.unicode 1) (random.list size) (of ! each sequence.of_list))] (_.coverage [\\parser.array] (|> (\\parser.result (\\parser.array (<>.some \\parser.string)) {/.#Array (sequence#each (|>> {/.#String}) expected)}) (!expect (^.multi {try.#Success actual} (of (sequence.equivalence text.equivalence) = expected (sequence.of_list actual))))))) (do [! random.monad] [expected (of ! each (|>> {/.#String}) (random.unicode 1))] (_.coverage [\\parser.unconsumed_input] (|> (\\parser.result (\\parser.array \\parser.any) {/.#Array (sequence expected expected)}) (!expect (^.multi {try.#Failure error} (exception.match? \\parser.unconsumed_input error)))))) (_.coverage [\\parser.empty_input] (|> (\\parser.result (\\parser.array \\parser.any) {/.#Array (sequence)}) (!expect (^.multi {try.#Failure error} (exception.match? \\parser.empty_input error))))) (do [! random.monad] [expected_boolean random.bit expected_number ..safe_frac expected_string (random.unicode 1) [boolean_field number_field string_field] (|> (random.set text.hash 3 (random.unicode 3)) (of ! each (|>> set.list (pipe.when (list boolean_field number_field string_field) [boolean_field number_field string_field] _ (undefined)))))] (_.coverage [\\parser.object \\parser.field] (|> (\\parser.result (\\parser.object (all <>.and (\\parser.field boolean_field \\parser.boolean) (\\parser.field number_field \\parser.number) (\\parser.field string_field \\parser.string))) {/.#Object (dictionary.of_list text.hash (list [boolean_field {/.#Boolean expected_boolean}] [number_field {/.#Number expected_number}] [string_field {/.#String expected_string}]))}) (!expect (^.multi {try.#Success [actual_boolean actual_number actual_string]} (and (of bit.equivalence = expected_boolean actual_boolean) (of frac.equivalence = expected_number actual_number) (of text.equivalence = expected_string actual_string))))))) (do [! random.monad] [size (of ! each (n.% 10) random.nat) keys (random.list size (random.unicode 1)) values (random.list size (random.unicode 1)) .let [expected (dictionary.of_list text.hash (list.zipped_2 keys values))]] (_.coverage [\\parser.dictionary] (|> (\\parser.result (\\parser.dictionary \\parser.string) {/.#Object (|> values (list#each (|>> {/.#String})) (list.zipped_2 keys) (dictionary.of_list text.hash))}) (!expect (^.multi {try.#Success actual} (of (dictionary.equivalence text.equivalence) = expected actual)))))) )))) (type Variant (.Variant {#Bit Bit} {#Text Text} {#Frac Frac})) (type Recursive (Rec Recursive (.Variant {#Number Frac} {#Addition Frac Recursive}))) (type Record (.Record [#bit Bit #frac Frac #text Text #maybe (Maybe Frac) #list (List Frac) #dictionary (Dictionary Text Frac) #variant Variant #tuple [Bit Text Frac] #recursive Recursive ... #instant instant.Instant ... #duration duration.Duration #date date.Date #grams (unit.Measure unit.Gram)])) (def gen_recursive (Random Recursive) (random.rec (function (_ gen_recursive) (random.or random.safe_frac (random.and random.safe_frac gen_recursive))))) (def measure (All (_ unit) (Random (unit.Measure unit))) (of random.monad each unit.measure random.int)) (def gen_record (Random Record) (do [! random.monad] [size (of ! each (n.% 2) random.nat)] (all random.and random.bit random.safe_frac (random.unicode size) (random.maybe random.safe_frac) (random.list size random.safe_frac) (random.dictionary text.hash size (random.unicode size) random.safe_frac) (all random.or random.bit (random.unicode size) random.safe_frac) (all random.and random.bit (random.unicode size) random.safe_frac) ..gen_recursive ... \\test/instant.instant ... \\test/duration.duration random.date ..measure ))) (for @.old (these) (these (def equivalence (Equivalence Record) (\\polytypic/equivalence.equivalence Record)) (def codec (Codec JSON Record) (\\polytypic.codec Record)))) (def \\polytypic Test (<| (_.covering \\polytypic._) (_.for [\\polytypic.codec] (for @.old (_.test "PLACEHOLDER" true) (codecT.spec ..equivalence ..codec ..gen_record))))) (def .public random (Random /.JSON) (random.rec (function (_ again) (do [! random.monad] [size (of ! each (n.% 2) random.nat)] (all random.or (of ! in []) random.bit random.safe_frac (random.unicode size) (random.sequence size again) (random.dictionary text.hash size (random.unicode size) again) ))))) (def boolean (syntax (_ []) (do meta.monad [value meta.seed] (in (list (code.bit (n.even? value))))))) (def number (syntax (_ []) (do meta.monad [value meta.seed] (in (list (code.frac (n.frac value))))))) (def string (syntax (_ []) (do meta.monad [value (macro.symbol "string")] (in (list (code.text (%.code value))))))) (def (digits/4 it) (-> Nat Text) (<| (if (n.< (hex "10") it) (format "000" (%.nat_16 it))) (if (n.< (hex "100") it) (format "00" (%.nat_16 it))) (if (n.< (hex "1000") it) (format "0" (%.nat_16 it))) (%.nat_16 it))) (def escaped_string (Random [Text Text]) (all random.either (random#in [text.tab "\t"]) (random#in [text.back_space "\b"]) (random#in [text.new_line "\n"]) (random#in [text.carriage_return "\r"]) (random#in [text.form_feed "\f"]) (random#in [text.double_quote text.double_quote]) (random#in ["\" "\\"]) (do [! random.monad] [char (of ! each (i64.and (hex "FF")) random.nat)] (in [(text.of_char char) (format "\u" (digits/4 char))])) )) (def any_string (Random [Text Text]) (all random.either escaped_string (do random.monad [it (random.alphabetic 1)] (in [it it])) )) (def .public test Test (<| (_.covering /._) (_.for [/.JSON]) (`` (all _.and (_.for [/.equivalence] ($equivalence.spec /.equivalence ..random)) (_.for [/.codec] (all _.and (codecT.spec /.equivalence /.codec ..random) (do random.monad [key (random.alphabetic 1) [expected escaped] any_string] (_.coverage [/.#String] (|> {/.#String escaped} (of /.codec encoded) (of /.codec decoded) (try#each (of /.equivalence = {/.#String expected})) (try.else false)))) )) (do random.monad [sample ..random] (_.coverage [/.Null /.#Null /.null?] (of bit.equivalence = (/.null? sample) (when sample {/.#Null} true _ false)))) (do random.monad [expected ..random] (_.coverage [/.format] (|> expected /.format (of /.codec decoded) (try#each (/#= expected)) (try.else false)))) (do random.monad [keys (random.set text.hash 3 (random.alphabetic 1)) values (random.set frac.hash 3 random.safe_frac) .let [expected (list.zipped_2 (set.list keys) (list#each (|>> {/.#Number}) (set.list values))) object (/.object expected)]] (all _.and (_.coverage [/.object /.fields] (when (/.fields object) {try.#Success actual} (of (list.equivalence text.equivalence) = (list#each product.left expected) actual) {try.#Failure error} false)) (_.coverage [/.field] (list.every? (function (_ [key expected]) (|> (/.field key object) (try#each (/#= expected)) (try.else false))) expected)) )) (do random.monad [key (random.alphabetic 1) unknown (random.only (|>> (of text.equivalence = key) not) (random.alphabetic 1)) expected random.safe_frac] (_.coverage [/.has] (<| (try.else false) (do try.monad [object (/.has key {/.#Number expected} (/.object (list))) .let [can_find_known_key! (|> object (/.field key) (try#each (/#= {/.#Number expected})) (try.else false)) cannot_find_unknown_key! (when (/.field unknown object) {try.#Success _} false {try.#Failure error} true)]] (in (and can_find_known_key! cannot_find_unknown_key!)))))) (,, (with_template [ ] [(do random.monad [key (random.alphabetic 1) value ] (_.coverage [ ] (|> (/.object (list [key { value}])) ( key) (try#each (of = value)) (try.else false))))] [/.Boolean /.boolean_field /.#Boolean random.bit bit.equivalence] [/.Number /.number_field /.#Number random.safe_frac frac.equivalence] [/.String /.string_field /.#String (random.alphabetic 1) text.equivalence] [/.Array /.array_field /.#Array (random.sequence 3 ..random) (sequence.equivalence /.equivalence)] [/.Object /.object_field /.#Object (random.dictionary text.hash 3 (random.alphabetic 1) ..random) (dictionary.equivalence /.equivalence)] )) (with_expansions [ (boolean) (number) (string) (sequence.sequence {/.#Null} {/.#Boolean } {/.#Number } {/.#String }) (string) (string) (string) (string) (string) (string) (string)] (_.coverage [/.json] (and (/#= {/.#Null} (/.json ())) (,, (with_template [ ] [(/#= { } (/.json ))] [/.#Boolean ] [/.#Number ] [/.#String ] )) (/#= {/.#Array } (/.json [() ])) (let [object (/.json { () [() ] { }})] (<| (try.else false) (do try.monad [value0 (/.field object) value1 (/.field object) value2 (/.field object) value3 (/.field object) value4 (/.field object) value5 (/.field object) value6 (/.field value5)] (in (and (/#= {/.#Null} value0) (/#= {/.#Boolean } value1) (/#= {/.#Number } value2) (/#= {/.#String } value3) (/#= {/.#Array } value4) (/#= {/.#Number } value6)))))) ))) ..\\polytypic ..\\parser ))))