use super::*;
use wsb::peer::identity::{Fingerprint, PairedPeer};
use wsb::peer::model::{PeerId, RepositoryId, SharedWorktreeId};
use crate::machine::MachineState;
fn machine() -> (tokio::runtime::Runtime, tempfile::TempDir, Arc<MachineState>) {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.expect("a runtime");
let dir = tempfile::tempdir().expect("a scratch directory");
let machine = {
let _inside = runtime.enter();
MachineState::new(
dir.path().to_path_buf(),
&dir.path().join("wsb.db"),
std::net::IpAddr::V4(std::net::Ipv4Addr::LOCALHOST),
0,
std::net::IpAddr::V4(std::net::Ipv4Addr::LOCALHOST),
0,
)
.expect("a machine with an identity and a store")
};
(runtime, dir, machine)
}
fn pair(machine: &Arc<MachineState>, id: &str, name: &str) -> PeerId {
let peer = PeerId::parse(id).expect("a peer id");
machine
.store
.add_peer(&PairedPeer {
id: peer.clone(),
name: name.to_string(),
public_key: format!("key-{id}"),
fingerprint: Fingerprint::from_stored(format!("{id}-{id}-{id}")),
address: "127.0.0.1:9494".to_string(),
paired_at: 0,
})
.expect("the peer is remembered");
peer
}
fn conflict(
machine: &Arc<MachineState>,
peer: &PeerId,
worktree: &str,
repository: &str,
path: &str,
) {
machine
.store
.record_conflict(
peer,
&SharedWorktreeId::parse(worktree).expect("a worktree id"),
&if repository.is_empty() {
RepositoryId::root()
} else {
RepositoryId::parse(repository).expect("a repository id")
},
path,
None,
None,
None,
0,
)
.expect("the conflict is recorded");
}
#[test]
fn test9583_conflicts_are_counted_by_workspace_repository_and_peer() {
let (runtime, _scratch, machine) = machine();
let laptop = pair(&machine, "laptop", "bahram-mac");
let desktop = pair(&machine, "desktop", "bahram-linux");
machine
.store
.register_worktree(&wsb::daemon::RegisteredWorktree {
id: wsb::daemon::WorktreeId::parse("machinefabric:main").expect("a worktree id"),
project: Some("machinefabric".to_string()),
name: "main".to_string(),
shared: Some(SharedWorktreeId::parse("db3f3a6e071ee7e0@main").expect("a worktree id")),
super_root: std::path::PathBuf::from("/ws/prj/machinefabric/main-worktree"),
root_commit: Some(format!("{:040x}", 1)),
last_seen: 0,
available: true,
})
.expect("the worktree is recorded");
conflict(&machine, &laptop, "db3f3a6e071ee7e0@main", "wsb", "src/main.rs");
conflict(&machine, &laptop, "db3f3a6e071ee7e0@main", "wsb", "src/lib.rs");
conflict(&machine, &desktop, "db3f3a6e071ee7e0@main", "wsb", "src/main.rs");
conflict(&machine, &laptop, "db3f3a6e071ee7e0@main", "", "README.md");
let Json(census) = runtime.block_on(conflicts(State(machine.clone())));
assert_eq!(census.total, 4, "every waiting conflict is counted");
assert_eq!(census.worktrees.len(), 1);
let worktree = &census.worktrees[0];
assert_eq!(
worktree.display_name, "machinefabric/main",
"named as the projects list names the worktree, not by its id"
);
assert_eq!(worktree.total, 4);
let repositories: Vec<(&str, usize, Vec<&str>)> = worktree
.repositories
.iter()
.map(|repository| {
(
repository.repository.as_str(),
repository.conflicts,
repository.peers.iter().map(String::as_str).collect(),
)
})
.collect();
assert_eq!(
repositories,
vec![
("", 1, vec!["bahram-mac"]),
("wsb", 3, vec!["bahram-linux", "bahram-mac"]),
],
"the superproject is the empty repository, exactly as the tree \
addresses it, and each repository names the machines it disagrees \
with, in the order a person reads them"
);
}
#[test]
fn test9584_a_conflict_in_an_unregistered_workspace_is_still_counted() {
let (runtime, _scratch, machine) = machine();
let laptop = pair(&machine, "laptop", "bahram-mac");
conflict(&machine, &laptop, "2502501b3cb21cc4@main", "", "README.md");
let Json(census) = runtime.block_on(conflicts(State(machine.clone())));
assert_eq!(census.total, 1);
assert_eq!(
census.worktrees[0].display_name, "2502501b3cb21cc4@main",
"with no name to give it, the page shows the id rather than nothing"
);
}
#[test]
fn test20121_a_rename_names_the_machine_now_and_from_its_file() {
let (runtime, dir, machine) = machine();
let id = machine.identity.id().clone();
let renamed = runtime
.block_on(rename(State(machine.clone()), Json(RenameRequest { name: " bench ".to_string() })))
.expect("the machine is renamed");
assert_eq!(renamed.0.name, "bench", "the daemon answers with the new name, trimmed");
assert_eq!(machine.identity.name(), "bench");
let reloaded = wsb::peer::identity::MachineIdentity::load_or_create(dir.path(), "other").expect("the file reads");
assert_eq!((reloaded.name(), reloaded.id()), ("bench".to_string(), &id), "the file holds the new name");
let (status, _) = runtime
.block_on(rename(State(machine.clone()), Json(RenameRequest { name: " ".to_string() })))
.expect_err("an empty name");
assert_eq!(status, axum::http::StatusCode::BAD_REQUEST);
assert_eq!(machine.identity.name(), "bench", "a refused rename changed the name");
}