use super::*;
use crate::cli_outbound::Cli;
use std::fs;
use std::os::unix::fs::PermissionsExt;
use tempfile::tempdir;
fn ambient() -> Env {
Env::from_pairs([
("HOME", "/h"),
("XDG_DATA_HOME", "/d"),
("XDG_CACHE_HOME", "/c"),
("LITANY_HOME", "/ambient/litany"),
("XDG_STATE_HOME", "/ambient/state"),
("BRAZEN_CONFIG", "/ambient/brazen.toml"),
("PATH", "/usr/bin:/bin"),
("USER", "alice"),
])
}
type Case = (fn(&Env) -> PathBuf, &'static str);
#[test]
fn overrides_win_and_every_substrate_fold_nests() {
let world = compose(&ambient());
let cases: &[Case] = &[
(Env::litany_config_root, "/d/yog/world/litany"),
(Env::litany_data_root, "/d/yog/world/litany"),
(Env::balls_state_root, "/d/yog/world/state/balls"),
(Env::balls_clones_dir, "/d/yog/world/state/balls/clones"),
(Env::yog_state_root, "/d/yog/world/state/yog"),
(Env::yog_stage_root, "/d/yog/world/state/yog/stage"),
];
for &(fold, expect) in cases {
assert_eq!(fold(&world), PathBuf::from(expect));
}
assert_eq!(
world.yog_state_root().join("ui.json"),
PathBuf::from("/d/yog/world/state/yog/ui.json")
);
assert_eq!(
world.yog_state_root().join("ops.jsonl"),
PathBuf::from("/d/yog/world/state/yog/ops.jsonl")
);
}
#[test]
fn nothing_brazen_survives_the_world_and_the_anchor_is_self_consistent() {
let amb = ambient();
let world = compose(&amb);
assert_eq!(world.wall(), None);
assert_eq!(crate::config_edit::brazen::BrazenPaths::of(&world), None);
let corp = crate::world::wall::env(&world, std::path::Path::new("/ws/corp"));
let paths = crate::config_edit::brazen::BrazenPaths::of(&corp).expect("a wall");
assert!(paths.config.starts_with("/d/yog/world/walls/corp"));
assert!(paths.credentials_dir.starts_with("/d/yog/world/walls/corp"));
assert!(
paths
.models_cache_dir
.starts_with("/d/yog/world/walls/corp")
);
assert_eq!(world.yog_data_root(), amb.yog_data_root());
assert_eq!(layout(&world).root, layout(&amb).root);
assert_eq!(world.user(), Some("alice".to_owned()));
}
#[test]
fn layout_names_the_world_subtree() {
let l = layout(&ambient());
assert_eq!(l.root, PathBuf::from("/d/yog/world"));
assert_eq!(l.litany, PathBuf::from("/d/yog/world/litany"));
assert_eq!(l.state, PathBuf::from("/d/yog/world/state"));
assert_eq!(l.tools, PathBuf::from("/d/yog/world/tools"));
}
#[test]
fn the_override_set_nests_two_state_vars_and_fronts_the_tool_path() {
let amb = ambient();
let ov = overrides(&amb);
assert_eq!(
ov,
vec![
("LITANY_HOME".to_owned(), "/d/yog/world/litany".to_owned()),
("XDG_STATE_HOME".to_owned(), "/d/yog/world/state".to_owned()),
(
"PATH".to_owned(),
"/d/yog/world/tools:/usr/bin:/bin".to_owned()
),
]
);
assert_eq!(overrides(&compose(&amb)), ov);
}
#[test]
fn a_bare_bl_spawned_in_the_world_resolves_to_the_seeded_shim() {
let data = tempdir().unwrap();
let bin = tempdir().unwrap();
let log = bin.path().join("ran");
let target = bin.path().join("yog");
fs::write(
&target,
format!("#!/bin/sh\nprintf '%s' \"$*\" > '{}'\n", log.display()),
)
.unwrap();
fs::set_permissions(&target, fs::Permissions::from_mode(0o755)).unwrap();
let data_s = data.path().to_string_lossy().into_owned();
let amb = Env::from_pairs([
("HOME", "/h"),
("XDG_DATA_HOME", data_s.as_str()),
("PATH", "/nonexistent"),
]);
tools::ensure_shim(&layout(&amb).tools, tools::BL, &Cli::new(&target)).unwrap();
let stream = Cli::new(tools::BL)
.with_env(overrides(&amb))
.run(&["close", "bl-1a2b"])
.unwrap();
for _ in stream {}
assert_eq!(fs::read_to_string(&log).unwrap(), "close bl-1a2b");
}
#[test]
fn watched_clones_dir_equals_the_dir_a_world_spawned_bl_writes() {
let data = tempdir().unwrap();
let bin = tempdir().unwrap();
let log = bin.path().join("state");
let data_s = data.path().to_string_lossy().into_owned();
let amb = Env::from_pairs([("HOME", "/h"), ("XDG_DATA_HOME", data_s.as_str())]);
let world = compose(&amb);
let ov = overrides(&amb);
let path = bin.path().join("bl");
fs::write(
&path,
format!(
"#!/bin/sh\nprintf '%s' \"$XDG_STATE_HOME\" > '{}'\n",
log.display()
),
)
.unwrap();
let mut perms = fs::metadata(&path).unwrap().permissions();
perms.set_mode(0o755);
fs::set_permissions(&path, perms).unwrap();
let stream = Cli::new(path).with_env(ov).run(&[]).unwrap();
for _ in stream {}
let child_state = fs::read_to_string(&log).unwrap();
assert_eq!(Path::new(&child_state), layout(&amb).state);
let spawned_clones = Path::new(&child_state).join("balls").join("clones");
assert_eq!(spawned_clones, world.balls_clones_dir());
}