Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-mediator

In-process messaging for Pudu: requests, notifications, streams, pipeline behaviors, processors, and exception handling

0.1.0Apache-2.01

InstallClose

RegistrationTest.pudu

Pudu127 lines6.2 KB

GitHub ↗
1/** @Test.Registration.Suite — what each registration adds to a catalog */2module PuduLangMediator.RegistrationTest34import Std.HashMap as HashMap5import Std.Io as Io6import Std.Test as Test7import PuduLangMediator.Catalog as Catalog8import PuduLangMediator.Context as Context9import PuduLangMediator.Domain.Order as Order10import PuduLangMediator.Message as Message11import PuduLangMediator as Messaging12import PuduLangMediator.Notification as Notification13import PuduLangMediator.Open as Open14import PuduLangMediator.Publishing as Publishing15import PuduLangMediator.Registration as Registration16import PuduLangMediator.Request as Request17import PuduLangMediator.Stream as Stream1819/** @Test.Registration.Quiet — an open component of every layer that does nothing */20type Quiet = {}2122impl Open.Behavior for Quiet {23  /// Runs the rest of the pipeline.24  fn handleRequest[Q, R, E](self: &Self, request: &Q, info: &Message.Info, context: Context.Context, next: Request.Next[R, E]) -> Messaging.Outcome[R, E] { next(context) }25}2627impl Open.PreProcessor for Quiet {28  /// Lets the request continue.29  fn beforeRequest[Q, E](self: &Self, request: &Q, info: &Message.Info, context: Context.Context) -> Messaging.Outcome[(), E] { Ok(()) }30}3132impl Open.PostProcessor for Quiet {33  /// Lets the response through.34  fn afterRequest[Q, R, E](self: &Self, request: &Q, response: &R, info: &Message.Info, context: Context.Context) -> Messaging.Outcome[(), E] { Ok(()) }35}3637impl Open.ExceptionAction for Quiet {38  /// Observes nothing.39  fn onFailure[Q, E](self: &Self, request: &Q, failure: &Messaging.Failure[E], info: &Message.Info, context: Context.Context) -> () { () }40}4142impl Open.NotificationHandler for Quiet {43  /// Hears nothing.44  fn handleNotification[N, E](self: &Self, notification: &N, info: &Message.Info, context: Context.Context) -> Messaging.Outcome[(), E] { Ok(()) }45}4647impl Open.StreamBehavior for Quiet {48  /// Runs the rest of the stream.49  fn handleStream[Q, T, E](self: &Self, request: &Q, info: &Message.Info, context: Context.Context, sink: Stream.Sink[T], next: Stream.Next[T, E]) -> Messaging.Outcome[(), E] {50    next(context, sink)51  }52}5354/// The catalog after applying registrations in order.55fn applied(registrations: Array[Registration.Registration]) -> Catalog.Catalog {56  var catalog = Catalog.empty(Publishing.Sequential{}, Catalog.ForUnhandled)57  for registration in registrations { catalog = (registration.apply)(catalog) }58  catalog59}6061/// The handler and component counts of one entry.62fn counted(table: &HashMap.HashMap[Str, Catalog.Entry], name: Str) -> (Int, Int) {63  match HashMap.get(table, &name) {64    case Some(entry) => (entry.handlers, entry.components)65    case None => (0, 0)66  }67}6869/// Runs the suite.70fn main() -> Int {71  let ask: Request.Kind[Int, Int, Str] = Request.kind("ask")72  let told: Notification.Kind[Int, Str] = Notification.kind("told")73  let flow: Stream.Kind[Int, Int, Str] = Stream.kind("flow")74  let passThrough = fn(_request: Int, context: Context.Context, next: Request.Next[Int, Str]) -> Messaging.Outcome[Int, Str] { next(context) }75  let catalog = applied([76      Registration.openBehavior(Quiet{}),77      Registration.group([78          Registration.handler(&ask, |value: Int, _context: Context.Context| Ok(value)),79          Registration.behavior(&ask, passThrough),80          Registration.preProcessor(&ask, |_value: Int, _context: Context.Context| Ok(())),81          Registration.postProcessor(&ask, |_value: Int, _answer: Int, _context: Context.Context| Ok(()))82        ]),83      Registration.exceptionHandler(&ask, |_value: Int, _failure: Messaging.Failure[Str], _context: Context.Context| None),84      Registration.exceptionAction(&ask, |_value: Int, _failure: Messaging.Failure[Str], _context: Context.Context| ()),85      Registration.openPreProcessor(Quiet{}),86      Registration.openPostProcessor(Quiet{}),87      Registration.openExceptionAction(Quiet{}),88      Registration.notificationHandler(&told, "one", |_value: Int, _context: Context.Context| Ok(())),89      Registration.openNotificationHandler("quiet", Quiet{}),90      Registration.notificationHandler(&told, "two", |_value: Int, _context: Context.Context| Ok(())),91      Registration.streamHandler(&flow, fn(_value: Int, _context: Context.Context, _sink: Stream.Sink[Int]) -> Messaging.Outcome[(), Str] { Ok(()) }),92      Registration.streamBehavior(&flow, fn(_value: Int, context: Context.Context, sink: Stream.Sink[Int], next: Stream.Next[Int, Str]) -> Messaging.Outcome[(), Str] { next(context, sink) }),93      Registration.openStreamBehavior(Quiet{})94    ])95  let held = catalog.assembly96  let checks = Test.suite("Registration", &[97      Test.equals("a request kind counts one handler and five components", &counted(&catalog.requests, "ask"), &(1, 5)),98      Test.equals("a notification kind counts every handler", &counted(&catalog.notifications, "told"), &(2, 0)),99      Test.equals("a stream kind counts its handler and behavior", &counted(&catalog.streams, "flow"), &(1, 1)),100      Test.equals("every open component is kept once", &(held.behaviors.length(), held.preProcessors.length(), held.postProcessors.length(), held.exceptionActions.length(), held.listeners.length(), held.streamBehaviors.length()), &(101          1, 1, 1, 1, 1, 1102        )),103      Test.equals("an open notification handler keeps its name", &held.listeners.map(|listener: Open.Listener| listener.name), &["quiet"]),104      Test.equals("every ordered registration is marked in order, groups included", &held.marks, &[105          Order.Open(Order.Behaviors, 0),106          Order.Closed(Order.Behaviors, "ask"),107          Order.Closed(Order.PreProcessors, "ask"),108          Order.Closed(Order.PostProcessors, "ask"),109          Order.Closed(Order.ExceptionActions, "ask"),110          Order.Open(Order.PreProcessors, 0),111          Order.Open(Order.PostProcessors, 0),112          Order.Open(Order.ExceptionActions, 0),113          Order.Closed(Order.NotificationHandlers, "told"),114          Order.Open(Order.NotificationHandlers, 0),115          Order.Closed(Order.NotificationHandlers, "told"),116          Order.Closed(Order.StreamBehaviors, "flow"),117          Order.Open(Order.StreamBehaviors, 0)118        ]),119      Test.equals("nothing is a problem", &Catalog.problems(&catalog), &[])120    ])121  let ran = Test.run(&checks)122  for failure in Test.failuresOf(&ran) {123    let _reported = Io.writeErrorLine(failure)124  }125  Test.report(&ran)126}127