Merge pull request #185 from udoprog/thiserror
Switch to modern error handling
This commit is contained in:
commit
8a6d8f4017
14 changed files with 143 additions and 171 deletions
|
@ -27,11 +27,11 @@ json = ["serde_json"]
|
||||||
yaml = ["serde_yaml"]
|
yaml = ["serde_yaml"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
thiserror = "1.0.2"
|
||||||
bufstream = "0.1"
|
bufstream = "0.1"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
encoding = "0.2"
|
encoding = "0.2"
|
||||||
failure = "0.1"
|
|
||||||
irc-proto = { version = "*", path = "irc-proto" }
|
irc-proto = { version = "*", path = "irc-proto" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
native-tls = "0.2"
|
native-tls = "0.2"
|
||||||
|
@ -46,7 +46,7 @@ toml = { version = "0.4", optional = true }
|
||||||
pin-utils = "0.1.0-alpha.4"
|
pin-utils = "0.1.0-alpha.4"
|
||||||
parking_lot = "0.9.0"
|
parking_lot = "0.9.0"
|
||||||
futures-channel = "0.3.1"
|
futures-channel = "0.3.1"
|
||||||
futures-util = "0.3.1"
|
futures-util = { version = "0.3.1", features = ["sink"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
futures = "0.3.1"
|
futures = "0.3.1"
|
||||||
|
|
|
@ -8,6 +8,7 @@ keywords = ["irc", "protocol", "tokio"]
|
||||||
categories = ["network-programming"]
|
categories = ["network-programming"]
|
||||||
documentation = "https://docs.rs/irc-proto/"
|
documentation = "https://docs.rs/irc-proto/"
|
||||||
repository = "https://github.com/aatxe/irc"
|
repository = "https://github.com/aatxe/irc"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
travis-ci = { repository = "aatxe/irc" }
|
travis-ci = { repository = "aatxe/irc" }
|
||||||
|
@ -18,6 +19,6 @@ default = ["tokio", "tokio-util", "bytes"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bytes = { version = "0.5", optional = true }
|
bytes = { version = "0.5", optional = true }
|
||||||
encoding = "0.2"
|
encoding = "0.2"
|
||||||
failure = "0.1"
|
thiserror = "1.0.2"
|
||||||
tokio-util = { version = "0.2.0", optional = true }
|
tokio-util = { version = "0.2.0", optional = true }
|
||||||
tokio = { version = "0.2.0", optional = true }
|
tokio = { version = "0.2.0", optional = true }
|
||||||
|
|
|
@ -118,7 +118,7 @@ impl FormattedStringExt<'static> for String {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use colors::FormattedStringExt;
|
use crate::colors::FormattedStringExt;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
macro_rules! test_formatted_string_ext {
|
macro_rules! test_formatted_string_ext {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
//! Enumeration of all available client commands.
|
//! Enumeration of all available client commands.
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use chan::ChannelExt;
|
use crate::chan::ChannelExt;
|
||||||
use error::MessageParseError;
|
use crate::error::MessageParseError;
|
||||||
use mode::{ChannelMode, Mode, UserMode};
|
use crate::mode::{ChannelMode, Mode, UserMode};
|
||||||
use response::Response;
|
use crate::response::Response;
|
||||||
|
|
||||||
/// List of all client commands as defined in [RFC 2812](http://tools.ietf.org/html/rfc2812). This
|
/// List of all client commands as defined in [RFC 2812](http://tools.ietf.org/html/rfc2812). This
|
||||||
/// also includes commands from the
|
/// also includes commands from the
|
||||||
|
|
|
@ -1,57 +1,57 @@
|
||||||
//! IRC protocol errors using `failure`.
|
//! IRC protocol errors using `failure`.
|
||||||
|
|
||||||
use std::io::Error as IoError;
|
use thiserror::Error;
|
||||||
|
|
||||||
/// A `Result` type for IRC `ProtocolErrors`.
|
/// A `Result` type for IRC `ProtocolErrors`.
|
||||||
pub type Result<T> = ::std::result::Result<T, ProtocolError>;
|
pub type Result<T, E = ProtocolError> = ::std::result::Result<T, E>;
|
||||||
|
|
||||||
/// An IRC protocol error.
|
/// An IRC protocol error.
|
||||||
#[derive(Debug, Fail)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ProtocolError {
|
pub enum ProtocolError {
|
||||||
/// An internal I/O error.
|
/// An internal I/O error.
|
||||||
#[fail(display = "an io error occurred")]
|
#[error("an io error occurred")]
|
||||||
Io(#[cause] IoError),
|
Io(#[source] std::io::Error),
|
||||||
|
|
||||||
/// Error for invalid messages.
|
/// Error for invalid messages.
|
||||||
#[fail(display = "invalid message: {}", string)]
|
#[error("invalid message: {}", string)]
|
||||||
InvalidMessage {
|
InvalidMessage {
|
||||||
/// The string that failed to parse.
|
/// The string that failed to parse.
|
||||||
string: String,
|
string: String,
|
||||||
/// The detailed message parsing error.
|
/// The detailed message parsing error.
|
||||||
#[cause]
|
#[source]
|
||||||
cause: MessageParseError,
|
cause: MessageParseError,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<IoError> for ProtocolError {
|
impl From<std::io::Error> for ProtocolError {
|
||||||
fn from(e: IoError) -> ProtocolError {
|
fn from(e: std::io::Error) -> ProtocolError {
|
||||||
ProtocolError::Io(e)
|
ProtocolError::Io(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Errors that occur when parsing messages.
|
/// Errors that occur when parsing messages.
|
||||||
#[derive(Debug, Fail)]
|
#[derive(Debug, Error)]
|
||||||
pub enum MessageParseError {
|
pub enum MessageParseError {
|
||||||
/// The message was empty.
|
/// The message was empty.
|
||||||
#[fail(display = "empty message")]
|
#[error("empty message")]
|
||||||
EmptyMessage,
|
EmptyMessage,
|
||||||
|
|
||||||
/// The command was invalid (i.e. missing).
|
/// The command was invalid (i.e. missing).
|
||||||
#[fail(display = "invalid command")]
|
#[error("invalid command")]
|
||||||
InvalidCommand,
|
InvalidCommand,
|
||||||
|
|
||||||
/// The mode string was malformed.
|
/// The mode string was malformed.
|
||||||
#[fail(display = "invalid mode string: {}", string)]
|
#[error("invalid mode string: {}", string)]
|
||||||
InvalidModeString {
|
InvalidModeString {
|
||||||
/// The invalid mode string.
|
/// The invalid mode string.
|
||||||
string: String,
|
string: String,
|
||||||
/// The detailed mode parsing error.
|
/// The detailed mode parsing error.
|
||||||
#[cause]
|
#[source]
|
||||||
cause: ModeParseError,
|
cause: ModeParseError,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// The subcommand used was invalid.
|
/// The subcommand used was invalid.
|
||||||
#[fail(display = "invalid {} subcommand: {}", cmd, sub)]
|
#[error("invalid {} subcommand: {}", cmd, sub)]
|
||||||
InvalidSubcommand {
|
InvalidSubcommand {
|
||||||
/// The command whose invalid subcommand was referenced.
|
/// The command whose invalid subcommand was referenced.
|
||||||
cmd: &'static str,
|
cmd: &'static str,
|
||||||
|
@ -61,16 +61,16 @@ pub enum MessageParseError {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Errors that occur while parsing mode strings.
|
/// Errors that occur while parsing mode strings.
|
||||||
#[derive(Debug, Fail)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ModeParseError {
|
pub enum ModeParseError {
|
||||||
/// Invalid modifier used in a mode string (only + and - are valid).
|
/// Invalid modifier used in a mode string (only + and - are valid).
|
||||||
#[fail(display = "invalid mode modifier: {}", modifier)]
|
#[error("invalid mode modifier: {}", modifier)]
|
||||||
InvalidModeModifier {
|
InvalidModeModifier {
|
||||||
/// The invalid mode modifier.
|
/// The invalid mode modifier.
|
||||||
modifier: char,
|
modifier: char,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Missing modifier used in a mode string.
|
/// Missing modifier used in a mode string.
|
||||||
#[fail(display = "missing mode modifier")]
|
#[error("missing mode modifier")]
|
||||||
MissingModeModifier,
|
MissingModeModifier,
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
use bytes::BytesMut;
|
use bytes::BytesMut;
|
||||||
use tokio_util::codec::{Decoder, Encoder};
|
use tokio_util::codec::{Decoder, Encoder};
|
||||||
|
|
||||||
use error;
|
use crate::error;
|
||||||
use line::LineCodec;
|
use crate::line::LineCodec;
|
||||||
use message::Message;
|
use crate::message::Message;
|
||||||
|
|
||||||
/// An IRC codec built around an inner codec.
|
/// An IRC codec built around an inner codec.
|
||||||
pub struct IrcCodec {
|
pub struct IrcCodec {
|
||||||
|
|
|
@ -2,16 +2,6 @@
|
||||||
|
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
#[cfg(feature = "tokio")]
|
|
||||||
extern crate bytes;
|
|
||||||
extern crate encoding;
|
|
||||||
#[macro_use]
|
|
||||||
extern crate failure;
|
|
||||||
#[cfg(feature = "tokio")]
|
|
||||||
extern crate tokio;
|
|
||||||
#[cfg(feature = "tokio-util")]
|
|
||||||
extern crate tokio_util;
|
|
||||||
|
|
||||||
pub mod caps;
|
pub mod caps;
|
||||||
pub mod chan;
|
pub mod chan;
|
||||||
pub mod colors;
|
pub mod colors;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use encoding::label::encoding_from_whatwg_label;
|
||||||
use encoding::{DecoderTrap, EncoderTrap, EncodingRef};
|
use encoding::{DecoderTrap, EncoderTrap, EncodingRef};
|
||||||
use tokio_util::codec::{Decoder, Encoder};
|
use tokio_util::codec::{Decoder, Encoder};
|
||||||
|
|
||||||
use error;
|
use crate::error;
|
||||||
|
|
||||||
/// A line-based codec parameterized by an encoding.
|
/// A line-based codec parameterized by an encoding.
|
||||||
pub struct LineCodec {
|
pub struct LineCodec {
|
||||||
|
|
|
@ -3,11 +3,11 @@ use std::borrow::ToOwned;
|
||||||
use std::fmt::{Display, Formatter, Result as FmtResult, Write};
|
use std::fmt::{Display, Formatter, Result as FmtResult, Write};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use chan::ChannelExt;
|
use crate::chan::ChannelExt;
|
||||||
use command::Command;
|
use crate::command::Command;
|
||||||
use error;
|
use crate::error;
|
||||||
use error::{MessageParseError, ProtocolError};
|
use crate::error::{MessageParseError, ProtocolError};
|
||||||
use prefix::Prefix;
|
use crate::prefix::Prefix;
|
||||||
|
|
||||||
/// A data structure representing an IRC message according to the protocol specification. It
|
/// A data structure representing an IRC message according to the protocol specification. It
|
||||||
/// consists of a collection of IRCv3 tags, a prefix (describing the source of the message), and
|
/// consists of a collection of IRCv3 tags, a prefix (describing the source of the message), and
|
||||||
|
@ -276,7 +276,7 @@ pub struct Tag(pub String, pub Option<String>);
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::{Message, Tag};
|
use super::{Message, Tag};
|
||||||
use command::Command::{Raw, PRIVMSG, QUIT};
|
use crate::command::Command::{Raw, PRIVMSG, QUIT};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn new() {
|
fn new() {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
//! A module defining an API for IRC user and channel modes.
|
//! A module defining an API for IRC user and channel modes.
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use command::Command;
|
use crate::command::Command;
|
||||||
use error::MessageParseError;
|
use crate::error::MessageParseError;
|
||||||
use error::MessageParseError::InvalidModeString;
|
use crate::error::MessageParseError::InvalidModeString;
|
||||||
use error::ModeParseError::*;
|
use crate::error::ModeParseError::*;
|
||||||
|
|
||||||
/// A marker trait for different kinds of Modes.
|
/// A marker trait for different kinds of Modes.
|
||||||
pub trait ModeType: fmt::Display + fmt::Debug + Clone + PartialEq {
|
pub trait ModeType: fmt::Display + fmt::Debug + Clone + PartialEq {
|
||||||
|
|
|
@ -535,6 +535,7 @@ impl Config {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::Config;
|
use super::Config;
|
||||||
|
use anyhow::Result;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -601,7 +602,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
fn load_from_json() -> Result<(), failure::Error> {
|
fn load_from_json() -> Result<()> {
|
||||||
const DATA: &str = include_str!("client_config.json");
|
const DATA: &str = include_str!("client_config.json");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Config::load_json("client_config.json", DATA)?.with_path("client_config.json"),
|
Config::load_json("client_config.json", DATA)?.with_path("client_config.json"),
|
||||||
|
@ -612,7 +613,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "toml")]
|
#[cfg(feature = "toml")]
|
||||||
fn load_from_toml() -> Result<(), failure::Error> {
|
fn load_from_toml() -> Result<()> {
|
||||||
const DATA: &str = include_str!("client_config.toml");
|
const DATA: &str = include_str!("client_config.toml");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Config::load_toml("client_config.toml", DATA)?.with_path("client_config.toml"),
|
Config::load_toml("client_config.toml", DATA)?.with_path("client_config.toml"),
|
||||||
|
@ -623,7 +624,7 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
fn load_from_yaml() -> Result<(), failure::Error> {
|
fn load_from_yaml() -> Result<()> {
|
||||||
const DATA: &str = include_str!("client_config.yaml");
|
const DATA: &str = include_str!("client_config.yaml");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Config::load_yaml("client_config.yaml", DATA)?.with_path("client_config.yaml"),
|
Config::load_yaml("client_config.yaml", DATA)?.with_path("client_config.yaml"),
|
||||||
|
|
|
@ -1086,6 +1086,7 @@ mod test {
|
||||||
ChannelMode, IrcCodec, Mode,
|
ChannelMode, IrcCodec, Mode,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use anyhow::Result;
|
||||||
use futures::prelude::*;
|
use futures::prelude::*;
|
||||||
|
|
||||||
pub fn test_config() -> Config {
|
pub fn test_config() -> Config {
|
||||||
|
@ -1120,7 +1121,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn stream() -> Result<(), failure::Error> {
|
async fn stream() -> Result<()> {
|
||||||
let exp = "PRIVMSG test :Hi!\r\nPRIVMSG test :This is a test!\r\n\
|
let exp = "PRIVMSG test :Hi!\r\nPRIVMSG test :This is a test!\r\n\
|
||||||
:test!test@test JOIN #test\r\n";
|
:test!test@test JOIN #test\r\n";
|
||||||
|
|
||||||
|
@ -1136,7 +1137,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn handle_message() -> Result<(), failure::Error> {
|
async fn handle_message() -> Result<()> {
|
||||||
let value = ":irc.test.net 376 test :End of /MOTD command.\r\n";
|
let value = ":irc.test.net 376 test :End of /MOTD command.\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1152,7 +1153,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn handle_end_motd_with_nick_password() -> Result<(), failure::Error> {
|
async fn handle_end_motd_with_nick_password() -> Result<()> {
|
||||||
let value = ":irc.test.net 376 test :End of /MOTD command.\r\n";
|
let value = ":irc.test.net 376 test :End of /MOTD command.\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1171,7 +1172,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn handle_end_motd_with_chan_keys() -> Result<(), failure::Error> {
|
async fn handle_end_motd_with_chan_keys() -> Result<()> {
|
||||||
let value = ":irc.test.net 376 test :End of /MOTD command\r\n";
|
let value = ":irc.test.net 376 test :End of /MOTD command\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1194,7 +1195,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn handle_end_motd_with_ghost() -> Result<(), failure::Error> {
|
async fn handle_end_motd_with_ghost() -> Result<()> {
|
||||||
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n\
|
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n\
|
||||||
:irc.test.net 376 test2 :End of /MOTD command.\r\n";
|
:irc.test.net 376 test2 :End of /MOTD command.\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
|
@ -1217,7 +1218,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn handle_end_motd_with_ghost_seq() -> Result<(), failure::Error> {
|
async fn handle_end_motd_with_ghost_seq() -> Result<()> {
|
||||||
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n\
|
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n\
|
||||||
:irc.test.net 376 test2 :End of /MOTD command.\r\n";
|
:irc.test.net 376 test2 :End of /MOTD command.\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
|
@ -1242,7 +1243,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn handle_end_motd_with_umodes() -> Result<(), failure::Error> {
|
async fn handle_end_motd_with_umodes() -> Result<()> {
|
||||||
let value = ":irc.test.net 376 test :End of /MOTD command.\r\n";
|
let value = ":irc.test.net 376 test :End of /MOTD command.\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1261,7 +1262,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn nickname_in_use() -> Result<(), failure::Error> {
|
async fn nickname_in_use() -> Result<()> {
|
||||||
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n";
|
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1274,7 +1275,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn ran_out_of_nicknames() -> Result<(), failure::Error> {
|
async fn ran_out_of_nicknames() -> Result<()> {
|
||||||
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n\
|
let value = ":irc.pdgn.co 433 * test :Nickname is already in use.\r\n\
|
||||||
:irc.pdgn.co 433 * test2 :Nickname is already in use.\r\n";
|
:irc.pdgn.co 433 * test2 :Nickname is already in use.\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
|
@ -1292,7 +1293,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send() -> Result<(), failure::Error> {
|
async fn send() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
assert!(client
|
assert!(client
|
||||||
.send(PRIVMSG(format!("#test"), format!("Hi there!")))
|
.send(PRIVMSG(format!("#test"), format!("Hi there!")))
|
||||||
|
@ -1306,7 +1307,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_no_newline_injection() -> Result<(), failure::Error> {
|
async fn send_no_newline_injection() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
assert!(client
|
assert!(client
|
||||||
.send(PRIVMSG(format!("#test"), format!("Hi there!\r\nJOIN #bad")))
|
.send(PRIVMSG(format!("#test"), format!("Hi there!\r\nJOIN #bad")))
|
||||||
|
@ -1320,7 +1321,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_raw_is_really_raw() -> Result<(), failure::Error> {
|
async fn send_raw_is_really_raw() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
assert!(client
|
assert!(client
|
||||||
.send(Raw("PASS".to_owned(), vec!["password".to_owned()], None))
|
.send(Raw("PASS".to_owned(), vec!["password".to_owned()], None))
|
||||||
|
@ -1338,7 +1339,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "nochanlists"))]
|
#[cfg(not(feature = "nochanlists"))]
|
||||||
async fn channel_tracking_names() -> Result<(), failure::Error> {
|
async fn channel_tracking_names() -> Result<()> {
|
||||||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n";
|
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1355,7 +1356,7 @@ mod test {
|
||||||
/*
|
/*
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "nochanlists"))]
|
#[cfg(not(feature = "nochanlists"))]
|
||||||
async fn channel_tracking_names_part() -> Result<(), failure::Error> {
|
async fn channel_tracking_names_part() -> Result<()> {
|
||||||
use crate::proto::command::Command::PART;
|
use crate::proto::command::Command::PART;
|
||||||
|
|
||||||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n";
|
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n";
|
||||||
|
@ -1373,7 +1374,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "nochanlists"))]
|
#[cfg(not(feature = "nochanlists"))]
|
||||||
async fn user_tracking_names() -> Result<(), failure::Error> {
|
async fn user_tracking_names() -> Result<()> {
|
||||||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n";
|
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1390,7 +1391,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "nochanlists"))]
|
#[cfg(not(feature = "nochanlists"))]
|
||||||
async fn user_tracking_names_join() -> Result<(), failure::Error> {
|
async fn user_tracking_names_join() -> Result<()> {
|
||||||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
|
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
|
||||||
:test2!test@test JOIN #test\r\n";
|
:test2!test@test JOIN #test\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
|
@ -1413,7 +1414,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "nochanlists"))]
|
#[cfg(not(feature = "nochanlists"))]
|
||||||
async fn user_tracking_names_kick() -> Result<(), failure::Error> {
|
async fn user_tracking_names_kick() -> Result<()> {
|
||||||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
|
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
|
||||||
:owner!test@test KICK #test test\r\n";
|
:owner!test@test KICK #test test\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
|
@ -1431,7 +1432,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "nochanlists"))]
|
#[cfg(not(feature = "nochanlists"))]
|
||||||
async fn user_tracking_names_part() -> Result<(), failure::Error> {
|
async fn user_tracking_names_part() -> Result<()> {
|
||||||
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
|
let value = ":irc.test.net 353 test = #test :test ~owner &admin\r\n\
|
||||||
:owner!test@test PART #test\r\n";
|
:owner!test@test PART #test\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
|
@ -1449,7 +1450,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(not(feature = "nochanlists"))]
|
#[cfg(not(feature = "nochanlists"))]
|
||||||
async fn user_tracking_names_mode() -> Result<(), failure::Error> {
|
async fn user_tracking_names_mode() -> Result<()> {
|
||||||
let value = ":irc.test.net 353 test = #test :+test ~owner &admin\r\n\
|
let value = ":irc.test.net 353 test = #test :+test ~owner &admin\r\n\
|
||||||
:test!test@test MODE #test +o test\r\n";
|
:test!test@test MODE #test +o test\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
|
@ -1478,7 +1479,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "nochanlists")]
|
#[cfg(feature = "nochanlists")]
|
||||||
async fn no_user_tracking() -> Result<(), failure::Error> {
|
async fn no_user_tracking() -> Result<()> {
|
||||||
let value = ":irc.test.net 353 test = #test :test ~owner &admin";
|
let value = ":irc.test.net 353 test = #test :test ~owner &admin";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1491,7 +1492,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn handle_single_soh() -> Result<(), failure::Error> {
|
async fn handle_single_soh() -> Result<()> {
|
||||||
let value = ":test!test@test PRIVMSG #test :\u{001}\r\n";
|
let value = ":test!test@test PRIVMSG #test :\u{001}\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1506,7 +1507,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn finger_response() -> Result<(), failure::Error> {
|
async fn finger_response() -> Result<()> {
|
||||||
let value = ":test!test@test PRIVMSG test :\u{001}FINGER\u{001}\r\n";
|
let value = ":test!test@test PRIVMSG test :\u{001}FINGER\u{001}\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1523,7 +1524,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn version_response() -> Result<(), failure::Error> {
|
async fn version_response() -> Result<()> {
|
||||||
let value = ":test!test@test PRIVMSG test :\u{001}VERSION\u{001}\r\n";
|
let value = ":test!test@test PRIVMSG test :\u{001}VERSION\u{001}\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1543,7 +1544,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn source_response() -> Result<(), failure::Error> {
|
async fn source_response() -> Result<()> {
|
||||||
let value = ":test!test@test PRIVMSG test :\u{001}SOURCE\u{001}\r\n";
|
let value = ":test!test@test PRIVMSG test :\u{001}SOURCE\u{001}\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1560,7 +1561,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn ctcp_ping_response() -> Result<(), failure::Error> {
|
async fn ctcp_ping_response() -> Result<()> {
|
||||||
let value = ":test!test@test PRIVMSG test :\u{001}PING test\u{001}\r\n";
|
let value = ":test!test@test PRIVMSG test :\u{001}PING test\u{001}\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1577,7 +1578,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn time_response() -> Result<(), failure::Error> {
|
async fn time_response() -> Result<()> {
|
||||||
let value = ":test!test@test PRIVMSG test :\u{001}TIME\u{001}\r\n";
|
let value = ":test!test@test PRIVMSG test :\u{001}TIME\u{001}\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1593,7 +1594,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn user_info_response() -> Result<(), failure::Error> {
|
async fn user_info_response() -> Result<()> {
|
||||||
let value = ":test!test@test PRIVMSG test :\u{001}USERINFO\u{001}\r\n";
|
let value = ":test!test@test PRIVMSG test :\u{001}USERINFO\u{001}\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1611,7 +1612,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn ctcp_ping_no_timestamp() -> Result<(), failure::Error> {
|
async fn ctcp_ping_no_timestamp() -> Result<()> {
|
||||||
let value = ":test!test@test PRIVMSG test :\u{001}PING\u{001}\r\n";
|
let value = ":test!test@test PRIVMSG test :\u{001}PING\u{001}\r\n";
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
mock_initial_value: Some(value.to_owned()),
|
mock_initial_value: Some(value.to_owned()),
|
||||||
|
@ -1624,7 +1625,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn identify() -> Result<(), failure::Error> {
|
async fn identify() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.identify()?;
|
client.identify()?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1637,7 +1638,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn identify_with_password() -> Result<(), failure::Error> {
|
async fn identify_with_password() -> Result<()> {
|
||||||
let mut client = Client::from_config(Config {
|
let mut client = Client::from_config(Config {
|
||||||
nickname: Some(format!("test")),
|
nickname: Some(format!("test")),
|
||||||
password: Some(format!("password")),
|
password: Some(format!("password")),
|
||||||
|
@ -1655,7 +1656,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_pong() -> Result<(), failure::Error> {
|
async fn send_pong() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_pong("irc.test.net")?;
|
client.send_pong("irc.test.net")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1664,7 +1665,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_join() -> Result<(), failure::Error> {
|
async fn send_join() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_join("#test,#test2,#test3")?;
|
client.send_join("#test,#test2,#test3")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1676,7 +1677,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_part() -> Result<(), failure::Error> {
|
async fn send_part() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_part("#test")?;
|
client.send_part("#test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1685,7 +1686,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_oper() -> Result<(), failure::Error> {
|
async fn send_oper() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_oper("test", "test")?;
|
client.send_oper("test", "test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1694,7 +1695,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_privmsg() -> Result<(), failure::Error> {
|
async fn send_privmsg() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_privmsg("#test", "Hi, everybody!")?;
|
client.send_privmsg("#test", "Hi, everybody!")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1706,7 +1707,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_notice() -> Result<(), failure::Error> {
|
async fn send_notice() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_notice("#test", "Hi, everybody!")?;
|
client.send_notice("#test", "Hi, everybody!")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1718,7 +1719,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_topic_no_topic() -> Result<(), failure::Error> {
|
async fn send_topic_no_topic() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_topic("#test", "")?;
|
client.send_topic("#test", "")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1727,7 +1728,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_topic() -> Result<(), failure::Error> {
|
async fn send_topic() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_topic("#test", "Testing stuff.")?;
|
client.send_topic("#test", "Testing stuff.")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1739,7 +1740,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_kill() -> Result<(), failure::Error> {
|
async fn send_kill() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_kill("test", "Testing kills.")?;
|
client.send_kill("test", "Testing kills.")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1751,7 +1752,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_kick_no_message() -> Result<(), failure::Error> {
|
async fn send_kick_no_message() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_kick("#test", "test", "")?;
|
client.send_kick("#test", "test", "")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1760,7 +1761,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_kick() -> Result<(), failure::Error> {
|
async fn send_kick() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_kick("#test", "test", "Testing kicks.")?;
|
client.send_kick("#test", "test", "Testing kicks.")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1772,7 +1773,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_mode_no_modeparams() -> Result<(), failure::Error> {
|
async fn send_mode_no_modeparams() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_mode("#test", &[Mode::Plus(ChannelMode::InviteOnly, None)])?;
|
client.send_mode("#test", &[Mode::Plus(ChannelMode::InviteOnly, None)])?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1781,7 +1782,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_mode() -> Result<(), failure::Error> {
|
async fn send_mode() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_mode(
|
client.send_mode(
|
||||||
"#test",
|
"#test",
|
||||||
|
@ -1793,7 +1794,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_samode_no_modeparams() -> Result<(), failure::Error> {
|
async fn send_samode_no_modeparams() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_samode("#test", "+i", "")?;
|
client.send_samode("#test", "+i", "")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1802,7 +1803,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_samode() -> Result<(), failure::Error> {
|
async fn send_samode() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_samode("#test", "+o", "test")?;
|
client.send_samode("#test", "+o", "test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1811,7 +1812,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_sanick() -> Result<(), failure::Error> {
|
async fn send_sanick() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_sanick("test", "test2")?;
|
client.send_sanick("test", "test2")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1820,7 +1821,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn send_invite() -> Result<(), failure::Error> {
|
async fn send_invite() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_invite("test", "#test")?;
|
client.send_invite("test", "#test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1830,7 +1831,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn send_ctcp() -> Result<(), failure::Error> {
|
async fn send_ctcp() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_ctcp("test", "MESSAGE")?;
|
client.send_ctcp("test", "MESSAGE")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1843,7 +1844,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn send_action() -> Result<(), failure::Error> {
|
async fn send_action() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_action("test", "tests.")?;
|
client.send_action("test", "tests.")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1856,7 +1857,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn send_finger() -> Result<(), failure::Error> {
|
async fn send_finger() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_finger("test")?;
|
client.send_finger("test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1869,7 +1870,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn send_version() -> Result<(), failure::Error> {
|
async fn send_version() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_version("test")?;
|
client.send_version("test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1882,7 +1883,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn send_source() -> Result<(), failure::Error> {
|
async fn send_source() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_source("test")?;
|
client.send_source("test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1895,7 +1896,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn send_user_info() -> Result<(), failure::Error> {
|
async fn send_user_info() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_user_info("test")?;
|
client.send_user_info("test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1908,7 +1909,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn send_ctcp_ping() -> Result<(), failure::Error> {
|
async fn send_ctcp_ping() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_ctcp_ping("test")?;
|
client.send_ctcp_ping("test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
@ -1921,7 +1922,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[cfg(feature = "ctcp")]
|
#[cfg(feature = "ctcp")]
|
||||||
async fn send_time() -> Result<(), failure::Error> {
|
async fn send_time() -> Result<()> {
|
||||||
let mut client = Client::from_config(test_config()).await?;
|
let mut client = Client::from_config(test_config()).await?;
|
||||||
client.send_time("test")?;
|
client.send_time("test")?;
|
||||||
client.stream()?.collect().await?;
|
client.stream()?.collect().await?;
|
||||||
|
|
102
src/error.rs
102
src/error.rs
|
@ -3,86 +3,77 @@
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
use std::sync::mpsc::RecvError;
|
use std::sync::mpsc::RecvError;
|
||||||
|
|
||||||
use failure;
|
|
||||||
use futures_channel::{
|
use futures_channel::{
|
||||||
mpsc::{SendError, TrySendError},
|
mpsc::{SendError, TrySendError},
|
||||||
oneshot::Canceled,
|
oneshot::Canceled,
|
||||||
};
|
};
|
||||||
use native_tls::Error as TlsError;
|
use thiserror::Error;
|
||||||
#[cfg(feature = "json")]
|
|
||||||
use serde_json::Error as JsonError;
|
|
||||||
#[cfg(feature = "yaml")]
|
|
||||||
use serde_yaml::Error as YamlError;
|
|
||||||
#[cfg(feature = "toml")]
|
|
||||||
use toml::de::Error as TomlReadError;
|
|
||||||
#[cfg(feature = "toml")]
|
|
||||||
use toml::ser::Error as TomlWriteError;
|
|
||||||
|
|
||||||
use crate::proto::error::{MessageParseError, ProtocolError};
|
use crate::proto::error::{MessageParseError, ProtocolError};
|
||||||
|
|
||||||
/// A specialized `Result` type for the `irc` crate.
|
/// A specialized `Result` type for the `irc` crate.
|
||||||
pub type Result<T> = ::std::result::Result<T, Error>;
|
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||||
|
|
||||||
/// The main crate-wide error type.
|
/// The main crate-wide error type.
|
||||||
#[derive(Debug, Fail)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// An internal I/O error.
|
/// An internal I/O error.
|
||||||
#[fail(display = "an io error occurred")]
|
#[error("an io error occurred")]
|
||||||
Io(#[cause] IoError),
|
Io(#[source] IoError),
|
||||||
|
|
||||||
/// An internal TLS error.
|
/// An internal TLS error.
|
||||||
#[fail(display = "a TLS error occurred")]
|
#[error("a TLS error occurred")]
|
||||||
Tls(#[cause] TlsError),
|
Tls(#[source] native_tls::Error),
|
||||||
|
|
||||||
/// An internal synchronous channel closed.
|
/// An internal synchronous channel closed.
|
||||||
#[fail(display = "a sync channel closed")]
|
#[error("a sync channel closed")]
|
||||||
SyncChannelClosed(#[cause] RecvError),
|
SyncChannelClosed(#[source] RecvError),
|
||||||
|
|
||||||
/// An internal asynchronous channel closed.
|
/// An internal asynchronous channel closed.
|
||||||
#[fail(display = "an async channel closed")]
|
#[error("an async channel closed")]
|
||||||
AsyncChannelClosed(#[cause] SendError),
|
AsyncChannelClosed(#[source] SendError),
|
||||||
|
|
||||||
/// An internal oneshot channel closed.
|
/// An internal oneshot channel closed.
|
||||||
#[fail(display = "a oneshot channel closed")]
|
#[error("a oneshot channel closed")]
|
||||||
OneShotCanceled(#[cause] Canceled),
|
OneShotCanceled(#[source] Canceled),
|
||||||
|
|
||||||
/// Error for invalid configurations.
|
/// Error for invalid configurations.
|
||||||
#[fail(display = "invalid config: {}", path)]
|
#[error("invalid config: {}", path)]
|
||||||
InvalidConfig {
|
InvalidConfig {
|
||||||
/// The path to the configuration, or "<none>" if none specified.
|
/// The path to the configuration, or "<none>" if none specified.
|
||||||
path: String,
|
path: String,
|
||||||
/// The detailed configuration error.
|
/// The detailed configuration error.
|
||||||
#[cause]
|
#[source]
|
||||||
cause: ConfigError,
|
cause: ConfigError,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Error for invalid messages.
|
/// Error for invalid messages.
|
||||||
#[fail(display = "invalid message: {}", string)]
|
#[error("invalid message: {}", string)]
|
||||||
InvalidMessage {
|
InvalidMessage {
|
||||||
/// The string that failed to parse.
|
/// The string that failed to parse.
|
||||||
string: String,
|
string: String,
|
||||||
/// The detailed message parsing error.
|
/// The detailed message parsing error.
|
||||||
#[cause]
|
#[source]
|
||||||
cause: MessageParseError,
|
cause: MessageParseError,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Mutex for a logged transport was poisoned making the log inaccessible.
|
/// Mutex for a logged transport was poisoned making the log inaccessible.
|
||||||
#[fail(display = "mutex for a logged transport was poisoned")]
|
#[error("mutex for a logged transport was poisoned")]
|
||||||
PoisonedLog,
|
PoisonedLog,
|
||||||
|
|
||||||
/// Ping timed out due to no response.
|
/// Ping timed out due to no response.
|
||||||
#[fail(display = "connection reset: no ping response")]
|
#[error("connection reset: no ping response")]
|
||||||
PingTimeout,
|
PingTimeout,
|
||||||
|
|
||||||
/// Failed to lookup an unknown codec.
|
/// Failed to lookup an unknown codec.
|
||||||
#[fail(display = "unknown codec: {}", codec)]
|
#[error("unknown codec: {}", codec)]
|
||||||
UnknownCodec {
|
UnknownCodec {
|
||||||
/// The attempted codec.
|
/// The attempted codec.
|
||||||
codec: String,
|
codec: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Failed to encode or decode something with the given codec.
|
/// Failed to encode or decode something with the given codec.
|
||||||
#[fail(display = "codec {} failed: {}", codec, data)]
|
#[error("codec {} failed: {}", codec, data)]
|
||||||
CodecFailed {
|
CodecFailed {
|
||||||
/// The canonical codec name.
|
/// The canonical codec name.
|
||||||
codec: &'static str,
|
codec: &'static str,
|
||||||
|
@ -91,78 +82,69 @@ pub enum Error {
|
||||||
},
|
},
|
||||||
|
|
||||||
/// All specified nicknames were in use or unusable.
|
/// All specified nicknames were in use or unusable.
|
||||||
#[fail(display = "none of the specified nicknames were usable")]
|
#[error("none of the specified nicknames were usable")]
|
||||||
NoUsableNick,
|
NoUsableNick,
|
||||||
|
|
||||||
/// Stream has already been configured.
|
/// Stream has already been configured.
|
||||||
#[fail(display = "stream has already been configured")]
|
#[error("stream has already been configured")]
|
||||||
StreamAlreadyConfigured,
|
StreamAlreadyConfigured,
|
||||||
|
|
||||||
/// This allows you to produce any `failure::Error` within closures used by
|
|
||||||
/// the irc crate. No errors of this kind will ever be produced by the crate
|
|
||||||
/// itself.
|
|
||||||
#[fail(display = "{}", inner)]
|
|
||||||
Custom {
|
|
||||||
/// The actual error that occurred.
|
|
||||||
inner: failure::Error,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Errors that occur with configurations.
|
/// Errors that occur with configurations.
|
||||||
#[derive(Debug, Fail)]
|
#[derive(Debug, Error)]
|
||||||
pub enum ConfigError {
|
pub enum ConfigError {
|
||||||
/// Failed to parse as TOML.
|
/// Failed to parse as TOML.
|
||||||
#[cfg(feature = "toml")]
|
#[cfg(feature = "toml")]
|
||||||
#[fail(display = "invalid toml")]
|
#[error("invalid toml")]
|
||||||
InvalidToml(#[cause] TomlError),
|
InvalidToml(#[source] TomlError),
|
||||||
|
|
||||||
/// Failed to parse as JSON.
|
/// Failed to parse as JSON.
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
#[fail(display = "invalid json")]
|
#[error("invalid json")]
|
||||||
InvalidJson(#[cause] JsonError),
|
InvalidJson(#[source] serde_json::Error),
|
||||||
|
|
||||||
/// Failed to parse as YAML.
|
/// Failed to parse as YAML.
|
||||||
#[cfg(feature = "yaml")]
|
#[cfg(feature = "yaml")]
|
||||||
#[fail(display = "invalid yaml")]
|
#[error("invalid yaml")]
|
||||||
InvalidYaml(#[cause] YamlError),
|
InvalidYaml(#[source] serde_yaml::Error),
|
||||||
|
|
||||||
/// Failed to parse the given format because it was disabled at compile-time.
|
/// Failed to parse the given format because it was disabled at compile-time.
|
||||||
#[fail(display = "config format disabled: {}", format)]
|
#[error("config format disabled: {}", format)]
|
||||||
ConfigFormatDisabled {
|
ConfigFormatDisabled {
|
||||||
/// The disabled file format.
|
/// The disabled file format.
|
||||||
format: &'static str,
|
format: &'static str,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Could not identify the given file format.
|
/// Could not identify the given file format.
|
||||||
#[fail(display = "config format unknown: {}", format)]
|
#[error("config format unknown: {}", format)]
|
||||||
UnknownConfigFormat {
|
UnknownConfigFormat {
|
||||||
/// The unknown file extension.
|
/// The unknown file extension.
|
||||||
format: String,
|
format: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// File was missing an extension to identify file format.
|
/// File was missing an extension to identify file format.
|
||||||
#[fail(display = "missing format extension")]
|
#[error("missing format extension")]
|
||||||
MissingExtension,
|
MissingExtension,
|
||||||
|
|
||||||
/// Configuration does not specify a nickname.
|
/// Configuration does not specify a nickname.
|
||||||
#[fail(display = "nickname not specified")]
|
#[error("nickname not specified")]
|
||||||
NicknameNotSpecified,
|
NicknameNotSpecified,
|
||||||
|
|
||||||
/// Configuration does not specify a server.
|
/// Configuration does not specify a server.
|
||||||
#[fail(display = "server not specified")]
|
#[error("server not specified")]
|
||||||
ServerNotSpecified,
|
ServerNotSpecified,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper that combines toml's serialization and deserialization errors.
|
/// A wrapper that combines toml's serialization and deserialization errors.
|
||||||
#[cfg(feature = "toml")]
|
#[cfg(feature = "toml")]
|
||||||
#[derive(Debug, Fail)]
|
#[derive(Debug, Error)]
|
||||||
pub enum TomlError {
|
pub enum TomlError {
|
||||||
/// A TOML deserialization error.
|
/// A TOML deserialization error.
|
||||||
#[fail(display = "deserialization failed")]
|
#[error("deserialization failed")]
|
||||||
Read(#[cause] TomlReadError),
|
Read(#[source] toml::de::Error),
|
||||||
/// A TOML serialization error.
|
/// A TOML serialization error.
|
||||||
#[fail(display = "serialization failed")]
|
#[error("serialization failed")]
|
||||||
Write(#[cause] TomlWriteError),
|
Write(#[source] toml::ser::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<ProtocolError> for Error {
|
impl From<ProtocolError> for Error {
|
||||||
|
@ -182,8 +164,8 @@ impl From<IoError> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TlsError> for Error {
|
impl From<native_tls::Error> for Error {
|
||||||
fn from(e: TlsError) -> Error {
|
fn from(e: native_tls::Error) -> Error {
|
||||||
Error::Tls(e)
|
Error::Tls(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,6 @@
|
||||||
|
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
#[macro_use]
|
|
||||||
extern crate failure;
|
|
||||||
|
|
||||||
pub extern crate irc_proto as proto;
|
pub extern crate irc_proto as proto;
|
||||||
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
|
|
Loading…
Add table
Reference in a new issue