(.with_expansions [' (.for {"{old}" (.as_is ["#/." jvm]) "JVM" (.as_is ["#/." jvm])} (.as_is)) '] (.module: [library ["/" lux #* [program (#+ program:)] ["_" test (#+ Test)] ["@" target] ["." meta] [abstract [monad (#+ do)] [predicate (#+ Predicate)]] [control ["." io] [concurrency ["." atom (#+ Atom)]]] [data ["." bit ("#\." equivalence)] ["." text ("#\." equivalence) ["%" format (#+ format)]] [collection ["." list]]] [macro ["." code ("#\." equivalence)]] ["." math ["." random (#+ Random) ("#\." functor)] [number ["n" nat] ["i" int] ["r" rev] ["f" frac] ["." i64]]]]] ## TODO: Must have 100% coverage on tests. ["." / #_ ["#." abstract] ["#." control] ["#." data] ["#." debug] ["#." locale] ["#." macro] ["#." math] ["#." meta] ["#." program] ["#." target] ["#." test] ["#." time] ## ["#." tool] ## TODO: Update & expand tests for this ["#." type] ["#." world] ["#." ffi] ["#." extension] ["#." target #_ ]])) ## TODO: Get rid of this ASAP (template: (!bundle body) (: Test (do random.monad [_ (wrap [])] body))) (def: identity Test (do {! random.monad} [value random.nat #let [object (: (Random (Atom Nat)) (\ ! map atom.atom (wrap value)))] self object] ($_ _.and (_.test "Every value is identical to itself." (is? self self)) (do ! [other object] (_.test "Values created separately can't be identical." (not (is? self other)))) ))) (def: prelude_macros Test ($_ _.and (do random.monad [factor (random\map (|>> (n.% 10) (n.max 1)) random.nat) iterations (random\map (n.% 10) random.nat) #let [expected (n.* factor iterations)]] (_.test "Can write loops." (n.= expected (loop [counter 0 value 0] (if (n.< iterations counter) (recur (inc counter) (n.+ factor value)) value))))) )) (def: sub_tests Test (with_expansions [## TODO: Update & expand tests for this (for {@.jvm (~~ (as_is /target/jvm.test)) @.old (~~ (as_is /target/jvm.test))} (~~ (as_is))) (for {@.old (~~ (as_is))} (~~ (as_is /extension.test)))] (`` (_.in_parallel (list /abstract.test /control.test /data.test /debug.test /locale.test /macro.test /math.test /meta.test /program.test /target.test /test.test /time.test ## /tool.test /type.test /world.test /ffi.test ))))) (def: for_bit Test (do random.monad [expected random.nat dummy random.nat] (_.for [/.Bit /.if] ($_ _.and (_.cover [/.false] (n.= expected (/.if /.false dummy expected))) (_.cover [/.true] (n.= expected (/.if /.true expected dummy))) (_.cover [/.or] (and (not (/.or /.false /.false)) (/.or /.false /.true) (/.or /.true /.false) (/.or /.true /.true))) (_.cover [/.and] (and (not (/.and /.false /.false)) (not (/.and /.false /.true)) (not (/.and /.true /.false)) (/.and /.true /.true))) (_.cover [/.not] (and (bit\= /.true (/.not /.false)) (bit\= /.false (/.not /.true)))) (_.cover [/.cond] (and (n.= expected (/.cond /.true expected ## else dummy)) (n.= expected (/.cond /.false dummy ## else expected)) (n.= expected (/.cond /.true expected /.false dummy ## else dummy)) (n.= expected (/.cond /.false dummy /.true expected ## else dummy)))) )))) (def: for_try Test (do random.monad [expected_error (random.ascii/lower 5) expected random.nat] ($_ _.and (_.cover [/.try] (case (/.try expected) (#.Left _) false (#.Right actual) (n.= expected actual))) (_.cover [/.undefined] (case (/.try (/.undefined)) (#.Left _) true (#.Right _) false)) (_.cover [/.error!] (case (/.try (/.error! expected_error)) (#.Left actual_error) (text.contains? expected_error actual_error) (#.Right _) false)) ))) (def: for_list Test (do random.monad [e/0 random.nat e/1 random.nat e/2 random.nat e/3 random.nat] ($_ _.and (_.cover [/.list] (case (/.list e/0 e/1) (^ (/.list a/0 a/1)) (and (n.= e/0 a/0) (n.= e/1 a/1)) _ false)) (_.cover [/.list&] (case (/.list& e/0 e/1 (/.list e/2 e/3)) (^ (/.list& a/0 a/1 (/.list a/2 a/3))) (and (n.= e/0 a/0) (n.= e/1 a/1) (n.= e/2 a/2) (n.= e/3 a/3)) _ false)) ))) (/.interface: (Returner a) (: (-> Any a) return)) (/.implementation: (global_returner value) (All [a] (-> a (Returner a))) (def: (return _) value)) (def: static_return 123) (/.open: "global\." (..global_returner ..static_return)) (def: for_interface Test (do random.monad [expected random.nat #let [local_returner (: (Returner Nat) (/.implementation (def: (return _) expected)))]] (_.for [/.interface:] ($_ _.and (_.cover [/.implementation:] (n.= expected (\ (global_returner expected) return []))) (_.cover [/.implementation] (n.= expected (\ local_returner return []))) (_.cover [/.open:] (n.= static_return (global\return []))) (_.cover [/.^open] (let [(/.^open "local\.") local_returner] (n.= expected (local\return [])))) (_.cover [/.\] (n.= expected (/.\ local_returner return []))) )))) (def: for_module Test ($_ _.and (let [[module short] (/.name_of .example)] (_.cover [/.name_of /.prelude_module] (and (text\= /.prelude_module module) (text\= short "example")))) (let [[module short] (/.name_of ..example)] (_.cover [/.module_separator] (and (text.contains? /.module_separator module) (not (text.contains? /.module_separator short))))) )) (def: for_pipe Test (do random.monad [start random.nat factor random.nat #let [expected (n.* factor (inc start))]] ($_ _.and (_.cover [/.|>] (n.= expected (/.|> start inc (n.* factor)))) (_.cover [/.|>>] (n.= expected ((/.|>> inc (n.* factor)) start))) (_.cover [/.<|] (n.= expected (/.<| (n.* factor) inc start))) (_.cover [/.<<|] (n.= expected ((/.<<| (n.* factor) inc) start))) ))) (def: example "YOLO") (def: i8 8) (def: current_module Text (let [[module _] (name_of .._)] module)) (def: for_code/' Test (do random.monad [example_nat random.nat] (_.cover [/.'] (and (code\= (code.nat 0) (/.' 0)) (code\= (code.int -1) (/.' -1)) (code\= (code.rev .2) (/.' .2)) (code\= (code.frac +3.4) (/.' +3.4)) (code\= (code.text "5") (/.' "5")) (code\= (code.identifier ["" "example"]) (/.' example)) (code\= (code.identifier [/.prelude_module "example"]) (/.' .example)) (code\= (code.identifier [..current_module "example"]) (/.' ..example)) (code\= (code.tag ["" "example"]) (/.' #example)) (code\= (code.tag [/.prelude_module "example"]) (/.' #.example)) (code\= (code.tag [..current_module "example"]) (/.' #..example)) (code\= (code.form (list (code.nat 6) (code.int +7) (code.rev .8))) (/.' (6 +7 .8))) (code\= (code.tuple (list (code.frac +9.0) (code.text "9") (code.identifier ["" "i8"]))) (/.' [+9.0 "9" i8])) (code\= (code.record (list [(code.identifier [/.prelude_module "i7"]) (code.identifier [..current_module "i6"])])) (/.' {.i7 ..i6})) (not (code\= (code.nat example_nat) (/.' (~ (code.nat example_nat))))) )))) (def: for_code/` Test (do random.monad [example_nat random.nat] (_.cover [/.`] (and (code\= (code.nat 0) (/.` 0)) (code\= (code.int -1) (/.` -1)) (code\= (code.rev .2) (/.` .2)) (code\= (code.frac +3.4) (/.` +3.4)) (code\= (code.text "5") (/.` "5")) (code\= (code.identifier [..current_module "example"]) (/.` example)) (code\= (code.identifier [/.prelude_module "example"]) (/.` .example)) (code\= (code.identifier [..current_module "example"]) (/.` ..example)) (code\= (code.tag [..current_module "example"]) (/.` #example)) (code\= (code.tag [/.prelude_module "example"]) (/.` #.example)) (code\= (code.tag [..current_module "example"]) (/.` #..example)) (code\= (code.form (list (code.nat 6) (code.int +7) (code.rev .8))) (/.` (6 +7 .8))) (code\= (code.tuple (list (code.frac +9.0) (code.text "9") (code.identifier [..current_module "i8"]))) (/.` [+9.0 "9" i8])) (code\= (code.record (list [(code.identifier [/.prelude_module "i7"]) (code.identifier [..current_module "i6"])])) (/.` {.i7 ..i6})) (code\= (code.nat example_nat) (/.` (~ (code.nat example_nat)))))))) (def: for_code/`' Test (do random.monad [example_nat random.nat] (_.cover [/.`'] (and (code\= (code.nat 0) (/.`' 0)) (code\= (code.int -1) (/.`' -1)) (code\= (code.rev .2) (/.`' .2)) (code\= (code.frac +3.4) (/.`' +3.4)) (code\= (code.text "5") (/.`' "5")) (code\= (code.identifier ["" "example"]) (/.`' example)) (code\= (code.identifier [/.prelude_module "example"]) (/.`' .example)) (code\= (code.identifier [..current_module "example"]) (/.`' ..example)) (code\= (code.tag ["" "example"]) (/.`' #example)) (code\= (code.tag [/.prelude_module "example"]) (/.`' #.example)) (code\= (code.tag [..current_module "example"]) (/.`' #..example)) (code\= (code.form (list (code.nat 6) (code.int +7) (code.rev .8))) (/.`' (6 +7 .8))) (code\= (code.tuple (list (code.frac +9.0) (code.text "9") (code.identifier ["" "i8"]))) (/.`' [+9.0 "9" i8])) (code\= (code.record (list [(code.identifier [/.prelude_module "i7"]) (code.identifier [..current_module "i6"])])) (/.`' {.i7 ..i6})) (code\= (code.nat example_nat) (/.`' (~ (code.nat example_nat)))))))) (def: for_code Test (do random.monad [example_nat random.nat] (_.for [/.Code /.Code'] ($_ _.and ..for_code/' ..for_code/` ..for_code/`' )))) (/.macro: (identity_macro tokens) (\ meta.monad wrap tokens)) (def: for_macro Test (let [macro (: /.Macro' (function (_ tokens lux) (#.Right [lux (list)])))] (do random.monad [expected random.nat] ($_ _.and (_.cover [/.Macro'] (|> macro (: /.Macro') (is? macro))) (_.cover [/.Macro] (|> macro "lux macro" (: /.Macro) (: Any) (is? (: Any macro)))) (_.cover [/.macro:] (is? expected (..identity_macro expected))) )))) (def: for_type Test (do random.monad [expected random.nat expected_left random.nat expected_right random.nat] ($_ _.and (_.cover [/.:] (|> expected (/.: Any) (is? (/.: Any expected)))) (_.cover [/.:as] (|> expected (/.: Any) (/.:as /.Nat) (is? expected))) (_.cover [/.:assume] (|> expected (/.: Any) /.:assume (/.: /.Nat) (is? expected))) (_.cover [/.:let] (let [[actual_left actual_right] (: (/.:let [side /.Nat] (& side side)) [expected_left expected_right])] (and (is? expected_left actual_left) (is? expected_right actual_right)))) (_.cover [/.:of] (is? /.Nat (/.:of expected))) ))) (def: for_i64 Test (do random.monad [expected random.i64] ($_ _.and (_.cover [/.i64] (is? (: Any expected) (: Any (/.i64 expected)))) (_.cover [/.nat] (is? (: Any expected) (: Any (/.nat expected)))) (_.cover [/.int] (is? (: Any expected) (: Any (/.int expected)))) (_.cover [/.rev] (is? (: Any expected) (: Any (/.rev expected)))) (_.cover [/.inc] (n.= 1 (n.- expected (/.inc expected)))) (_.cover [/.dec] (n.= 1 (n.- (/.dec expected) expected))) ))) (def: for_function Test (do random.monad [expected_left random.nat expected_right random.nat] (_.cover [/.-> /.function] (let [actual (: (/.-> Nat Nat Nat) (/.function (_ actual_left actual_right) (n.* (inc actual_left) (dec actual_right))))] (n.= (n.* (inc expected_left) (dec expected_right)) (actual expected_left expected_right)))))) (/.template: (!n/+ ) (n.+ )) (def: for_template Test (`` ($_ _.and (_.cover [/.template] (let [bits (list (~~ (/.template [_] [true] [0] [1] [2] )))] (and (n.= 3 (list.size bits)) (list.every? (bit\= true) bits)))) (do random.monad [left random.nat right random.nat] (_.cover [/.template:] (n.= (n.+ left right) (!n/+ left right)))) (do {! random.monad} [sample (\ ! map (n.% 5) random.nat)] (_.cover [/.^template] (case sample (/.^template [] [ true]) ([0] [1] [2] [3] [4]) _ false))) ))) (def: option/0 "0") (def: option/1 "1") (def: static_char "@") (def: for_static Test (do random.monad [sample (random.either (wrap option/0) (wrap option/1))] ($_ _.and (_.cover [/.static] (case sample (^ (/.static option/0)) true (^ (/.static option/1)) true _ false)) (_.cover [/.char] (|> (`` (/.char (~~ (/.static static_char)))) text.from_code (text\= static_char))) ))) (type: Small {#small_left Nat #small_right Text}) (type: Big {#big_left Nat #big_right Small}) (def: for_slot Test (do random.monad [start/s random.nat start/b random.nat shift/s random.nat shift/b random.nat text (random.ascii/lower 1) #let [expected/s (n.+ shift/s start/s) expected/b (n.+ shift/b start/b) sample {#big_left start/b #big_right {#small_left start/s #small_right text}}]] ($_ _.and (_.cover [/.get@] (and (and (|> sample (/.get@ #big_left) (is? start/b)) (|> sample ((/.get@ #big_left)) (is? start/b))) (and (|> sample (/.get@ [#big_right #small_left]) (is? start/s)) (|> sample ((/.get@ [#big_right #small_left])) (is? start/s))))) (_.cover [/.set@] (and (and (|> sample (/.set@ #big_left shift/b) (/.get@ #big_left) (is? shift/b)) (|> sample ((/.set@ #big_left shift/b)) (/.get@ #big_left) (is? shift/b)) (|> sample ((/.set@ #big_left) shift/b) (/.get@ #big_left) (is? shift/b))) (and (|> sample (/.set@ [#big_right #small_left] shift/s) (/.get@ [#big_right #small_left]) (is? shift/s)) (|> sample ((/.set@ [#big_right #small_left] shift/s)) (/.get@ [#big_right #small_left]) (is? shift/s)) (|> sample ((/.set@ [#big_right #small_left]) shift/s) (/.get@ [#big_right #small_left]) (is? shift/s))))) (_.cover [/.update@] (and (and (|> sample (/.update@ #big_left (n.+ shift/b)) (/.get@ #big_left) (n.= expected/b)) (|> sample ((/.update@ #big_left (n.+ shift/b))) (/.get@ #big_left) (n.= expected/b)) (|> sample ((: (-> (-> Nat Nat) (-> Big Big)) (/.update@ #big_left)) (n.+ shift/b)) (/.get@ #big_left) (n.= expected/b))) (and (|> sample (/.update@ [#big_right #small_left] (n.+ shift/s)) (/.get@ [#big_right #small_left]) (n.= expected/s)) (|> sample ((/.update@ [#big_right #small_left] (n.+ shift/s))) (/.get@ [#big_right #small_left]) (n.= expected/s)) (|> sample ((: (-> (-> Nat Nat) (-> Big Big)) (/.update@ [#big_right #small_left])) (n.+ shift/s)) (/.get@ [#big_right #small_left]) (n.= expected/s))))) ))) (def: for_associative Test (do random.monad [left (random.ascii/lower 1) mid (random.ascii/lower 1) right (random.ascii/lower 1) #let [expected (text.join_with "" (list left mid right))]] (_.cover [/.$_ /._$] (with_expansions [ (/._$ format left mid right) (/.$_ format left mid right)] (and (text\= ) (not (code\= (' ) (' )))))))) (def: for_expansion Test (do random.monad [left random.nat right random.nat dummy random.nat #let [expected (n.+ left right)]] ($_ _.and (_.cover [/.as_is] (`` (and (~~ (as_is true true true))))) (_.cover [/.with_expansions] (/.with_expansions [ (as_is left right)] (n.= expected (n.+ )))) (_.cover [/.comment] (/.with_expansions [ (/.comment dummy) (as_is left right)] (n.= expected ($_ n.+ )))) (_.cover [/.``] (n.= expected (/.`` ($_ n.+ (~~ (as_is left right)) (~~ (/.comment dummy)))))) (_.cover [/.for] (and (n.= expected (/.for {"fake host" dummy} expected)) (n.= expected (/.for {@.old expected @.jvm expected @.js expected @.python expected @.lua expected @.ruby expected @.php expected} dummy)))) ))) (def: test Test (<| (_.covering /._) ($_ _.and (<| (_.context "Identity.") ..identity) (<| (_.context "Prelude macros.") ..prelude_macros) ..for_bit ..for_try ..for_list ..for_interface ..for_module ..for_pipe ..for_code ..for_macro ..for_type ..for_i64 ..for_function ..for_template ..for_static ..for_slot ..for_associative ..for_expansion ..sub_tests ))) (program: args (let [times (for {@.old 100 @.jvm 100 @.js 10 @.python 1 @.lua 1 @.ruby 1} 100)] (<| io.io _.run! (_.times times) ..test)))