liminal-server 0.27.3

Standalone server for the liminal messaging bus
Documentation
//! ACCESS-011 R3: the access answer's exact fields for the three shapes of
//! exchange, and their one-line words.

use super::AccessHealth;
use crate::config::types::{AuthConfig, Decisions, OpenConfig, Reach, ServerConfig};

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

fn open(reach: Option<Reach>) -> Result<ServerConfig, Box<dyn std::error::Error>> {
    let mut config: ServerConfig = toml::from_str(
        "listen_address = \"127.0.0.1:7900\"\nhealth_listen_address = \"127.0.0.1:7901\"\n\
         drain_timeout_ms = 5000\nchannels = []\nrouting_rules = []\n",
    )?;
    config.open = reach.map(|reach| OpenConfig { reach });
    Ok(config)
}

fn gated(lys: Option<Decisions>) -> Result<ServerConfig, Box<dyn std::error::Error>> {
    let lys = lys.map_or(String::new(), |decisions| {
        format!(
            "[lys]\nissuer = \"https://lys.test\"\nnetwork_id = \"n\"\nkeys_path = \"/k\"\n\
             decisions = \"{decisions}\"\n"
        )
    });
    let mut config = open(None)?;
    let auth: AuthConfig = toml::from_str(&format!("token = \"s3cr3t\"\n{lys}"))?;
    config.auth = Some(auth);
    Ok(config)
}

#[test]
fn an_open_exchange_names_its_mode_and_reach() -> TestResult {
    for (reach, word) in [
        (None, "loopback"),
        (Some(Reach::Loopback), "loopback"),
        (Some(Reach::Network), "network"),
    ] {
        let access = AccessHealth::from(&open(reach)?);
        assert_eq!(
            access,
            AccessHealth {
                mode: "open",
                reach: Some(word),
                decisions: None,
            }
        );
        assert_eq!(
            serde_json::to_value(access)?,
            serde_json::json!({"mode": "open", "reach": word})
        );
        assert_eq!(access.words(), format!("mode open, reach {word}"));
    }
    Ok(())
}

#[test]
fn a_gated_exchange_names_its_mode_and_its_lys_decisions() -> TestResult {
    let bearer = AccessHealth::from(&gated(None)?);
    assert_eq!(
        serde_json::to_value(bearer)?,
        serde_json::json!({"mode": "gated"})
    );
    assert_eq!(bearer.words(), "mode gated");
    for (decisions, word) in [
        (Decisions::Enforce, "enforce"),
        (Decisions::Advise, "advise"),
    ] {
        let access = AccessHealth::from(&gated(Some(decisions))?);
        assert_eq!(
            serde_json::to_value(access)?,
            serde_json::json!({"mode": "gated", "decisions": word})
        );
        assert_eq!(access.words(), format!("mode gated, decisions {word}"));
    }
    Ok(())
}