Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-log

Structured event logging for Pudu: message templates, enrichment, filtering, formatting, and sinks

0.1.0Apache-2.01

InstallClose

ValueTest.pudu

Pudu53 lines3.7 KB

GitHub ↗
1/** @Test.Value.Suite — value builders, failures, and clocks */2module PuduLangLog.ValueTest34import Std.Bytes as Bytes5import Std.Io as Io6import Std.Test as Test7import PuduLangLog.Clock as Clock8import PuduLangLog.Failure as Failure9import PuduLangLog as Log10import PuduLangLog.Value as Value1112/** @Test.Value.Point — a program type that captures itself */13type Point = { x: Int, y: Int }1415impl Value.Capturable for Point {16  /// The point as a tagged structure.17  fn capture(self: &Self) -> Log.Value { Value.structure("Point", [("X", Value.int(self.x)), ("Y", Value.int(self.y))]) }18}1920/// Runs the suite.21fn main() -> Int {22  let moment = Log.Timestamp{millis: 5, offset: 60}23  let none: Option[Int] = None24  let stepping = Clock.stepping(moment, 10)25  let firstStep = stepping()26  let secondStep = stepping()27  let failure = Failure.causedBy(&Failure.withTrace(&Failure.of("ParseError", "bad digit"), ["Reader.next", "Main.main"]), Failure.from("IoError", "closed"))28  let checks = Test.suite("Value", &[29      Test.equals("built-in types capture as scalars", &[Value.of(3), Value.of("x"), Value.of(true), Value.of(1.5), Value.of('c')], &[Value.int(3), Value.text("x"), Value.bool(true), Value.float(1.5), Value.text("c")]),30      Test.equals("moments and bytes capture as scalars", &(Value.of(moment), Value.of(Bytes.fromText("a"))), &(Log.Scalar(Log.Moment(moment)), Log.Scalar(Log.Binary(Bytes.fromText("a"))))),31      Test.equals("arrays capture as sequences", &Value.of([1, 2]), &Value.list([Value.int(1), Value.int(2)])),32      Test.equals("options capture their value or null", &(Value.of(Some(4)), Value.of(none), Value.of([Some("a"), None])), &(Value.int(4), Value.nothing(), Value.list([Value.text("a"), Value.nothing()]))),33      Test.equals("values capture as themselves", &Value.of(Value.int(1)), &Value.int(1)),34      Test.equals("program types capture as they choose", &Value.of(Point{x: 1, y: 2}), &Value.structure("Point", [("X", Value.int(1)), ("Y", Value.int(2))])),35      Test.equals("durations and decimals", &(Value.duration(1500), Value.decimal(2.50d)), &(Log.Scalar(Log.Span(1500)), Log.Scalar(Log.Exact(2.50d)))),36      Test.equals("objects are untagged structures", &Value.object([("A", Value.int(1))]), &Log.Structure(Log.Structure{tag: None, properties: [Value.property("A", Value.int(1))]})),37      Test.equals("dictionaries by text and by any scalar", &(Value.dictionary([("a", Value.int(1))]), Value.keyed([(Log.Integer(2), Value.int(2))])), &(Log.Dictionary([Log.Entry{key: Log.Text("a"), value: Value.int(1)}]), Log.Dictionary([Log.Entry{key: Log.Integer(2), value: Value.int(2)}]))),38      Test.equals("render shows a value as a message would", &Value.render(&Value.of(Point{x: 1, y: 2})), &"Point \{ X: 1, Y: 2 \}"),39      Test.equals("json shows a value as a JSON formatter would", &Value.json(&Value.of(Point{x: 1, y: 2})), &"\{\"X\":1,\"Y\":2,\"$type\":\"Point\"\}"),40      Test.equals("failures describe their trace and causes", &Failure.describe(&failure), &"ParseError: bad digit\n   at Reader.next\n   at Main.main\n ---> IoError: closed"),41      Test.equals("a failure from an error value", &(Failure.from("Code", 42), Failure.from("Text", "quoted")), &(Failure.of("Code", "42"), Failure.of("Text", "quoted"))),42      Test.equals("a fixed clock", &Clock.fixed(moment)(), &moment),43      Test.equals("a stepping clock advances per reading", &(firstStep, secondStep), &(moment, Log.Timestamp{millis: 15, offset: 60})),44      Test.that("the system clock reads the present", Clock.system()().millis > 1700000000000),45      Test.equals("the UTC clock has no offset", &Clock.utc()().offset, &0)46    ])47  let ran = Test.run(&checks)48  for problem in Test.failuresOf(&ran) {49    let _reported = Io.writeErrorLine(problem)50  }51  Test.report(&ran)52}53