//! Asking `brokerd` for a session's state on its `state.sock` (M5c spec, section 7): the //! question as `brokerd` reads it, its answer, an error frame, silence and no listener, each an //! error with one line. Against a fake `brokerd` in the test's own directory. Do not edit. #[path = "support/brokerd.rs"] mod brokerd; #[path = "support/tmp.rs"] mod tmp; use std::time::{Duration, Instant}; use brokerd::{Answer, FakeBrokerd}; use bxcore::{DataClass, Message, PROTOCOL_VERSION, SessionId, SessionState, SessionStateReply}; use memoryd::honcho::state::{RUNBOOK, WAIT, ask}; use tmp::TempDir; fn session() -> SessionId { SessionId::new("mm-chat-1").unwrap() } #[test] fn the_constants() { assert_eq!(WAIT, Duration::from_secs(5)); assert_eq!(RUNBOOK, "see docs/runbook.md#broker-state-unavailable"); } #[test] fn the_question_and_its_answer() { let dir = TempDir::new("state-answer"); let socket = dir.path().join("run/memory-broker/state.sock"); let reply = SessionStateReply { class: DataClass::Secret, untrusted: true, }; let fake = FakeBrokerd::start(&socket, Answer::State(reply.clone())); assert_eq!(ask(&socket, &session(), WAIT), Ok(reply)); let seen = fake.seen(); assert_eq!(seen.len(), 1); assert_eq!( (seen[0].v, seen[0].id, seen[0].r#final), (PROTOCOL_VERSION, 1, true) ); assert_eq!( seen[0].msg, Message::SessionState(SessionState { session: session() }) ); } #[test] fn an_error_frame_is_an_error() { let dir = TempDir::new("state-error"); let socket = dir.path().join("state.sock"); let _fake = FakeBrokerd::start(&socket, Answer::Error("the state file is damaged".into())); assert_eq!( ask(&socket, &session(), WAIT), Err("brokerd: the state file is damaged".to_string()) ); } #[test] fn no_listener_is_an_error_at_once() { let dir = TempDir::new("state-none"); let socket = dir.path().join("state.sock"); let started = Instant::now(); let err = ask(&socket, &session(), WAIT).unwrap_err(); assert!( started.elapsed() < Duration::from_secs(1), "{:?}", started.elapsed() ); assert!(err.starts_with(&format!("{}: ", socket.display())), "{err}"); assert!(!err.contains('\n'), "{err}"); } #[test] fn silence_is_an_error_after_the_wait() { let dir = TempDir::new("state-hang"); let socket = dir.path().join("state.sock"); let fake = FakeBrokerd::start(&socket, Answer::Hang); let started = Instant::now(); let err = ask(&socket, &session(), Duration::from_millis(300)).unwrap_err(); let waited = started.elapsed(); assert!(waited >= Duration::from_millis(300), "{waited:?}"); assert!(waited < Duration::from_secs(5), "{waited:?}"); assert!(err.starts_with(&format!("{}: ", socket.display())), "{err}"); assert_eq!(fake.seen().len(), 1, "the question was not sent"); }