use super::*;
fn layout() -> CityLayout {
CityLayout::new(Path::new("/city"))
}
fn addr(raw: &str) -> Address {
Address::parse(raw).unwrap()
}
#[test]
fn a_nested_address_becomes_one_directory_per_segment() {
let expected = Path::new("/city").join("lab").join("refactor");
assert_eq!(layout().scope(&addr("lab/refactor")), expected);
}
#[test]
fn the_city_wide_stores_sit_under_the_city_s_reserved_subtree() {
let governed = Path::new("/city").join(RESERVED_PREFIX);
assert_eq!(layout().ledger(), governed.join(LEDGER_DIR));
assert_eq!(layout().cas(), governed.join(CAS_DIR));
assert_eq!(layout().library(), governed.join(LIBRARY_DIR));
assert_eq!(layout().playback_exports(), governed.join(PLAYBACK_DIR));
}
#[test]
fn what_governs_a_scope_is_unreachable_by_any_write_domain() {
let building = addr("lab");
let governing = [
layout().config(&building),
layout().filters(&building),
layout().building_skills(&building),
];
for path in governing {
let spelled = path.to_string_lossy().replace('\\', "/");
let as_address = spelled.trim_start_matches("/city/").to_owned();
assert!(
addr(&as_address).is_reserved(),
"{spelled} is not in a reserved subtree"
);
}
}
#[test]
fn what_residents_write_stays_where_residents_can_reach_it() {
let room = addr("lab/refactor");
let open = [
layout().job(&room),
layout().handoff(&room),
layout().urbanite(&room),
layout().archive(&addr("lab")),
];
for path in open {
let spelled = path.to_string_lossy().replace('\\', "/");
assert!(
!spelled.contains(RESERVED_PREFIX),
"{spelled} is governing rather than written"
);
}
}
#[test]
fn a_configuration_layer_is_named_by_the_scope_it_sits_in() {
assert_eq!(
layout().config(&addr("lab")),
Path::new("/city")
.join("lab")
.join(RESERVED_PREFIX)
.join(CONFIG_FILE)
);
}
#[test]
fn a_city_s_name_is_the_directory_it_lives_in() {
assert_eq!(
CityLayout::new(Path::new("/city")).city_address(),
Some(addr("city"))
);
assert_eq!(
CityLayout::new(Path::new("/city/bad:name")).city_address(),
None
);
assert_eq!(CityLayout::new(Path::new("/")).city_address(), None);
}
#[test]
fn a_ledger_directory_alone_yields_the_city_it_belongs_to() {
let ledger = Path::new("/city").join(RESERVED_PREFIX).join(LEDGER_DIR);
assert_eq!(
CityLayout::of_ledger(&ledger),
Some(CityLayout::new(Path::new("/city")))
);
for not_a_city in [
Path::new("/store/ledger"),
Path::new("/store/.sprawling"),
Path::new(".sprawling/ledger"),
] {
assert_eq!(CityLayout::of_ledger(not_a_city), None, "{not_a_city:?}");
}
}
#[test]
fn the_run_id_pattern_matches_every_run_id_the_city_displays() {
for bytes in [[0u8; 16], [0xffu8; 16]] {
let shown = crate::RunId::from_bytes(bytes).to_string();
assert_eq!(shown.len(), RUN_ID_PATTERN.len(), "{shown}");
for (glyph, wanted) in shown.chars().zip(RUN_ID_PATTERN.chars()) {
assert!(wanted == '?' || glyph == wanted, "{shown}");
assert_eq!(glyph == '-', wanted == '-', "{shown}");
}
}
}
#[test]
fn the_device_table_sits_in_the_remote_gate_s_own_directory_of_the_reserved_subtree() {
let devices = layout().devices();
assert_eq!(
devices,
Path::new("/city")
.join(RESERVED_PREFIX)
.join(REMOTE_DIR)
.join(DEVICES_FILE)
);
let spelled = devices.to_string_lossy().replace('\\', "/");
assert!(
addr(spelled.trim_start_matches("/city/")).is_reserved(),
"{spelled} is reachable by a write domain"
);
}
#[test]
fn a_document_staging_name_is_recognised_and_a_document_is_not() {
use std::ffi::OsStr;
for name in ["Roadmap.md", "CONFIG.toml", "a", ".hidden"] {
let staged = document_staging_name(OsStr::new(name));
assert!(is_document_staging_name(&staged), "{staged:?}");
assert!(!is_document_staging_name(OsStr::new(name)), "{name}");
}
assert_eq!(
document_staging_name(OsStr::new("Roadmap.md")),
OsStr::new(".Roadmap.md.staging")
);
for name in [".staging", "..staging", "Roadmap.md.staging", ".Roadmap.md"] {
assert!(!is_document_staging_name(OsStr::new(name)), "{name}");
}
}
#[test]
fn every_kind_of_file_has_a_path_of_its_own_inside_the_city() {
let city = layout();
let building = addr("lab");
let room = addr("lab/refactor");
let paths = [
city.ledger(),
city.snapshot(),
city.cas(),
city.library(),
city.city_config(),
city.city_filters(),
city.guide(),
city.devices(),
city.playback_exports(),
city.config(&building),
city.filters(&building),
city.building_skills(&building),
city.archive(&building),
city.job(&room),
city.handoff(&room),
city.urbanite(&room),
];
let distinct: std::collections::BTreeSet<&PathBuf> = paths.iter().collect();
assert_eq!(distinct.len(), paths.len(), "{paths:?}");
for path in &paths {
assert!(
path.starts_with(city.root()) && path != city.root(),
"{path:?} is not inside the city"
);
}
}