127 lines
3.4 KiB
Rust
127 lines
3.4 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}");
|
|
}
|
|
|
|
#[test]
|
|
fn rehash_applies_channel_nick_and_prefix() {
|
|
let output = Arc::new(Mutex::new(Vec::new()));
|
|
let mock = Mock {
|
|
input: Cursor::new(Vec::new()),
|
|
output: output.clone(),
|
|
};
|
|
let conn = Connection::from_stream(mock);
|
|
let cfg = Config {
|
|
name: "testnet".to_string(),
|
|
channels: vec!["#a".to_string(), "#keep".to_string()],
|
|
..Config::default()
|
|
};
|
|
let mut bot = Bot::new(cfg, conn);
|
|
|
|
let new = Config {
|
|
name: "testnet".to_string(),
|
|
channels: vec!["#keep".to_string(), "#b".to_string()],
|
|
command_prefix: ">".to_string(),
|
|
nick: "rubot2".to_string(),
|
|
..Config::default()
|
|
};
|
|
let summary = bot.apply_config(new).unwrap();
|
|
|
|
let out = String::from_utf8_lossy(&output.lock().unwrap()).into_owned();
|
|
assert!(out.contains("JOIN #b"), "{out}");
|
|
assert!(out.contains("PART #a"), "{out}");
|
|
assert!(!out.contains("PART #keep"), "{out}");
|
|
assert!(out.contains("NICK rubot2"), "{out}");
|
|
assert!(
|
|
summary.contains("+#b") && summary.contains("-#a"),
|
|
"{summary}"
|
|
);
|
|
assert!(
|
|
summary.contains("prefix") && summary.contains("nick"),
|
|
"{summary}"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn rehash_command_requires_admin() {
|
|
// no admin configured -> ignored (default prefix is !)
|
|
let out = run(":alice!a@h PRIVMSG #chan :!rehash\r\n");
|
|
assert!(
|
|
!out.contains("rehash:"),
|
|
"unauthorized rehash replied: {out}"
|
|
);
|
|
}
|