use super::*;
use crate::app::snapshot::Growth;
use crate::binding::{Workspace, WorkspaceKind};
use crate::git_tree::GitTree;
use std::path::PathBuf;
const MINE: &str = "/d/yog/workspaces/home";
const THEIRS: &str = "/d/yog/workspaces/corp";
fn allowed(names: &[&str]) -> BTreeSet<String> {
names.iter().map(|n| (*n).to_owned()).collect()
}
fn snap() -> Snapshot {
let mut s = Snapshot::empty(0);
for path in [MINE, THEIRS] {
s.workspaces.push(Workspace {
path: PathBuf::from(path),
kind: WorkspaceKind::Named {
name: crate::naming::leaf(std::path::Path::new(path)),
},
});
s.trees.insert(PathBuf::from(path), GitTree::default());
s.bills.insert(PathBuf::from(path), Vec::new());
s.growth.push(Growth {
workspace: PathBuf::from(path),
conversation: "c-1".to_owned(),
added: 1,
});
s.fleet.insert(
crate::nav::ws_key(std::path::Path::new(path)),
crate::fleet::Policy {
project: PathBuf::from("/d/proj"),
cap: 1,
lease: None,
},
);
}
s.projects.push(PathBuf::from("/d/proj"));
s
}
#[test]
fn a_scoped_derivation_holds_only_the_registered_workspaces() {
let scoped = snap().scoped(&allowed(&["home"]));
assert_eq!(scoped.workspaces.len(), 1);
assert_eq!(
scoped.workspaces.first().map(|w| w.path.clone()),
Some(PathBuf::from(MINE))
);
assert_eq!(
scoped.trees.keys().collect::<Vec<_>>(),
[&PathBuf::from(MINE)]
);
assert_eq!(
scoped.bills.keys().collect::<Vec<_>>(),
[&PathBuf::from(MINE)]
);
assert_eq!(scoped.growth.len(), 1);
assert_eq!(scoped.fleet.keys().collect::<Vec<_>>(), [MINE]);
assert_eq!(scoped.projects, [PathBuf::from("/d/proj")]);
}
#[test]
fn an_unregistered_name_refuses_exactly_as_an_unknown_one_does() {
let scoped = snap().scoped(&allowed(&["home"]));
let hidden = scoped.ws_path("corp").expect_err("refused");
let absent = scoped.ws_path("no-such-thing").expect_err("refused");
assert_eq!(hidden, "unknown workspace \"corp\" — known: home");
assert_eq!(absent.replace("no-such-thing", "corp"), hidden);
assert!(scoped.ws_path("home").is_ok());
}
#[test]
fn a_real_armed_entry_survives_scoping_and_reaches_the_board() {
let h = crate::app::tests::harness::Harness::new();
let (_c, mut model) = h.model();
let ws = h.ws.clone();
std::fs::write(
h.roots.yog_state.join(crate::app::cadence::CADENCE_YAML),
format!(
"fleet:\n {}:\n project: /dev/yog\n cap: 2\n",
ws.display()
),
)
.expect("cadence");
model
.dirty_handle()
.mark_all([(h.roots.yog_state.clone(), crate::watch::Mark::Watch)]);
assert!(model.tick(), "an arming publishes");
let board = |snap: &Snapshot| crate::board::build(snap, &model.ui, model.now_unix()).fleet;
assert_eq!(board(&model.snap).len(), 1, "armed, unscoped");
let name = crate::naming::leaf(&ws);
let mine = model.snap.scoped(&allowed(&[name.as_str()]));
let facts = board(&mine);
assert_eq!(
facts.len(),
1,
"a registered seat sees the loop over its own workspace"
);
assert_eq!(facts[0].cap, 2);
assert_eq!(facts[0].workspace, ws);
let theirs = model.snap.scoped(&allowed(&["somebody-else"]));
assert!(
board(&theirs).is_empty(),
"an unregistered workspace's loop stays absent, which is the other half"
);
}
#[test]
fn an_unseated_client_sees_no_workspace_at_all() {
let scoped = snap().scoped(&BTreeSet::new());
assert!(scoped.workspaces.is_empty());
assert!(scoped.trees.is_empty());
assert!(scoped.fleet.is_empty());
assert!(scoped.growth.is_empty());
assert!(scoped.ws_path("home").is_err());
}