use std::time::{Duration, Instant};
use super::error::ConsoleError;
use super::model::{FlowRole, ThisDevice, TopologyChange, TopologyModel};
use super::records::{
Carrier, LineLife, LineState, LinkCounters, LinkState, Mount, canonical_bytes,
};
use super::wall::WallBase;
type TestResult = Result<(), Box<dyn std::error::Error>>;
fn model(started: Instant) -> TopologyModel {
TopologyModel::new(
ThisDevice {
id: "local".to_owned(),
liminal: "1.2.3".to_owned(),
started,
depot: false,
},
["orders.reply".to_owned()],
[
("orders".to_owned(), LineLife::Kept, LineState::Live),
(
"console.topology".to_owned(),
LineLife::Passing,
LineState::Live,
),
(
"console.tap.orders".to_owned(),
LineLife::Passing,
LineState::Live,
),
],
[(7, Mount::Websocket, Some("alice".to_owned()))],
[],
)
}
const WALL_MS: u64 = 1_791_272_000_000;
fn document(
model: &TopologyModel,
built: Instant,
) -> Result<serde_json::Value, Box<dyn std::error::Error>> {
Ok(serde_json::from_slice(&canonical_bytes(
&model.document(&WallBase::fixed(WALL_MS, built)).0,
"topology",
)?)?)
}
#[test]
fn the_topology_has_no_console_line() -> TestResult {
let started = Instant::now();
let mut model = model(started);
assert!(!model.apply(TopologyChange::Channel {
name: "console.tap.audit".to_owned(),
life: LineLife::Passing,
state: LineState::Live,
}));
let value = document(&model, started)?;
let lines = value["lines"].as_array().ok_or("lines is an array")?;
assert_eq!(lines.len(), 2);
assert_eq!(lines[0]["id"], "orders");
assert_eq!(lines[1]["id"], "orders.reply");
assert_eq!(lines[1]["kind"], "call");
assert!(lines.iter().all(|line| {
!line["id"]
.as_str()
.is_some_and(|id| id.starts_with("console."))
}));
Ok(())
}
#[test]
fn one_revision_per_real_change() {
let started = Instant::now();
let mut model = model(started);
assert_eq!(model.rev(), 1);
let changes = [
TopologyChange::Service {
subject: "billing".to_owned(),
present: true,
},
TopologyChange::Channel {
name: "orders".to_owned(),
life: LineLife::Kept,
state: LineState::Quiesced,
},
TopologyChange::ConnectionOpened {
id: 8,
mount: Mount::Tcp,
participant: None,
},
TopologyChange::Peer {
name: "edge".to_owned(),
present: true,
},
];
for change in changes.clone() {
assert!(model.apply(change));
}
assert_eq!(model.rev(), 5);
for change in changes {
assert!(!model.apply(change), "a repeat is not a change");
}
assert_eq!(model.rev(), 5);
assert!(model.apply(TopologyChange::ConnectionClosed { id: 8 }));
assert!(!model.apply(TopologyChange::ConnectionClosed { id: 8 }));
assert_eq!(model.rev(), 6);
}
#[path = "model_tests/state.rs"]
mod state;
#[path = "model_tests/stations.rs"]
mod stations;