Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-httpclient

Named HTTP clients for Pudu: a client factory, delegating handlers, pooled keep-alive connections, handler lifetimes, logging, and resilience

0.1.1Apache-2.01

InstallClose

EntryTest.pudu

Pudu54 lines3.1 KB

GitHub ↗
1/** @Test.Factory.Entry.Suite — one built pipeline and the order of its layers */2module PuduLangHttpClient.Factory.EntryTest34import Std.Concurrent.Cancel as Cancel5import Std.Http as Http6import Std.Io as Io7import Std.Result as Result8import Std.Test as Test9import PuduLangHttpClient.Factory.Builder as Builder10import PuduLangHttpClient.Factory.Entry as Entry11import PuduLangHttpClient.Handler as Handler12import PuduLangHttpClient.Request as Request13import PuduLangHttpClient.Response as Response14import PuduLangHttpClient.Stub as Stub15import PuduLangHttpClient.Transport as Transport1617/// A handler adding its name to the `trace` header.18fn tracing(name: Str) -> Handler.Handler { Handler.before(|request: Request.Request| request.withHeader("trace", name)) }1920/// An observer tracing its own name outside and inside the other handlers, and the client's name.21fn observer(name: Str) -> Builder.Observer {22  Builder.Observer{outer: |seen: Builder.Observation| tracing(name + "-outer-" + seen.name), inner: |_seen: Builder.Observation| tracing(name + "-inner")}23}2425/// The redirect limit of an entry's transport, when it has one.26fn redirectsOf(entry: &Entry.Entry) -> Option[Int] {27  let transport = entry.transport ?28  Some(transport.options.maxAutomaticRedirections)29}3031/// Runs the suite.32fn main() -> Int {33  let stub = Stub.create()34  Stub.on(&stub, Http.Get, "/", |request: Request.Request| Ok(Response.answer(&request, 200).withText(request.headers.map(|pair: (Str, Str)| pair[1]).join(">"))))35  let builder = Builder.named("api").observedBy(observer("a")).observedBy(observer("b")).withHandler(tracing("h1")).withHandler(tracing("h2")).withPrimary(|| Stub.send(&stub))36  let entry = Entry.build(&builder, 7)37  let order = Result.map(entry.send(Request.get("http://x/"), Cancel.token()), |r: Response.Response| Result.unwrapOr(Response.text(&r), ""))38  let pooled = Entry.build(&Builder.named("p").configureTransport(|options: Transport.Options| options.withMaxRedirects(2)), 1)39  let checks = Test.suite("Factory.Entry", &[40      Test.equals("observers wrap the handlers, the first outermost, and their inner handlers sit innermost in reverse", &order, &Ok("a-outer-api>b-outer-api>h1>h2>b-inner>a-inner")),41      Test.equals("an entry records its name, generation, and lifetime", &(entry.name, entry.generation, entry.lifetime, entry.expiredAt), &("api", 7, 120000, None)),42      Test.equals("a program's own primary handler has no transport", &(entry.transport == None), &true),43      Test.equals("a pooled entry builds its transport from the edited defaults", &redirectsOf(&pooled), &Some(2)),44      Test.equals("the layers number the observers twice and the handlers once", &Entry.layers(&builder).length(), &6),45      Test.equals("transport edits run in order", &Entry.transportOptions(&Builder.named("t").configureTransport(|o: Transport.Options| o.withMaxRedirects(3)).configureTransport(|o: Transport.Options| o.withoutRedirects()), Transport.defaults()).allowAutoRedirect, &false)46    ])47  Entry.close(&pooled)48  let ran = Test.run(&checks)49  for failure in Test.failuresOf(&ran) {50    let _reported = Io.writeErrorLine(failure)51  }52  Test.report(&ran)53}54