1use std::collections::BTreeMap;
13
14use crate::address::Address;
15use crate::event::RunId;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
20pub enum RepairVerdict {
21 Lease,
22 Queued { holder: RunId },
23}
24
25pub fn request(active: &BTreeMap<Address, RunId>, scope: &Address, who: &RunId) -> RepairVerdict {
29 for (held, holder) in active {
30 let overlaps = scope.is_within(held) || held.is_within(scope);
31 if !overlaps {
32 continue;
33 }
34 if held == scope && holder == who {
35 return RepairVerdict::Lease;
36 }
37 return RepairVerdict::Queued { holder: *holder };
38 }
39 RepairVerdict::Lease
40}
41
42#[cfg(test)]
43#[allow(
44 clippy::unwrap_used,
45 clippy::expect_used,
46 clippy::panic,
47 clippy::indexing_slicing,
48 reason = "test code"
49)]
50mod tests {
51 use super::*;
52
53 fn addr(raw: &str) -> Address {
54 Address::parse(raw).unwrap()
55 }
56
57 fn run(n: u8) -> RunId {
58 RunId::parse(&format!("0198f6a2-7c4a-7bbb-9d1e-0000000000{n:02x}")).unwrap()
59 }
60
61 #[test]
62 fn a_free_scope_leases() {
63 let active = BTreeMap::new();
64 assert_eq!(
65 request(&active, &addr("b/env"), &run(1)),
66 RepairVerdict::Lease
67 );
68 }
69
70 #[test]
71 fn overlap_queues_either_way_and_names_the_holder() {
72 let mut active = BTreeMap::new();
73 active.insert(addr("b/env"), run(1));
74 assert_eq!(
75 request(&active, &addr("b/env/tools"), &run(2)),
76 RepairVerdict::Queued { holder: run(1) }
77 );
78 assert_eq!(
79 request(&active, &addr("b"), &run(2)),
80 RepairVerdict::Queued { holder: run(1) }
81 );
82 assert_eq!(
83 request(&active, &addr("other"), &run(2)),
84 RepairVerdict::Lease
85 );
86 }
87
88 #[test]
89 fn the_holder_re_requesting_its_exact_scope_re_leases() {
90 let mut active = BTreeMap::new();
91 active.insert(addr("b/env"), run(1));
92 assert_eq!(
93 request(&active, &addr("b/env"), &run(1)),
94 RepairVerdict::Lease
95 );
96 assert_eq!(
99 request(&active, &addr("b/env/x"), &run(1)),
100 RepairVerdict::Queued { holder: run(1) }
101 );
102 }
103}