gatewayd: a turn's speaker, the username of the one person who wrote its burst
Co-Authored-By: ornith-1.5-35b-a3b <agent@wntrmute.dev>
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
//! The speaker `deliver` is given goes on the turn it sends to `loopd`, and nowhere else: not into
|
||||
//! the turn's text (M5c spec, section 11). Do not edit.
|
||||
|
||||
#[path = "support/fake_loop.rs"]
|
||||
mod fake_loop;
|
||||
#[path = "support/tmp.rs"]
|
||||
mod tmp;
|
||||
|
||||
use std::sync::Mutex;
|
||||
use std::time::Duration;
|
||||
|
||||
use bxcore::{ErrorCode, SessionId, Turn};
|
||||
use fake_loop::{done, error, serve_loop};
|
||||
use gatewayd::deliver::{Notice, Poster, deliver};
|
||||
use gatewayd::mm::MmError;
|
||||
use gatewayd::sessions::{Batch, Thread};
|
||||
use tmp::TempDir;
|
||||
|
||||
const DM: &str = "d0000000000000000000000000";
|
||||
const ROOT: &str = "r0000000000000000000000000";
|
||||
const KYLE: &str = "k0000000000000000000000000";
|
||||
const WAIT: Duration = Duration::from_secs(5);
|
||||
|
||||
#[derive(Default)]
|
||||
struct Record(Mutex<Vec<String>>);
|
||||
|
||||
impl Poster for Record {
|
||||
fn post(&self, _: &str, _: &str, text: &str) -> Result<(), MmError> {
|
||||
self.0.lock().unwrap().push(text.to_string());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// One `deliver` of "one\n\ntwo" with `speaker`, against a fake `loopd` whose n-th turn gets
|
||||
/// `script(n)`; the turns it received and what was posted.
|
||||
fn deliver_with(
|
||||
tag: &str,
|
||||
speaker: Option<&str>,
|
||||
script: fn(usize) -> Vec<fake_loop::Reply>,
|
||||
) -> (Vec<Turn>, Vec<String>) {
|
||||
let dir = TempDir::new(tag);
|
||||
let socket = dir.path().join("loop.sock");
|
||||
let turns = serve_loop(&socket, move |n, _| script(n));
|
||||
let batch = Batch {
|
||||
session: SessionId::new(&format!("mm-{ROOT}")).unwrap(),
|
||||
thread: Thread {
|
||||
channel: DM.to_string(),
|
||||
root: ROOT.to_string(),
|
||||
},
|
||||
resume: true,
|
||||
text: "one\n\ntwo".to_string(),
|
||||
senders: vec![KYLE.to_string(), KYLE.to_string()],
|
||||
};
|
||||
let never = |_: u64| false;
|
||||
let notice = Notice {
|
||||
posted: &never,
|
||||
wait: Duration::ZERO,
|
||||
};
|
||||
let poster = Record::default();
|
||||
let log = Mutex::new(Vec::new());
|
||||
deliver(
|
||||
&poster,
|
||||
&socket,
|
||||
&batch,
|
||||
speaker,
|
||||
&|line| log.lock().unwrap().push(line.to_string()),
|
||||
¬ice,
|
||||
);
|
||||
assert!(log.lock().unwrap().is_empty(), "{:?}", log.lock().unwrap());
|
||||
// The fake reports each turn before it answers, so every turn is in by now.
|
||||
let mut got = vec![turns.recv_timeout(WAIT).unwrap()];
|
||||
while let Ok(turn) = turns.try_recv() {
|
||||
got.push(turn);
|
||||
}
|
||||
(got, poster.0.into_inner().unwrap())
|
||||
}
|
||||
|
||||
fn answer(_: usize) -> Vec<fake_loop::Reply> {
|
||||
vec![done("fine")]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_speaker_goes_on_the_turn_and_not_into_its_text() {
|
||||
let (turns, posts) = deliver_with("speaker-some", Some("first.last"), answer);
|
||||
assert_eq!(turns.len(), 1);
|
||||
let turn = &turns[0];
|
||||
assert_eq!(turn.speaker.as_deref(), Some("first.last"));
|
||||
assert_eq!(
|
||||
(turn.content.as_str(), turn.resume),
|
||||
("one\n\ntwo", true),
|
||||
"the text is the batch's, unchanged"
|
||||
);
|
||||
assert_eq!(posts, ["fine"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn without_a_speaker_the_turn_has_none() {
|
||||
let (turns, posts) = deliver_with("speaker-none", None, answer);
|
||||
assert_eq!(turns.len(), 1);
|
||||
assert_eq!(turns[0].speaker, None, "never the user id");
|
||||
assert_eq!(turns[0].content, "one\n\ntwo");
|
||||
assert_eq!(posts, ["fine"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_turn_sent_again_for_an_unknown_session_keeps_the_speaker() {
|
||||
let unknown_first = |n: usize| {
|
||||
if n == 0 {
|
||||
vec![error(ErrorCode::NoSuchSession, "no such session")]
|
||||
} else {
|
||||
vec![done("hello")]
|
||||
}
|
||||
};
|
||||
let (turns, posts) = deliver_with("speaker-again", Some("kyle"), unknown_first);
|
||||
let seen: Vec<(bool, Option<&str>)> = turns
|
||||
.iter()
|
||||
.map(|t| (t.resume, t.speaker.as_deref()))
|
||||
.collect();
|
||||
assert_eq!(seen, [(true, Some("kyle")), (false, Some("kyle"))]);
|
||||
assert_eq!(posts, ["hello"]);
|
||||
}
|
||||
Reference in New Issue
Block a user