(.module: [library [lux "*" ["_" test {"+" [Test]}] [abstract [monad {"+" [do]}] [\\specification ["$[0]" equivalence] ["$[0]" order] ["$[0]" enum] ["$[0]" codec]]] [control [pipe {"+" [case>]}] ["[0]" try ("[1]\[0]" functor)] ["[0]" exception] [parser ["<[0]>" text]]] [data ["[0]" text ["%" format {"+" [format]}]]] [math ["[0]" random] [number ["n" nat]]]]] ["[0]" / "_" ["[1][0]" date] ["[1][0]" day] ["[1][0]" duration] ["[1][0]" instant] ["[1][0]" month] ["[1][0]" year]] [\\library ["[0]" / ["[0]" duration]]]) (def: for_implementation Test ($_ _.and (_.for [/.equivalence] ($equivalence.spec /.equivalence random.time)) (_.for [/.order] ($order.spec /.order random.time)) (_.for [/.enum] ($enum.spec /.enum random.time)) (_.for [/.codec] ($codec.spec /.equivalence /.codec random.time)))) (def: for_clock Test (do [! random.monad] [expected random.time] (_.cover [/.clock /.time] (|> expected /.clock /.time (try\each (\ /.equivalence = expected)) (try.else false))))) (def: for_ranges Test (do [! random.monad] [valid_hour (\ ! each (|>> (n.% /.hours) (n.max 10)) random.nat) valid_minute (\ ! each (|>> (n.% /.minutes) (n.max 10)) random.nat) valid_second (\ ! each (|>> (n.% /.seconds) (n.max 10)) random.nat) valid_milli_second (\ ! each (n.% /.milli_seconds) random.nat) .let [invalid_hour (|> valid_hour (n.+ /.hours)) invalid_minute (|> valid_minute (n.+ /.minutes) (n.min 99)) invalid_second (|> valid_second (n.+ /.seconds) (n.min 99))]] (`` ($_ _.and (~~ (template [ ] [(_.cover [ ] (let [valid! (|> %.nat (text.prefix ) (text.suffix ) (\ /.codec decoded) (case> (#try.Success _) true (#try.Failure error) false)) invalid! (|> %.nat (text.prefix ) (text.suffix ) (\ /.codec decoded) (case> (#try.Success _) false (#try.Failure error) (exception.match? error)))] (and valid! invalid!)))] [/.hours /.invalid_hour "" ":00:00.000" valid_hour invalid_hour] [/.minutes /.invalid_minute "00:" ":00.000" valid_minute invalid_minute] [/.seconds /.invalid_second "00:00:" ".000" valid_second invalid_second] )) (_.cover [/.milli_seconds] (|> valid_milli_second %.nat (format "00:00:00.") (\ /.codec decoded) (case> (#try.Success _) true (#try.Failure error) false))) )))) (def: .public test Test (<| (_.covering /._) (_.for [/.Time]) (do [! random.monad] [.let [day (.nat (duration.millis duration.day))] expected random.time out_of_bounds (\ ! each (|>> /.millis (n.+ day)) random.time)] (`` ($_ _.and ..for_implementation (_.cover [/.millis /.of_millis] (|> expected /.millis /.of_millis (try\each (\ /.equivalence = expected)) (try.else false))) (_.cover [/.time_exceeds_a_day] (case (/.of_millis out_of_bounds) (#try.Success _) false (#try.Failure error) (exception.match? /.time_exceeds_a_day error))) (_.cover [/.midnight] (|> /.midnight /.millis (n.= 0))) (_.cover [/.parser] (|> expected (\ /.codec encoded) (.result /.parser) (try\each (\ /.equivalence = expected)) (try.else false))) ..for_ranges (_.for [/.Clock] ..for_clock) /date.test /day.test /duration.test /instant.test /month.test /year.test )))))