rubot/tests/bot.rs

78 lines
1.9 KiB
Rust

use std::io::{self, Cursor, Read, Write};
use std::sync::{Arc, Mutex};
use rustbot::bot::Bot;
use rustbot::config::Config;
use rustbot::irc::Connection;
struct Mock {
input: Cursor<Vec<u8>>,
output: Arc<Mutex<Vec<u8>>>,
}
impl Read for Mock {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.input.read(buf)
}
}
impl Write for Mock {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.output.lock().unwrap().extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
fn run(server: &str) -> String {
let output = Arc::new(Mutex::new(Vec::new()));
let mock = Mock {
input: Cursor::new(server.as_bytes().to_vec()),
output: output.clone(),
};
let conn = Connection::from_stream(mock);
let mut bot = Bot::new(Config::default(), conn);
let _ = bot.run();
let bytes = output.lock().unwrap().clone();
String::from_utf8_lossy(&bytes).into_owned()
}
#[test]
fn sends_registration() {
let out = run("");
assert!(out.contains("CAP LS"), "{out}");
assert!(out.contains("NICK rubot"), "{out}");
assert!(out.contains("USER rubot"), "{out}");
}
#[test]
fn answers_ping() {
let out = run("PING :tok123\r\n");
assert!(out.contains("PONG :tok123"), "{out}");
}
#[test]
fn joins_configured_channels_on_welcome() {
let out = run(":srv 001 rubot :welcome\r\n");
assert!(out.contains("JOIN #devs"), "{out}");
}
#[test]
fn appends_underscore_on_nick_in_use() {
let out = run(":srv 433 * rubot :nickname is already in use\r\n");
assert!(out.contains("NICK rubot_"), "{out}");
}
#[test]
fn dispatches_command_to_module() {
let out = run(":alice!a@h PRIVMSG #chan :!ping\r\n");
assert!(out.contains("PRIVMSG #chan :pong"), "{out}");
}
#[test]
fn ignores_own_echoed_message() {
let out = run(":rubot!r@h PRIVMSG #chan :!ping\r\n");
assert!(!out.contains(":pong"), "{out}");
}