Files

104 lines
3.7 KiB
Rust

//! Fleet layout and node-config tests. The bus daemon is a fake `tines-busd`
//! seeded onto PATH (see `common`; the real binary isn't on PATH for unit
//! tests): it creates the socket file named by argv[1], so the fleet's
//! spawn protocol is what's under test — the real daemon is covered by
//! tines-bus's own suite and Task 4's e2e.
mod common;
use std::os::unix::fs::PermissionsExt;
use std::time::{Duration, Instant};
use tines_gui::fleet::{Fleet, Mode};
fn fleet_name(tag: &str) -> String {
format!(
"test-{tag}-{}",
std::thread::current().name().unwrap_or("t")
)
}
#[test]
fn fleet_dir_layout() {
common::env_with_fake_busd();
let fleet = Fleet::create(&fleet_name("layout")).expect("fleet creates");
let dir = tines_gui::config::fleet_dir(&fleet_name("layout"));
let meta = std::fs::metadata(&dir).expect("fleet dir exists");
assert!(meta.is_dir());
assert_eq!(meta.permissions().mode() & 0o777, 0o700);
// The fake daemon creates the bus socket the fleet asked it to bind.
let socket = fleet.bus_socket();
assert_eq!(socket, dir.join("bus.sock"));
let deadline = Instant::now() + Duration::from_secs(5);
while !socket.exists() {
assert!(
Instant::now() < deadline,
"bus.sock never appeared: {}",
socket.display()
);
std::thread::sleep(Duration::from_millis(50));
}
}
#[test]
fn add_node_bus_config_mounts_data() {
common::env_with_fake_busd();
let fleet_name = fleet_name("bus");
let fleet = Fleet::create(&fleet_name).expect("fleet creates");
let spec = fleet
.add_node("alpha", Some(&"11".repeat(16)), Mode::Sim, None)
.expect("node added");
let json = std::fs::read_to_string(spec.dir.join("config.json")).unwrap();
let parsed: tines::config::Config =
serde_json::from_str(&json).expect("config parses as the service config");
assert_eq!(parsed.transport, Some(tines::config::TransportKind::Bus));
assert_eq!(parsed.bus_socket, Some("/data/bus.sock".to_string()));
assert_eq!(parsed.socket_path, "/data/alpha/sock".to_string());
assert_eq!(parsed.log_path, "/data/alpha/log".to_string());
assert_eq!(parsed.node_id, "11".repeat(16));
assert_eq!(parsed.validate(), Ok(()));
}
#[test]
fn add_node_bt_config_has_peer() {
common::env_with_fake_busd();
let fleet_name = fleet_name("bt");
let fleet = Fleet::create(&fleet_name).expect("fleet creates");
let peer = "22".repeat(16);
let spec = fleet
.add_node("bravo", None, Mode::Bt, Some(&peer))
.expect("node added");
let json = std::fs::read_to_string(spec.dir.join("config.json")).unwrap();
let parsed: tines::config::Config =
serde_json::from_str(&json).expect("config parses as the service config");
assert_eq!(parsed.transport, Some(tines::config::TransportKind::Bt));
assert_eq!(parsed.peer, Some(peer));
assert_eq!(parsed.bus_socket, None);
assert_eq!(parsed.validate(), Ok(()));
}
#[test]
fn generated_id_roundtrips() {
common::env_with_fake_busd();
let fleet_name = fleet_name("gen");
let fleet = Fleet::create(&fleet_name).expect("fleet creates");
let spec = fleet
.add_node("charlie", None, Mode::Sim, None)
.expect("node added");
let json = std::fs::read_to_string(spec.dir.join("config.json")).unwrap();
let parsed: tines::config::Config =
serde_json::from_str(&json).expect("config parses as the service config");
assert_eq!(parsed.node_id.len(), 32);
assert!(
parsed
.node_id
.chars()
.all(|c| c.is_ascii_hexdigit() && !c.is_ascii_uppercase()),
"generated id must be lowercase hex"
);
}