96 lines
3.2 KiB
Rust
96 lines
3.2 KiB
Rust
//! The approval posts in the state file, for marking them at a restart; an M4a state file still
|
|
//! loads; and the turn of a session (M4b spec, sections 6 and 8). Do not edit.
|
|
|
|
#[path = "support/tmp.rs"]
|
|
mod tmp;
|
|
|
|
use gatewayd::state::{ApprovalPosts, InFlight, State, StateError};
|
|
use tmp::TempDir;
|
|
|
|
const DM: &str = "d0000000000000000000000000";
|
|
const ROOT: &str = "r0000000000000000000000000";
|
|
|
|
fn id(n: u32) -> String {
|
|
format!("p{n:025}")
|
|
}
|
|
|
|
fn shown(approval: u64, posts: &[u32]) -> ApprovalPosts {
|
|
ApprovalPosts {
|
|
approval,
|
|
channel: DM.to_string(),
|
|
posts: posts.iter().map(|n| id(*n)).collect(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn approval_posts_survive_a_restart_and_are_taken_once() {
|
|
let dir = TempDir::new("state-approvals");
|
|
let path = dir.path().join("gateway/state.json");
|
|
let mut s = State::load(&path).unwrap();
|
|
s.add_approval(shown(42, &[1, 2])).unwrap();
|
|
s.add_approval(shown(43, &[3])).unwrap();
|
|
s.add_approval(shown(42, &[4])).unwrap();
|
|
s.remove_approval(43).unwrap();
|
|
s.remove_approval(99).unwrap();
|
|
let mut again = State::load(&path).unwrap();
|
|
assert_eq!(
|
|
again.take_approvals().unwrap(),
|
|
[shown(42, &[4])],
|
|
"the later posting of 42 replaced the first"
|
|
);
|
|
assert!(
|
|
State::load(&path)
|
|
.unwrap()
|
|
.take_approvals()
|
|
.unwrap()
|
|
.is_empty(),
|
|
"taking is saved"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn an_m4a_state_file_loads() {
|
|
let dir = TempDir::new("state-m4a");
|
|
let text = format!(r#"{{"channels":{{"{DM}":5}},"recent":[],"threads":[],"in_flight":[]}}"#);
|
|
let path = dir.write("state.json", &text);
|
|
let mut s = State::load(&path).unwrap();
|
|
assert_eq!(s.since(DM), Some(5));
|
|
assert!(s.take_approvals().unwrap().is_empty());
|
|
}
|
|
|
|
#[test]
|
|
fn bad_approval_posts_are_refused() {
|
|
let dir = TempDir::new("state-approvals-bad");
|
|
for (n, approvals) in [
|
|
r#"[{"approval":1,"channel":"../x","posts":["p0000000000000000000000001"]}]"#,
|
|
r#"[{"approval":1,"channel":"d0000000000000000000000000","posts":[]}]"#,
|
|
r#"[{"approval":1,"channel":"d0000000000000000000000000","posts":["short"]}]"#,
|
|
r#"[{"approval":1,"channel":"d0000000000000000000000000","posts":["p0000000000000000000000001"],"extra":1}]"#,
|
|
r#"[{"approval":-1,"channel":"d0000000000000000000000000","posts":["p0000000000000000000000001"]}]"#,
|
|
]
|
|
.iter()
|
|
.enumerate()
|
|
{
|
|
let text = format!(r#"{{"channels":{{}},"recent":[],"threads":[],"in_flight":[],"approvals":{approvals}}}"#);
|
|
let path = dir.write(&format!("s{n}.json"), &text);
|
|
assert!(matches!(State::load(&path), Err(StateError::Read(..))), "{approvals}");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn the_turn_of_a_session() {
|
|
let dir = TempDir::new("state-turn-of");
|
|
let mut s = State::load(&dir.path().join("state.json")).unwrap();
|
|
let turn = InFlight {
|
|
session: format!("mm-{ROOT}"),
|
|
channel: DM.to_string(),
|
|
root: ROOT.to_string(),
|
|
};
|
|
assert_eq!(s.turn_of(&turn.session), None);
|
|
s.start_turn(turn.clone()).unwrap();
|
|
assert_eq!(s.turn_of(&turn.session), Some(turn.clone()));
|
|
assert_eq!(s.turn_of("mm-other"), None);
|
|
s.end_turn(&turn.session).unwrap();
|
|
assert_eq!(s.turn_of(&turn.session), None);
|
|
}
|