(.module: [library [lux "*" ["_" test {"+" [Test]}] [abstract [monad {"+" [do]}]] [control ["[0]" io {"+" [IO]}] ["[0]" maybe ("[1]\[0]" functor)] ["[0]" try ("[1]\[0]" monad)] ["[0]" exception] ["[0]" function]] [data ["[0]" binary ("[1]\[0]" equivalence)] ["[0]" text ("[1]\[0]" equivalence) ["%" format {"+" [format]}] [encoding ["[0]" utf8]]] [collection ["[0]" dictionary]]] [math ["[0]" random {"+" [Random]}]] [world [net {"+" [URL]} ["[0]" http "_" ["[1]" client] ["[1]/[0]" status] ["@[1]" /]]]]]] [\\program ["[0]" / ["/[1]" // "_" ["[1][0]" identity]]]]) (def: (url_body url) (-> URL (@http.Body IO)) (let [url (\ utf8.codec encoded url)] (function (_ _) (io.io (#try.Success [(binary.size url) url]))))) (def: (good_http user password) (-> //identity.User //identity.Password (http.Client IO)) (implementation (def: (request method url headers input) (with_expansions [ [http/status.bad_request [#@http.headers (http.headers (list)) #@http.body (..url_body "")]]] (<| io.io #try.Success (if (|> headers (dictionary.value "User-Agent") (maybe\each (same? /.user_agent)) (maybe.else false)) (case [method input] [#@http.Get #.None] [http/status.ok [#@http.headers (http.headers (list)) #@http.body (..url_body url)]] [#@http.Put (#.Some input)] (if (|> headers (dictionary.value "Authorization") (maybe\each (text\= (//identity.basic_auth user password))) (maybe.else false)) [http/status.created [#@http.headers (http.headers (list)) #@http.body (..url_body url)]] ) _ ) )))))) (def: bad_http (http.Client IO) (implementation (def: (request method url headers input) (<| io.io #try.Success [http/status.bad_request [#@http.headers (http.headers (list)) #@http.body (..url_body "")]])))) (def: .public test Test (<| (_.covering /._) (do [! random.monad] [address (random.ascii/upper 10) uri (random.ascii/lower 10) user (random.ascii/lower 10) password (random.ascii/lower 10) content (\ ! each (\ utf8.codec encoded) (random.ascii/lower 10))] ($_ _.and (_.cover [/.repository /.user_agent /.Address] (let [repo (/.repository (..good_http user password) (#.Some [#//identity.user user #//identity.password password]) address)] (and (|> (\ repo download uri) io.run! (try\each (\ utf8.codec decoded)) try\conjoint (try\each (text\= (format address uri))) (try.else false)) (|> (\ repo upload uri content) io.run! (try\each (function.constant true)) (try.else false))))) (_.cover [/.upload_failure] (let [repo (/.repository (..good_http user password) #.None address)] (case (io.run! (\ repo upload uri content)) (#try.Failure error) (exception.match? /.upload_failure error) (#try.Success _) false))) (_.cover [/.download_failure] (let [repo (/.repository ..bad_http #.None address)] (case (io.run! (\ repo download uri)) (#try.Failure error) (exception.match? /.download_failure error) (#try.Success _) false))) ))))