liminal-server 0.24.9

Standalone server for the liminal messaging bus
Documentation
//! SRV-015 R1: the `console.readings` record against its golden bytes. The
//! same file is what the console's own `parseRecord` reads in
//! `apps/liminal-console/tests/server-records.test.ts`, so a renamed or
//! missing field fails on one side of the language boundary or the other.

use super::readings::{Origin, Reading, ReadingValue, ReadingsRecord, Source, TargetKind};
use super::records::canonical_bytes;

type TestResult = Result<(), Box<dyn std::error::Error>>;

const READINGS_GOLDEN: &[u8] = include_bytes!("../../tests/fixtures/console-records/readings.json");

const AT: u64 = 1_791_319_224_159;

fn value(v: f64) -> Result<ReadingValue, Box<dyn std::error::Error>> {
    ReadingValue::new(v).ok_or_else(|| format!("{v} is not finite").into())
}

fn readings() -> Result<ReadingsRecord, Box<dyn std::error::Error>> {
    let source = |id: &str, label: &str, unit: &str, target, from| Source {
        id: id.to_owned(),
        label: label.to_owned(),
        unit: unit.to_owned(),
        target,
        from,
        range: None,
    };
    let reading = |source: &str, target: &str, value| Reading {
        source: source.to_owned(),
        target: target.to_owned(),
        value,
        at: AT,
    };
    let mut rate = source(
        "line.rate",
        "rate",
        "msg/s",
        TargetKind::Line,
        Origin::Server,
    );
    rate.range = Some([value(0.0)?, value(100.0)?]);
    Ok(ReadingsRecord::new(
        3,
        7,
        vec![
            source(
                "line.depth",
                "waiting",
                "msg",
                TargetKind::Line,
                Origin::Server,
            ),
            rate,
            source(
                "worker.backlog",
                "backlog",
                "job",
                TargetKind::Station,
                Origin::Participant("embed.umap".to_owned()),
            ),
        ],
        vec![
            reading("line.depth", "cambium.posts", value(50.0)?),
            reading("line.rate", "cambium.posts", value(2.5)?),
            reading("worker.backlog", "embed.umap", value(3.0)?),
        ],
    ))
}

#[test]
fn the_readings_record_matches_its_golden_bytes() -> TestResult {
    let encoded = canonical_bytes(&readings()?, "readings")?;
    assert_eq!(
        String::from_utf8(encoded)?,
        String::from_utf8(READINGS_GOLDEN.to_vec())?,
        "the readings record drifted from its golden bytes"
    );
    Ok(())
}

#[test]
fn a_reading_value_is_finite_and_has_one_zero() {
    assert!(ReadingValue::new(f64::NAN).is_none(), "NaN is no reading");
    assert!(
        ReadingValue::new(f64::INFINITY).is_none(),
        "infinity is no reading"
    );
    assert!(
        ReadingValue::new(f64::NEG_INFINITY).is_none(),
        "nor is its negative"
    );
    assert_eq!(
        ReadingValue::new(-0.0),
        ReadingValue::new(0.0),
        "minus zero and zero are one reading"
    );
    assert_eq!(ReadingValue::new(2.5).map(ReadingValue::get), Some(2.5));
}