diff options
| author | Max Audron <audron@cocaine.farm> | 2021-01-21 14:57:22 +0100 |
|---|---|---|
| committer | Max Audron <audron@cocaine.farm> | 2021-01-21 14:57:22 +0100 |
| commit | 2405fa686a53f1d895807b1658c38a5e7e7693a0 (patch) | |
| tree | d40a9430a421d3ca4a28ce2ad98b51e3d731f265 | |
| parent | Merge branch 'client' (diff) | |
reorganize tests and add quassel features
Diffstat (limited to '')
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Cargo.toml | 26 | ||||
| -rw-r--r-- | src/frame/mod.rs | 4 | ||||
| -rw-r--r-- | src/frame/tests.rs | 209 | ||||
| -rw-r--r-- | src/lib.rs | 4 | ||||
| -rw-r--r-- | src/message/handshake/clientinitack.rs | 4 | ||||
| -rw-r--r-- | src/message/handshake/clientloginack.rs | 2 | ||||
| -rw-r--r-- | src/message/handshake/mod.rs | 2 | ||||
| -rw-r--r-- | src/message/handshake/types.rs | 49 | ||||
| -rw-r--r-- | src/primitive/bufferinfo.rs | 37 | ||||
| -rw-r--r-- | src/primitive/datetime.rs | 34 | ||||
| -rw-r--r-- | src/primitive/message.rs | 80 | ||||
| -rw-r--r-- | src/primitive/signedint.rs | 5 | ||||
| -rw-r--r-- | src/primitive/string.rs | 56 | ||||
| -rw-r--r-- | src/primitive/stringlist.rs | 26 | ||||
| -rw-r--r-- | src/primitive/variant.rs | 326 | ||||
| -rw-r--r-- | src/primitive/variantlist.rs | 2 | ||||
| -rw-r--r-- | src/primitive/variantmap.rs | 2 | ||||
| -rw-r--r-- | src/tests/base_types.rs | 84 | ||||
| -rw-r--r-- | src/tests/datetime.rs | 28 | ||||
| -rw-r--r-- | src/tests/frame.rs | 240 | ||||
| -rw-r--r-- | src/tests/handshake_types.rs | 44 | ||||
| -rw-r--r-- | src/tests/mod.rs | 17 | ||||
| -rw-r--r-- | src/tests/variant_types.rs | 100 | ||||
| -rw-r--r-- | src/util.rs | 19 |
25 files changed, 850 insertions, 551 deletions
@@ -2,3 +2,4 @@ Cargo.lock /target **/*.rs.bk examples/testserver +lcov.info @@ -15,24 +15,24 @@ autobins = true log = "0.4" byteorder = "1.3.2" failure = "0.1" -either = "1.5" time = "0.2" -async-trait = "0.1" -default-macro = { path = "../default-macro" } +num-traits = "0.2" +num-derive = "0.3" -bytes = { version = "1.0" } +libquassel-derive = { path = "./derive" } + + +bytes = { version = "1.0", optional = true } flate2 = { version = "1.0", features = ["tokio"], optional = true } tokio = { version = "1.0", features = [], optional = true } tokio-util = { version = "0.6", features = ["codec"], optional = true } -futures-util = { version = "0.3", features = ["std"], optional = true } -futures = { version = "0.3", optional = true } [features] -framing = ["tokio", "tokio-util", "flate2"] +framing = ["tokio", "tokio-util", "flate2", "bytes"] # Enable all the quassel features -all-quassel-features = ["long-message-id", "long-time", "rich-messages", "sender-prefixes"] +all-quassel-features = ["long-message-id", "long-time", "rich-messages", "sender-prefixes", "authenticators"] # Serialize message IDs as i64 long-message-id = [] @@ -42,6 +42,8 @@ long-time = [] rich-messages = [] # Show prefixes for senders in backlog sender-prefixes = [] +# Support for exchangeable auth backends +authenticators = [] default = [] @@ -53,8 +55,12 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dev-dependencies] -# futures = { version = "0.3" } +futures = { version = "0.3" } # flate2 = { version = "1.0", features = ["tokio"] } # tokio = { version = "0.3", features = ["full"] } # tokio-util = { version = "0.5", features = ["codec"] } -# tokio-test = { version = "0.3" } +tokio-test = { version = "0.4" } +pretty_assertions = "0.6" + +[workspace] +members = ["derive", "examples/quasselproxy"] diff --git a/src/frame/mod.rs b/src/frame/mod.rs index cbeddb0..34a8514 100644 --- a/src/frame/mod.rs +++ b/src/frame/mod.rs @@ -15,6 +15,9 @@ use flate2::Decompress; use flate2::FlushCompress; use flate2::FlushDecompress; +#[cfg(test)] +mod tests; + /// Builder for the QuasselCodec #[derive(Debug, Clone, Copy)] pub struct Builder { @@ -28,6 +31,7 @@ pub struct Builder { } // An error when the number of bytes read is more than max frame length. +#[derive(PartialEq)] pub struct QuasselCodecError { _priv: (), } diff --git a/src/frame/tests.rs b/src/frame/tests.rs new file mode 100644 index 0000000..5029ea3 --- /dev/null +++ b/src/frame/tests.rs @@ -0,0 +1,209 @@ +use tokio_test::assert_ready; +use tokio_test::task; +use tokio_util::codec::*; + +use futures::{pin_mut, Stream}; + +use crate::frame::*; + +macro_rules! assert_next_eq { + ($io:ident, $expect:expr) => {{ + task::spawn(()).enter(|cx, _| { + let res = assert_ready!($io.as_mut().poll_next(cx)); + match res { + Some(Ok(v)) => assert_eq!(v, $expect.as_ref()), + Some(Err(e)) => panic!("error = {:?}", e), + None => panic!("none"), + } + }); + }}; +} + +// macro_rules! assert_next_pending { +// ($io:ident) => {{ +// task::spawn(()).enter(|cx, _| match $io.as_mut().poll_next(cx) { +// Ready(Some(Ok(v))) => panic!("value = {:?}", v), +// Ready(Some(Err(e))) => panic!("error = {:?}", e), +// Ready(None) => panic!("done"), +// Pending => {} +// }); +// }}; +// } + +// macro_rules! assert_next_err { +// ($io:ident) => {{ +// task::spawn(()).enter(|cx, _| match $io.as_mut().poll_next(cx) { +// Ready(Some(Ok(v))) => panic!("value = {:?}", v), +// Ready(Some(Err(_))) => {} +// Ready(None) => panic!("done"), +// Pending => panic!("pending"), +// }); +// }}; +// } + +macro_rules! assert_done { + ($io:ident) => {{ + task::spawn(()).enter(|cx, _| { + let res = assert_ready!($io.as_mut().poll_next(cx)); + match res { + Some(Ok(v)) => panic!("value = {:?}", v), + Some(Err(e)) => panic!("error = {:?}", e), + None => {} + } + }); + }}; +} + +// ====================== +// ===== Test ===== +// ====================== + +use tokio_test::io::Builder; + +#[test] +fn quasselcodec_set_options() { + use flate2::Compression; + + let mut codec = QuasselCodec::default(); + + assert_eq!(codec.max_frame_length(), 64 * 1024 * 1024); + assert_eq!(codec.compression(), false); + assert_eq!(codec.compression_level(), Compression::default()); + + codec.set_max_frame_length(42); + codec.set_compression(true); + codec.set_compression_level(Compression::best()); + + assert_eq!(codec.max_frame_length(), 42); + assert_eq!(codec.compression(), true); + assert_eq!(codec.compression_level(), Compression::best()); +} + +#[test] +fn quasselcodec_write_oversized() { + use futures::sink::SinkExt; + + let mut io = Framed::new( + Builder::new() + .write_error(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + QuasselCodecError { _priv: () }, + )) + .build(), + QuasselCodec::builder().max_frame_length(5).new_codec(), + ); + + tokio_test::block_on(async move { + let res = io.send(b"abcdefghi".to_vec()).await.map_err(|e| e.kind()); + let want = Err(std::io::ErrorKind::InvalidInput); + + assert_eq!(want, res); + }); +} + +#[test] +fn quasselcodec_read_oversized() { + use futures::stream::StreamExt; + + let mut io = FramedRead::new( + Builder::new().read(b"\x00\x00\x00\x09abcdefghi").build(), + QuasselCodec::builder().max_frame_length(5).new_codec(), + ); + + tokio_test::block_on(async move { + let res = io.next().await.unwrap().map_err(|e| e.kind()); + let want = Err(std::io::ErrorKind::InvalidData); + + assert_eq!(want, res); + }); +} + +#[test] +pub fn read_single_frame() { + let io = FramedRead::new( + Builder::new().read(b"\x00\x00\x00\x09abcdefghi").build(), + QuasselCodec::new(), + ); + pin_mut!(io); + + assert_next_eq!(io, b"abcdefghi"); + assert_done!(io); +} + +#[test] +pub fn read_multi_frame() { + let mut d: Vec<u8> = vec![]; + d.extend_from_slice(b"\x00\x00\x00\x09abcdefghi"); + d.extend_from_slice(b"\x00\x00\x00\x03123"); + d.extend_from_slice(b"\x00\x00\x00\x0bhello world"); + + let io = FramedRead::new(Builder::new().read(&d).build(), QuasselCodec::new()); + pin_mut!(io); + + assert_next_eq!(io, b"abcdefghi"); + assert_next_eq!(io, b"123"); + assert_next_eq!(io, b"hello world"); + assert_done!(io); +} + +#[test] +pub fn read_single_frame_compressed() { + let io = FramedRead::new( + Builder::new().read(b"\x78\x9c\x63\x60\x60\xe0\x4c\x4c\x4a\x4e\x49\x4d\x4b\xcf\xc8\x04\x00\x11\xec\x03\x97").build(), + QuasselCodec::builder().compression(true).new_codec(), + ); + pin_mut!(io); + + assert_next_eq!(io, b"abcdefghi"); + assert_done!(io); +} + +#[test] +fn write_single_frame() { + use futures::sink::SinkExt; + + let mut io = Framed::new( + Builder::new().write(b"\x00\x00\x00\x09abcdefghi").build(), + QuasselCodec::new(), + ); + + tokio_test::block_on(async move { + io.send(b"abcdefghi".to_vec()).await.unwrap(); + }); +} + +#[test] +fn write_multi_frame() { + use futures::sink::SinkExt; + + let mut io = Framed::new( + Builder::new() + .write(b"\x00\x00\x00\x09abcdefghi") + .write(b"\x00\x00\x00\x03123") + .write(b"\x00\x00\x00\x0bhello world") + .build(), + QuasselCodec::new(), + ); + + tokio_test::block_on(async move { + io.send(b"abcdefghi".to_vec()).await.unwrap(); + io.send(b"123".to_vec()).await.unwrap(); + io.send(b"hello world".to_vec()).await.unwrap(); + }); +} + +#[test] +fn write_single_frame_compressed() { + use futures::sink::SinkExt; + + let mut io = Framed::new( + Builder::new() + .write(&[120, 156, 98, 96, 96, 224, 76, 76, 74, 78, 73, 77, 75]) + .build(), + QuasselCodec::builder().compression(true).new_codec(), + ); + + tokio_test::block_on(async move { + io.send(b"abcdefghi".to_vec()).await.unwrap(); + }); +} @@ -1,3 +1,4 @@ +#![feature(array_value_iter)] #![feature(external_doc)] #![feature(doc_cfg)] #![doc(include = "../README.md")] @@ -5,9 +6,6 @@ #[macro_use] mod util; -#[cfg(test)] -pub mod tests; - #[macro_use] extern crate failure; diff --git a/src/message/handshake/clientinitack.rs b/src/message/handshake/clientinitack.rs index f881113..a259f9c 100644 --- a/src/message/handshake/clientinitack.rs +++ b/src/message/handshake/clientinitack.rs @@ -13,6 +13,8 @@ pub struct ClientInitAck { /// List of VariantMaps of info on available backends pub storage_backends: VariantList, /// List of VariantMaps of info on available authenticators + #[cfg(feature = "authenticators")] + #[cfg_attr(docsrs, doc(cfg(feature = "authenticators")))] pub authenticators: VariantList, /// List of supported extended features pub feature_list: Vec<String>, @@ -34,6 +36,7 @@ impl HandshakeSerialize for ClientInitAck { "StorageBackends".to_string(), Variant::VariantList(self.storage_backends.clone()), ); + #[cfg(feature = "authenticators")] values.insert( "Authenticators".to_string(), Variant::VariantList(self.authenticators.clone()), @@ -56,6 +59,7 @@ impl From<VariantMap> for ClientInitAck { input.get("StorageBackends").unwrap(), Variant::VariantList ), + #[cfg(feature = "authenticators")] authenticators: match_variant!( input.get("Authenticators").unwrap(), Variant::VariantList diff --git a/src/message/handshake/clientloginack.rs b/src/message/handshake/clientloginack.rs index e385a81..72dd6ac 100644 --- a/src/message/handshake/clientloginack.rs +++ b/src/message/handshake/clientloginack.rs @@ -24,7 +24,7 @@ impl HandshakeDeserialize for ClientLoginAck { fn parse(b: &[u8]) -> Result<(usize, Self), Error> { let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?; - let msgtype = match_variant!(&values["MsgType"], Variant::StringUTF8); + let msgtype = match_variant!(&values["MsgType"], Variant::ByteArray); if msgtype == "ClientLogin" { return Ok((len, Self {})); diff --git a/src/message/handshake/mod.rs b/src/message/handshake/mod.rs index 9885012..c180c5e 100644 --- a/src/message/handshake/mod.rs +++ b/src/message/handshake/mod.rs @@ -5,6 +5,7 @@ mod clientlogin; mod clientloginack; mod clientloginreject; mod connack; +mod features; mod init; mod protocol; mod sessioninit; @@ -17,6 +18,7 @@ pub use clientlogin::*; pub use clientloginack::*; pub use clientloginreject::*; pub use connack::*; +pub use features::*; pub use init::*; pub use protocol::*; pub use sessioninit::*; diff --git a/src/message/handshake/types.rs b/src/message/handshake/types.rs index 04e1dd0..24d847b 100644 --- a/src/message/handshake/types.rs +++ b/src/message/handshake/types.rs @@ -6,9 +6,9 @@ use failure::Error; use crate::error::ProtocolError; use crate::primitive::Variant; +use crate::util; use crate::Deserialize; use crate::Serialize; -use crate::util; use crate::primitive::VariantMap; use crate::{HandshakeDeserialize, HandshakeSerialize}; @@ -46,7 +46,7 @@ impl HandshakeDeserialize for VariantMap { match name { Variant::String(x) => map.insert(x, value), - Variant::StringUTF8(x) => map.insert(x, value), + Variant::ByteArray(x) => map.insert(x, value), _ => bail!(ProtocolError::WrongVariant), }; } @@ -54,3 +54,48 @@ impl HandshakeDeserialize for VariantMap { return Ok((pos, map)); } } + +#[test] +pub fn serialize_variantmap() { + let mut test_variantmap = VariantMap::new(); + test_variantmap.insert("Configured".to_string(), Variant::bool(true)); + let bytes = [ + 0, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, + 117, 0, 114, 0, 101, 0, 100, 0, 0, 0, 1, 0, 1, + ] + .to_vec(); + assert_eq!( + HandshakeSerialize::serialize(&test_variantmap).unwrap(), + bytes + ); +} + +#[test] +pub fn deserialize_variantmap() { + let test_bytes: &[u8] = &[ + 0, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, + 117, 0, 114, 0, 101, 0, 100, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, + ]; + let mut test_variantmap = VariantMap::new(); + test_variantmap.insert("Configured".to_string(), Variant::bool(true)); + + let (len, res): (usize, VariantMap) = HandshakeDeserialize::parse(test_bytes).unwrap(); + + assert_eq!(len, 39); + assert_eq!(res, test_variantmap); +} + +#[test] +pub fn deserialize_variantmap_utf8() { + let test_bytes: &[u8] = &[ + 0, 0, 0, 2, 0, 0, 0, 12, 0, 0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, + 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, + ]; + let mut test_variantmap = VariantMap::new(); + test_variantmap.insert("Configured".to_string(), Variant::bool(true)); + + let (len, res): (usize, VariantMap) = HandshakeDeserialize::parse(test_bytes).unwrap(); + + assert_eq!(len, 29); + assert_eq!(res, test_variantmap); +} diff --git a/src/primitive/bufferinfo.rs b/src/primitive/bufferinfo.rs index 9cbaa2d..1c4e206 100644 --- a/src/primitive/bufferinfo.rs +++ b/src/primitive/bufferinfo.rs @@ -5,8 +5,6 @@ use failure::Error; use crate::{Deserialize, DeserializeUTF8}; use crate::{Serialize, SerializeUTF8}; -extern crate bytes; - /// The BufferInfo struct represents a BufferInfo as received in IRC /// /// BufferInfo is, like all other struct based types, serialized sequentially. @@ -79,3 +77,38 @@ impl From<i16> for BufferType { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn bufferinfo_serialize() { + let buffer = BufferInfo { + id: 1, + network_id: 1, + buffer_type: BufferType::Channel, + name: "#test".to_string(), + }; + + assert_eq!( + buffer.serialize().unwrap(), + [0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116] + ) + } + + #[test] + fn bufferinfo_deserialize() { + let buffer = BufferInfo { + id: 1, + network_id: 1, + buffer_type: BufferType::Channel, + name: "#test".to_string(), + }; + let bytes = vec![ + 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116, + ]; + + assert_eq!(BufferInfo::parse(&bytes).unwrap(), (23, buffer)) + } +} diff --git a/src/primitive/datetime.rs b/src/primitive/datetime.rs index fadd6a5..e4c4c83 100644 --- a/src/primitive/datetime.rs +++ b/src/primitive/datetime.rs @@ -166,3 +166,37 @@ impl Deserialize for Time { Ok((4, time)) } } + +#[test] +pub fn datetime_serialize() { + let datetime = DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap(); + + let sers = datetime.serialize().unwrap(); + let bytes = vec![0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32]; + + assert_eq!(sers, bytes) +} + +#[test] +pub fn datetime_deserialize() { + let datetime = DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap(); + + let bytes = vec![0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32]; + let (_, res): (usize, DateTime) = Deserialize::parse(&bytes).unwrap(); + + assert_eq!(res, datetime) +} + +#[test] +pub fn datetime_deserialize_epoch() { + let datetime = DateTime::unix_epoch(); + + let bytes = vec![0, 37, 133, 19, 0xff, 0xff, 0xff, 0xff, 3, 0, 0, 28, 32]; + let (_, res): (usize, DateTime) = Deserialize::parse(&bytes).unwrap(); + + let bytes = vec![0xff, 0xff, 0xff, 0xff, 2, 202, 28, 128, 3, 0, 0, 28, 32]; + let (_, res2): (usize, DateTime) = Deserialize::parse(&bytes).unwrap(); + + assert_eq!(res, datetime); + assert_eq!(res2, datetime) +} diff --git a/src/primitive/message.rs b/src/primitive/message.rs index 56bae22..04c427e 100644 --- a/src/primitive/message.rs +++ b/src/primitive/message.rs @@ -7,8 +7,6 @@ use crate::{Serialize, SerializeUTF8}; use crate::primitive::BufferInfo; -extern crate bytes; - /// The Message struct represents a Message as received in IRC /// /// Messages are, like all other struct based types, serialized sequentially. @@ -22,7 +20,9 @@ pub struct Message { #[cfg(not(feature = "long-message-id"))] #[cfg_attr(docsrs, doc(cfg(not(feature = "long-message-id"))))] pub msg_id: i32, - /// The timestamp of the message in UNIX time (32-bit, seconds, 64-bit if long-time feature enabled) + /// The timestamp of the message in UNIX time. + /// If long-time is disabled this is an i32 representing the seconds since EPOCH. + /// If long-time is enabled this is an i64 representing the miliseconds since EPOCH. #[cfg(feature = "long-time")] #[cfg_attr(docsrs, doc(cfg(feature = "long-time")))] pub timestamp: i64, @@ -220,3 +220,77 @@ impl From<i32> for MessageType { } } } + +#[cfg(test)] +#[cfg(feature = "all-quassel-features")] +mod tests { + use super::*; + use crate::primitive::{BufferInfo, BufferType}; + + #[test] + fn message_serialize() { + let message = Message { + msg_id: 1, + timestamp: 1609846597, + msg_type: MessageType::Plain, + flags: 0, + buffer: BufferInfo { + id: 1, + network_id: 1, + buffer_type: BufferType::Channel, + name: "#test".to_string(), + }, + sender: "test".to_string(), + content: "this is a test message".to_string(), + sender_prefixes: "blabla".to_string(), + real_name: "test user".to_string(), + avatar_url: "https://jfkalsdkjfj.com/kjkj".to_string(), + }; + + assert_eq!( + message.serialize().unwrap(), + [ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 95, 244, 79, 69, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116, 0, 0, 0, 4, 116, + 101, 115, 116, 0, 0, 0, 6, 98, 108, 97, 98, 108, 97, 0, 0, 0, 9, 116, 101, 115, + 116, 32, 117, 115, 101, 114, 0, 0, 0, 28, 104, 116, 116, 112, 115, 58, 47, 47, 106, + 102, 107, 97, 108, 115, 100, 107, 106, 102, 106, 46, 99, 111, 109, 47, 107, 106, + 107, 106, 0, 0, 0, 22, 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 115, + 116, 32, 109, 101, 115, 115, 97, 103, 101 + ] + ) + } + + #[test] + fn message_deserialize() { + let message = Message { + msg_id: 1, + timestamp: 1609846597, + msg_type: MessageType::Plain, + flags: 0, + buffer: BufferInfo { + id: 1, + network_id: 1, + buffer_type: BufferType::Channel, + name: "#test".to_string(), + }, + sender: "test".to_string(), + content: "this is a test message".to_string(), + sender_prefixes: "blabla".to_string(), + real_name: "test user".to_string(), + avatar_url: "https://jfkalsdkjfj.com/kjkj".to_string(), + }; + + let bytes = vec![ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 95, 244, 79, 69, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116, 0, 0, 0, 4, 116, 101, 115, + 116, 0, 0, 0, 6, 98, 108, 97, 98, 108, 97, 0, 0, 0, 9, 116, 101, 115, 116, 32, 117, + 115, 101, 114, 0, 0, 0, 28, 104, 116, 116, 112, 115, 58, 47, 47, 106, 102, 107, 97, + 108, 115, 100, 107, 106, 102, 106, 46, 99, 111, 109, 47, 107, 106, 107, 106, 0, 0, 0, + 22, 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 115, 116, 32, 109, 101, + 115, 115, 97, 103, 101, + ]; + + assert_eq!(Message::parse(&bytes).unwrap(), (133, message)) + } +} diff --git a/src/primitive/signedint.rs b/src/primitive/signedint.rs index 4c21a69..a1254fb 100644 --- a/src/primitive/signedint.rs +++ b/src/primitive/signedint.rs @@ -1,8 +1,6 @@ -extern crate byteorder; use byteorder::{BigEndian, ReadBytesExt}; use std::io::Cursor; -use std::convert::TryInto; use std::result::Result; use std::vec::Vec; @@ -57,6 +55,7 @@ impl Serialize for i8 { impl Deserialize for i8 { fn parse(b: &[u8]) -> Result<(usize, Self), Error> { - return Ok((1, b[0].try_into()?)); + let mut rdr = Cursor::new(&b[0..1]); + return Ok((1, rdr.read_i8()?)); } } diff --git a/src/primitive/string.rs b/src/primitive/string.rs index dcd4f7c..590c529 100644 --- a/src/primitive/string.rs +++ b/src/primitive/string.rs @@ -50,6 +50,7 @@ impl Deserialize for String { // length as usize let ulen = len as usize; + trace!("parsed bytes: {:x?}", &b[0..ulen]); let mut pos: usize = 4; let mut chars: Vec<u16> = Vec::new(); loop { @@ -91,7 +92,62 @@ impl DeserializeUTF8 for String { } trace!("parsed string after trunc: {}", res); + trace!("parsed bytes: {:x?}", &b[0..ulen]); return Ok((ulen + 4, res)); } } + +#[test] +pub fn string_serialize() { + let test_string: String = String::from("Configured"); + + assert_eq!( + test_string.serialize().unwrap(), + [ + 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, + 100 + ] + ); +} + +#[test] +pub fn string_serialize_utf8() { + let test_string: String = String::from("Configured"); + + assert_eq!( + test_string.serialize_utf8().unwrap(), + [0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100] + ); +} + +#[test] +pub fn string_deserialize() { + let test_bytes: &[u8] = &[ + 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, + 0, 0, 0, 1, + ]; + let (len, res) = String::parse(test_bytes).unwrap(); + assert_eq!(res, "Configured"); + assert_eq!(len, 24); +} + +#[test] +pub fn string_deserialize_utf8() { + let test_bytes: &[u8] = &[ + 0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0, 0, 0, 1, + ]; + let (len, res) = String::parse_utf8(test_bytes).unwrap(); + assert_eq!(len, 14); + assert_eq!(res, "Configured"); +} + +#[test] +pub fn string_deserialize_utf8_null_terminated() { + let test_bytes: &[u8] = &[ + 0, 0, 0, 11, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0, 0, 0, 0, 1, + ]; + let (len, res) = String::parse_utf8(test_bytes).unwrap(); + assert_eq!(len, 15); + assert_eq!(res, "Configured"); +} diff --git a/src/primitive/stringlist.rs b/src/primitive/stringlist.rs index e5d1a44..df6d281 100644 --- a/src/primitive/stringlist.rs +++ b/src/primitive/stringlist.rs @@ -47,3 +47,29 @@ impl Deserialize for StringList { return Ok((pos, res)); } } + +#[test] +pub fn string_list_serialize() { + let mut test_list = StringList::new(); + test_list.push("Configured".to_string()); + assert_eq!( + test_list.serialize().unwrap(), + [ + 0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, + 0, 101, 0, 100 + ] + ) +} + +#[test] +pub fn string_list_deserialize() { + let test_bytes: &[u8] = &[ + 0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, + 101, 0, 100, 0, 0, 0, 1, + ]; + let mut test_list = StringList::new(); + test_list.push("Configured".to_string()); + let (len, res) = StringList::parse(test_bytes).unwrap(); + assert_eq!(len, 28); + assert_eq!(test_list, res); +} diff --git a/src/primitive/variant.rs b/src/primitive/variant.rs index be2bebe..e9e032e 100644 --- a/src/primitive/variant.rs +++ b/src/primitive/variant.rs @@ -10,8 +10,6 @@ use crate::primitive::StringList; use crate::{Deserialize, DeserializeUTF8}; use crate::{Serialize, SerializeUTF8}; -extern crate bytes; - use crate::primitive::{BufferInfo, Date, DateTime, Message, Time, VariantList, VariantMap}; /// Variant represents the possible types we can receive @@ -21,7 +19,7 @@ use crate::primitive::{BufferInfo, Date, DateTime, Message, Time, VariantList, V /// BufferInfo and Message are UserTypes /// but we represent them as a native Type here. /// -/// StringUTF8 is de-/serialized as a C ByteArray. +/// ByteArray is de-/serialized as a C ByteArray. #[allow(non_camel_case_types, dead_code)] #[derive(Clone, Debug, std::cmp::PartialEq)] pub enum Variant { @@ -35,7 +33,6 @@ pub enum Variant { VariantMap(VariantMap), VariantList(VariantList), String(String), - StringUTF8(String), ByteArray(String), StringList(StringList), bool(bool), @@ -73,11 +70,6 @@ impl Serialize for Variant { res.extend(unknown.to_be_bytes().iter()); res.extend(v.serialize()?.iter()); } - Variant::StringUTF8(v) => { - res.extend(primitive::QBYTEARRAY.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize_utf8()?.iter()); - } Variant::ByteArray(v) => { res.extend(primitive::QBYTEARRAY.to_be_bytes().iter()); res.extend(unknown.to_be_bytes().iter()); @@ -199,7 +191,7 @@ impl Deserialize for Variant { primitive::QBYTEARRAY => { trace!(target: "primitive::Variant", "Parsing Variant: ByteArray"); let (vlen, value) = String::parse_utf8(&b[len..])?; - return Ok((len + vlen, Variant::StringUTF8(value.clone()))); + return Ok((len + vlen, Variant::ByteArray(value.clone()))); } primitive::QSTRINGLIST => { trace!(target: "primitive::Variant", "Parsing Variant: StringList"); @@ -320,3 +312,317 @@ impl Deserialize for Variant { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn signed_serialize() { + let i_64 = Variant::i64(847291274197592); + let i_32 = Variant::i32(897911521); + let i_16 = Variant::i16(8179); + let i_8 = Variant::i8(78); + + let i_n_64 = Variant::i64(-847291274197592); + let i_n_32 = Variant::i32(-897911521); + let i_n_16 = Variant::i16(-8179); + let i_n_8 = Variant::i8(-78); + + assert_eq!( + i_64.serialize().unwrap(), + [0, 0, 0, 129, 0, 0, 3, 2, 155, 95, 107, 122, 88] + ); + assert_eq!(i_32.serialize().unwrap(), [0, 0, 0, 2, 0, 53, 133, 10, 225]); + assert_eq!(i_16.serialize().unwrap(), [0, 0, 0, 130, 0, 31, 243]); + assert_eq!(i_8.serialize().unwrap(), [0, 0, 0, 131, 0, 78]); + + assert_eq!( + i_n_64.serialize().unwrap(), + [0, 0, 0, 129, 0, 255, 252, 253, 100, 160, 148, 133, 168] + ); + assert_eq!( + i_n_32.serialize().unwrap(), + [0, 0, 0, 2, 0, 202, 122, 245, 31] + ); + assert_eq!(i_n_16.serialize().unwrap(), [0, 0, 0, 130, 0, 224, 13]); + assert_eq!(i_n_8.serialize().unwrap(), [0, 0, 0, 131, 0, 178]); + } + + #[test] + fn unsigned_serialize() { + let u_64 = Variant::u64(847291274197592); + let u_32 = Variant::u32(897911521); + let u_16 = Variant::u16(8179); + let u_8 = Variant::u8(78); + + assert_eq!( + u_64.serialize().unwrap(), + [0, 0, 0, 132, 0, 0, 3, 2, 155, 95, 107, 122, 88] + ); + assert_eq!(u_32.serialize().unwrap(), [0, 0, 0, 3, 0, 53, 133, 10, 225]); + assert_eq!(u_16.serialize().unwrap(), [0, 0, 0, 133, 0, 31, 243]); + assert_eq!(u_8.serialize().unwrap(), [0, 0, 0, 134, 0, 78]); + } + + #[test] + fn variant_signed_deserialize() { + let i_64 = Variant::i64(847291274197592); + let i_32 = Variant::i32(897911521); + let i_16 = Variant::i16(8179); + let i_8 = Variant::i8(78); + + let i_n_64 = Variant::i64(-847291274197592); + let i_n_32 = Variant::i32(-897911521); + let i_n_16 = Variant::i16(-8179); + let i_n_8 = Variant::i8(-78); + + let (_, v_i_64) = + Variant::parse(&[0, 0, 0, 129, 0, 0, 3, 2, 155, 95, 107, 122, 88]).unwrap(); + let (_, v_i_32) = Variant::parse(&[0, 0, 0, 2, 0, 53, 133, 10, 225]).unwrap(); + let (_, v_i_16) = Variant::parse(&[0, 0, 0, 130, 0, 31, 243]).unwrap(); + let (_, v_i_8) = Variant::parse(&[0, 0, 0, 131, 0, 78]).unwrap(); + + let (_, v_i_n_64) = + Variant::parse(&[0, 0, 0, 129, 0, 255, 252, 253, 100, 160, 148, 133, 168]).unwrap(); + let (_, v_i_n_32) = Variant::parse(&[0, 0, 0, 2, 0, 202, 122, 245, 31]).unwrap(); + let (_, v_i_n_16) = Variant::parse(&[0, 0, 0, 130, 0, 224, 13]).unwrap(); + let (_, v_i_n_8) = Variant::parse(&[0, 0, 0, 131, 0, 178]).unwrap(); + + assert_eq!(i_64, v_i_64); + assert_eq!(i_32, v_i_32); + assert_eq!(i_16, v_i_16); + assert_eq!(i_8, v_i_8); + + assert_eq!(i_n_64, v_i_n_64); + assert_eq!(i_n_32, v_i_n_32); + assert_eq!(i_n_16, v_i_n_16); + assert_eq!(i_n_8, v_i_n_8); + } + + #[test] + fn unsigned_deserialize() { + let u_64 = Variant::u64(847291274197592); + let u_32 = Variant::u32(897911521); + let u_16 = Variant::u16(8179); + let u_8 = Variant::u8(78); + + let (_, v_u_64) = + Variant::parse(&[0, 0, 0, 132, 0, 0, 3, 2, 155, 95, 107, 122, 88]).unwrap(); + let (_, v_u_32) = Variant::parse(&[0, 0, 0, 3, 0, 53, 133, 10, 225]).unwrap(); + let (_, v_u_16) = Variant::parse(&[0, 0, 0, 133, 0, 31, 243]).unwrap(); + let (_, v_u_8) = Variant::parse(&[0, 0, 0, 134, 0, 78]).unwrap(); + + assert_eq!(u_64, v_u_64); + assert_eq!(u_32, v_u_32); + assert_eq!(u_16, v_u_16); + assert_eq!(u_8, v_u_8); + } + + #[test] + pub fn bool_serialize() { + let test_variant_true = Variant::bool(true); + let test_variant_false = Variant::bool(false); + assert_eq!(test_variant_true.serialize().unwrap(), [0, 0, 0, 1, 0, 1]); + assert_eq!(test_variant_false.serialize().unwrap(), [0, 0, 0, 1, 0, 0]); + } + + #[test] + pub fn bool_deserialize() { + let test_bytes: &[u8] = &[0, 0, 0, 1, 0, 1, 0, 0, 0, 1]; + let (len, res) = Variant::parse(test_bytes).unwrap(); + assert_eq!(len, 6); + assert_eq!(res, Variant::bool(true)); + } + + #[test] + pub fn variantlist_serialize() { + let mut test_variantlist = VariantList::new(); + test_variantlist.push(Variant::bool(true)); + assert_eq!( + test_variantlist.serialize().unwrap(), + [0, 0, 0, 1, 0, 0, 0, 1, 0, 1] + ); + } + + #[test] + pub fn variantlist_deserialize() { + let test_bytes: &[u8] = &[0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1]; + let (len, res) = VariantList::parse(test_bytes).unwrap(); + let mut test_variantlist = VariantList::new(); + test_variantlist.push(Variant::bool(true)); + assert_eq!(len, 10); + assert_eq!(res, test_variantlist); + } + + #[test] + pub fn variantmap_serialize() { + let mut test_variantmap = VariantMap::new(); + test_variantmap.insert("Configured".to_string(), Variant::bool(true)); + let bytes = [ + 0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, + 0, 101, 0, 100, 0, 0, 0, 1, 0, 1, + ] + .to_vec(); + assert_eq!(test_variantmap.serialize().unwrap(), bytes); + } + + #[test] + pub fn variantmap_deserialize() { + let test_bytes: &[u8] = &[ + 0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, + 0, 101, 0, 100, 0, 0, 0, 1, 0, 1, + ]; + let (len, res) = VariantMap::parse(test_bytes).unwrap(); + let mut test_variantmap = VariantMap::new(); + test_variantmap.insert("Configured".to_string(), Variant::bool(true)); + assert_eq!(len, 34); + assert_eq!(res, test_variantmap); + } + + #[test] + pub fn buffer_info_serialize() { + let test_buffer_info = BufferInfo { + id: 0, + network_id: 0, + buffer_type: primitive::BufferType::Status, + name: "test".to_string(), + }; + + let bytes = vec![ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x4, 0x74, 0x65, 0x73, 0x74, + ]; + assert_eq!(test_buffer_info.serialize().unwrap(), bytes); + } + + #[test] + pub fn buffer_info_deserialize() { + let test_buffer_info = BufferInfo { + id: 0, + network_id: 0, + buffer_type: primitive::BufferType::Status, + name: "test".to_string(), + }; + + let bytes = vec![ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x5, 0x74, 0x65, 0x73, 0x74, 0x0, + ]; + let (len, res) = BufferInfo::parse(&bytes).unwrap(); + + assert_eq!(len, 23); + assert_eq!(res, test_buffer_info); + } + + #[test] + fn strings_serialize() { + let test_string = "This is a Test!1!!".to_string(); + let test_string_list = vec!["test1".to_string(), "test 2".to_string()]; + + assert_eq!( + Variant::String(test_string.clone()).serialize().unwrap(), + [ + 0, 0, 0, 10, 0, 0, 0, 0, 36, 0, 0x54, 0, 0x68, 0, 0x69, 0, 0x73, 0, 0x20, 0, 0x69, + 0, 0x73, 0, 0x20, 0, 0x61, 0, 0x20, 0, 0x54, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x21, 0, + 0x31, 0, 0x21, 0, 0x21 + ] + ); + assert_eq!( + Variant::ByteArray(test_string.clone()).serialize().unwrap(), + [ + 0, 0, 0, 12, 0, 0, 0, 0, 18, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, + 0x20, 0x54, 0x65, 0x73, 0x74, 0x21, 0x31, 0x21, 0x21 + ] + ); + assert_eq!( + Variant::StringList(test_string_list).serialize().unwrap(), + [ + 0, 0, 0, 11, 0, 0, 0, 0, 2, 0, 0, 0, 10, 0, 0x74, 0, 0x65, 0, 0x73, 0, 0x74, 0, + 0x31, 0, 0, 0, 12, 0, 0x74, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x20, 0, 0x32 + ] + ); + } + + #[test] + fn strings_deserialize() { + let test_string = "This is a Test!1!!".to_string(); + let test_string_list = vec!["test1".to_string(), "test 2".to_string()]; + + let test_string_src = vec![ + 0, 0, 0, 10, 0, 0, 0, 0, 36, 0, 0x54, 0, 0x68, 0, 0x69, 0, 0x73, 0, 0x20, 0, 0x69, 0, + 0x73, 0, 0x20, 0, 0x61, 0, 0x20, 0, 0x54, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x21, 0, 0x31, + 0, 0x21, 0, 0x21, + ]; + + let test_string_src_utf8 = vec![ + 0, 0, 0, 12, 0, 0, 0, 0, 18, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, + 0x20, 0x54, 0x65, 0x73, 0x74, 0x21, 0x31, 0x21, 0x21, 0, + ]; + + let test_string_list_src = vec![ + 0, 0, 0, 11, 0, 0, 0, 0, 2, 0, 0, 0, 10, 0, 0x74, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x31, + 0, 0, 0, 12, 0, 0x74, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x20, 0, 0x32, + ]; + + assert_eq!( + (45, Variant::String(test_string.clone())), + Variant::parse(&test_string_src).unwrap() + ); + assert_eq!( + (27, Variant::ByteArray(test_string.clone())), + Variant::parse(&test_string_src_utf8).unwrap() + ); + assert_eq!( + (39, Variant::StringList(test_string_list)), + Variant::parse(&test_string_list_src).unwrap() + ); + } + + #[test] + fn datetime_serialize() { + let datetime = + Variant::DateTime(DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap()); + let date = Variant::Date(Date::parse("2020-02-19", "%Y-%m-%d").unwrap()); + let time = Variant::Time(Time::parse("13:00", "%R").unwrap()); + + assert_eq!( + datetime.serialize().unwrap(), + [0, 0, 0, 0x10, 0, 0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32] + ); + + assert_eq!( + date.serialize().unwrap(), + [0, 0, 0, 0x0e, 0, 0, 37, 133, 19] + ); + + assert_eq!( + time.serialize().unwrap(), + [0, 0, 0, 0x0f, 0, 2, 202, 28, 128] + ); + } + + #[test] + fn datetime_deserialize() { + let datetime = + Variant::DateTime(DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap()); + let date = Variant::Date(Date::parse("2020-02-19", "%Y-%m-%d").unwrap()); + let time = Variant::Time(Time::parse("13:00", "%R").unwrap()); + + assert_eq!( + (18, datetime), + Variant::parse(&[0, 0, 0, 0x10, 0, 0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32]) + .unwrap() + ); + + assert_eq!( + (9, date), + Variant::parse(&[0, 0, 0, 0x0e, 0, 0, 37, 133, 19]).unwrap() + ); + + assert_eq!( + (9, time), + Variant::parse(&[0, 0, 0, 0x0f, 0, 2, 202, 28, 128]).unwrap() + ); + } +} diff --git a/src/primitive/variantlist.rs b/src/primitive/variantlist.rs index a802864..7e74122 100644 --- a/src/primitive/variantlist.rs +++ b/src/primitive/variantlist.rs @@ -7,8 +7,6 @@ use log::trace; use crate::{Deserialize, Serialize}; -extern crate bytes; - use crate::primitive::Variant; /// VariantLists are represented as a Vec of Variants. diff --git a/src/primitive/variantmap.rs b/src/primitive/variantmap.rs index 4f017f3..d43028c 100644 --- a/src/primitive/variantmap.rs +++ b/src/primitive/variantmap.rs @@ -11,8 +11,6 @@ use crate::Serialize; use crate::primitive::Variant; use crate::util; -extern crate bytes; - /// VariantMaps are represented as a HashMap with String as key and Variant as value /// /// They are serialized as the amount of keys as an i32 then for each entry a String and a Variant. diff --git a/src/tests/base_types.rs b/src/tests/base_types.rs deleted file mode 100644 index bbd2fc3..0000000 --- a/src/tests/base_types.rs +++ /dev/null @@ -1,84 +0,0 @@ -use crate::{Deserialize, DeserializeUTF8}; -use crate::{Serialize, SerializeUTF8}; - -use crate::primitive::*; - -#[test] -pub fn serialize_string() { - let test_string: String = String::from("Configured"); - - assert_eq!( - test_string.serialize().unwrap(), - [ - 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, - 100 - ] - ); -} - -#[test] -pub fn serialize_string_utf8() { - let test_string: String = String::from("Configured"); - - assert_eq!( - test_string.serialize_utf8().unwrap(), - [0, 0, 0, 11, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0] - ); -} - -#[test] -pub fn deserialize_string() { - let test_bytes: &[u8] = &[ - 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, - 0, 0, 0, 1, - ]; - let (len, res) = String::parse(test_bytes).unwrap(); - assert_eq!(res, "Configured"); - assert_eq!(len, 24); -} - -#[test] -pub fn deserialize_string_utf8() { - let test_bytes: &[u8] = &[ - 0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0, 0, 0, 1, - ]; - let (len, res) = String::parse_utf8(test_bytes).unwrap(); - assert_eq!(len, 14); - assert_eq!(res, "Configured"); -} - -#[test] -pub fn deserialize_string_utf8_null_terminated() { - let test_bytes: &[u8] = &[ - 0, 0, 0, 11, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0, 0, 0, 0, 1, - ]; - let (len, res) = String::parse_utf8(test_bytes).unwrap(); - assert_eq!(len, 15); - assert_eq!(res, "Configured"); -} - -#[test] -pub fn serialize_string_list() { - let mut test_list = StringList::new(); - test_list.push("Configured".to_string()); - assert_eq!( - test_list.serialize().unwrap(), - [ - 0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, - 0, 101, 0, 100 - ] - ) -} - -#[test] -pub fn deserialize_string_list() { - let test_bytes: &[u8] = &[ - 0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, - 101, 0, 100, 0, 0, 0, 1, - ]; - let mut test_list = StringList::new(); - test_list.push("Configured".to_string()); - let (len, res) = StringList::parse(test_bytes).unwrap(); - assert_eq!(len, 28); - assert_eq!(test_list, res); -} diff --git a/src/tests/datetime.rs b/src/tests/datetime.rs deleted file mode 100644 index 85d84cb..0000000 --- a/src/tests/datetime.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::Deserialize; -use crate::Serialize; - -use crate::primitive::DateTime; - -#[test] -pub fn serialize_datetime() { - // Create datetime object - let datetime = DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap(); - println!("datetime: {:?}", datetime); - - let sers = datetime.serialize().unwrap(); - let bytes = vec![0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32]; - - assert_eq!(sers, bytes) -} - -#[test] -pub fn deserialize_datetime() { - // Create datetime object - let datetime = DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap(); - println!("datetime: {:?}", datetime); - - let bytes = vec![0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32]; - let (_, res): (usize, DateTime) = Deserialize::parse(&bytes).unwrap(); - - assert_eq!(res, datetime) -} diff --git a/src/tests/frame.rs b/src/tests/frame.rs deleted file mode 100644 index 878379f..0000000 --- a/src/tests/frame.rs +++ /dev/null @@ -1,240 +0,0 @@ -use tokio::io::{AsyncRead, AsyncWrite}; -use tokio_test::task; -use tokio_test::{ - assert_err, assert_ok, assert_pending, assert_ready, assert_ready_err, assert_ready_ok, -}; -use tokio_util::codec::*; - -use bytes::{BufMut, Bytes, BytesMut}; -use futures::{pin_mut, Sink, Stream}; - -use std::collections::VecDeque; -use std::io; -use std::pin::Pin; -use std::task::Poll::*; -use std::task::{Context, Poll}; - -use flate2::Compress; -use flate2::Compression; -use flate2::Decompress; -use flate2::FlushCompress; -use flate2::FlushDecompress; - -use crate::frame::QuasselCodec; - -macro_rules! mock { - ($($x:expr,)*) => {{ - let mut v = VecDeque::new(); - v.extend(vec![$($x),*]); - Mock { calls: v } - }}; -} - -macro_rules! assert_next_eq { - ($io:ident, $expect:expr) => {{ - task::spawn(()).enter(|cx, _| { - let res = assert_ready!($io.as_mut().poll_next(cx)); - match res { - Some(Ok(v)) => assert_eq!(v, $expect.as_ref()), - Some(Err(e)) => panic!("error = {:?}", e), - None => panic!("none"), - } - }); - }}; -} - -macro_rules! assert_next_pending { - ($io:ident) => {{ - task::spawn(()).enter(|cx, _| match $io.as_mut().poll_next(cx) { - Ready(Some(Ok(v))) => panic!("value = {:?}", v), - Ready(Some(Err(e))) => panic!("error = {:?}", e), - Ready(None) => panic!("done"), - Pending => {} - }); - }}; -} - -macro_rules! assert_next_err { - ($io:ident) => {{ - task::spawn(()).enter(|cx, _| match $io.as_mut().poll_next(cx) { - Ready(Some(Ok(v))) => panic!("value = {:?}", v), - Ready(Some(Err(_))) => {} - Ready(None) => panic!("done"), - Pending => panic!("pending"), - }); - }}; -} - -macro_rules! assert_done { - ($io:ident) => {{ - task::spawn(()).enter(|cx, _| { - let res = assert_ready!($io.as_mut().poll_next(cx)); - match res { - Some(Ok(v)) => panic!("value = {:?}", v), - Some(Err(e)) => panic!("error = {:?}", e), - None => {} - } - }); - }}; -} - -// ====================== -// ===== Test ===== -// ====================== - -#[test] -pub fn read_single_frame() { - let io = FramedRead::new( - mock! { - data(b"\x00\x00\x00\x09abcdefghi"), - }, - QuasselCodec::new(), - ); - pin_mut!(io); - - assert_next_eq!(io, b"abcdefghi"); - assert_done!(io); -} - -#[test] -pub fn read_multi_frame() { - let mut d: Vec<u8> = vec![]; - d.extend_from_slice(b"\x00\x00\x00\x09abcdefghi"); - d.extend_from_slice(b"\x00\x00\x00\x03123"); - d.extend_from_slice(b"\x00\x00\x00\x0bhello world"); - - let io = FramedRead::new( - mock! { - data(&d), - }, - QuasselCodec::new(), - ); - pin_mut!(io); - - assert_next_eq!(io, b"abcdefghi"); - assert_next_eq!(io, b"123"); - assert_next_eq!(io, b"hello world"); - assert_done!(io); -} - -#[test] -pub fn read_single_frame_compressed() { - let io = FramedRead::new( - mock! { - data(b"\x78\x9c\x63\x60\x60\xe0\x4c\x4c\x4a\x4e\x49\x4d\x4b\xcf\xc8\x04\x00\x11\xec\x03\x97"), - }, - QuasselCodec::builder().compression(true).new_codec(), - ); - pin_mut!(io); - - assert_next_eq!(io, b"abcdefghi"); - assert_done!(io); -} - -#[test] -pub fn read_multi_frame_compressed() { - let io = FramedRead::new( - mock! { - data( - b"\x78\x9c\x63\x60\x60\xe0\x4c\x4c\x4a\x4e\x49\x4d\x4b\xcf\xc8\x04\x00\x11\xec\x03\x97\x78\x9c\x63\x60\x60\x60\x36\x34\x32\x06\x00\x01\x3d\x00\x9a\x78\x9c\x63\x60\x60\xe0\xce\x48\xcd\xc9\xc9\x57\x28\xcf\x2f\xca\x49\x01\x00\x1a\x93\x04\x68", - ), - }, - QuasselCodec::builder().compression(true).new_codec(), - ); - pin_mut!(io); - - assert_next_eq!(io, b"abcdefghi"); - assert_next_eq!(io, b"123"); - assert_next_eq!(io, b"hello world"); - assert_done!(io); -} - -// ====================== -// ===== Test utils ===== -// ====================== - -struct Mock { - calls: VecDeque<Poll<io::Result<Op>>>, -} - -enum Op { - Data(Vec<u8>), - Flush, -} - -use self::Op::*; - -impl AsyncRead for Mock { - fn poll_read( - mut self: Pin<&mut Self>, - _cx: &mut Context<'_>, - dst: &mut [u8], - ) -> Poll<io::Result<usize>> { - match self.calls.pop_front() { - Some(Ready(Ok(Op::Data(data)))) => { - debug_assert!(dst.len() >= data.len()); - dst[..data.len()].copy_from_slice(&data[..]); - Ready(Ok(data.len())) - } - Some(Ready(Ok(_))) => panic!(), - Some(Ready(Err(e))) => Ready(Err(e)), - Some(Pending) => Pending, - None => Ready(Ok(0)), - } - } -} - -impl AsyncWrite for Mock { - fn poll_write( - mut self: Pin<&mut Self>, - _cx: &mut Context<'_>, - src: &[u8], - ) -> Poll<Result<usize, io::Error>> { - match self.calls.pop_front() { - Some(Ready(Ok(Op::Data(data)))) => { - let len = data.len(); - assert!(src.len() >= len, "expect={:?}; actual={:?}", data, src); - assert_eq!(&data[..], &src[..len]); - Ready(Ok(len)) - } - Some(Ready(Ok(_))) => panic!(), - Some(Ready(Err(e))) => Ready(Err(e)), - Some(Pending) => Pending, - None => Ready(Ok(0)), - } - } - - fn poll_flush(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { - match self.calls.pop_front() { - Some(Ready(Ok(Op::Flush))) => Ready(Ok(())), - Some(Ready(Ok(_))) => panic!(), - Some(Ready(Err(e))) => Ready(Err(e)), - Some(Pending) => Pending, - None => Ready(Ok(())), - } - } - - fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> { - Ready(Ok(())) - } -} - -impl<'a> From<&'a [u8]> for Op { - fn from(src: &'a [u8]) -> Op { - Op::Data(src.into()) - } -} - -impl From<Vec<u8>> for Op { - fn from(src: Vec<u8>) -> Op { - Op::Data(src) - } -} - -fn data(bytes: &[u8]) -> Poll<io::Result<Op>> { - Ready(Ok(bytes.into())) -} - -fn flush() -> Poll<io::Result<Op>> { - Ready(Ok(Flush)) -} diff --git a/src/tests/handshake_types.rs b/src/tests/handshake_types.rs deleted file mode 100644 index 1e789c1..0000000 --- a/src/tests/handshake_types.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::primitive::{Variant, VariantMap}; -use crate::{HandshakeDeserialize, HandshakeSerialize}; - -#[test] -pub fn serialize_variantmap() { - let mut test_variantmap = VariantMap::new(); - test_variantmap.insert("Configured".to_string(), Variant::bool(true)); - let bytes = [ - 0, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, - 117, 0, 114, 0, 101, 0, 100, 0, 0, 0, 1, 0, 1, - ] - .to_vec(); - assert_eq!(test_variantmap.serialize().unwrap(), bytes); -} - -#[test] -pub fn deserialize_variantmap() { - let test_bytes: &[u8] = &[ - 0, 0, 0, 2, 0, 0, 0, 10, 0, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, - 117, 0, 114, 0, 101, 0, 100, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, - ]; - let mut test_variantmap = VariantMap::new(); - test_variantmap.insert("Configured".to_string(), Variant::bool(true)); - - let (len, res) = VariantMap::parse(test_bytes).unwrap(); - - assert_eq!(len, 39); - assert_eq!(res, test_variantmap); -} - -#[test] -pub fn deserialize_variantmap_utf8() { - let test_bytes: &[u8] = &[ - 0, 0, 0, 2, 0, 0, 0, 12, 0, 0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, - 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, - ]; - let mut test_variantmap = VariantMap::new(); - test_variantmap.insert("Configured".to_string(), Variant::bool(true)); - - let (len, res) = VariantMap::parse(test_bytes).unwrap(); - - assert_eq!(len, 29); - assert_eq!(res, test_variantmap); -} diff --git a/src/tests/mod.rs b/src/tests/mod.rs deleted file mode 100644 index 1e99bfe..0000000 --- a/src/tests/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -pub mod base_types; -pub mod datetime; - -#[allow(unused_imports)] -#[allow(unused_macros)] -#[allow(dead_code)] -#[cfg(feature = "framing")] -pub mod frame; - -pub mod handshake_types; - -pub mod variant_types; - -extern crate futures; -extern crate tokio; -extern crate tokio_test; -extern crate tokio_util; diff --git a/src/tests/variant_types.rs b/src/tests/variant_types.rs deleted file mode 100644 index 7ba4166..0000000 --- a/src/tests/variant_types.rs +++ /dev/null @@ -1,100 +0,0 @@ -use crate::Deserialize; -use crate::Serialize; - -use crate::primitive::{BufferInfo, BufferType, Message, Variant, VariantList, VariantMap}; - -#[test] -pub fn serialize_variant_bool() { - let test_variant_true = Variant::bool(true); - let test_variant_false = Variant::bool(false); - assert_eq!(test_variant_true.serialize().unwrap(), [0, 0, 0, 1, 0, 1]); - assert_eq!(test_variant_false.serialize().unwrap(), [0, 0, 0, 1, 0, 0]); -} - -#[test] -pub fn deserialize_variant_bool() { - let test_bytes: &[u8] = &[0, 0, 0, 1, 0, 1, 0, 0, 0, 1]; - let (len, res) = Variant::parse(test_bytes).unwrap(); - assert_eq!(len, 6); - assert_eq!(res, Variant::bool(true)); -} - -#[test] -pub fn serialize_variantlist() { - let mut test_variantlist = VariantList::new(); - test_variantlist.push(Variant::bool(true)); - assert_eq!( - test_variantlist.serialize().unwrap(), - [0, 0, 0, 1, 0, 0, 0, 1, 0, 1] - ); -} - -#[test] -pub fn deserialize_variantlist() { - let test_bytes: &[u8] = &[0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1]; - let (len, res) = VariantList::parse(test_bytes).unwrap(); - let mut test_variantlist = VariantList::new(); - test_variantlist.push(Variant::bool(true)); - assert_eq!(len, 10); - assert_eq!(res, test_variantlist); -} - -#[test] -pub fn serialize_variantmap() { - let mut test_variantmap = VariantMap::new(); - test_variantmap.insert("Configured".to_string(), Variant::bool(true)); - let bytes = [ - 0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, - 101, 0, 100, 0, 0, 0, 1, 0, 1, - ] - .to_vec(); - assert_eq!(test_variantmap.serialize().unwrap(), bytes); -} - -#[test] -pub fn deserialize_variantmap() { - let test_bytes: &[u8] = &[ - 0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, - 101, 0, 100, 0, 0, 0, 1, 0, 1, - ]; - let (len, res) = VariantMap::parse(test_bytes).unwrap(); - let mut test_variantmap = VariantMap::new(); - test_variantmap.insert("Configured".to_string(), Variant::bool(true)); - assert_eq!(len, 34); - assert_eq!(res, test_variantmap); -} - -#[test] -pub fn serialize_buffer_info() { - let test_buffer_info = BufferInfo { - id: 0, - network_id: 0, - buffer_type: BufferType::Status, - name: "test".to_string(), - }; - - let bytes = vec![ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0x74, 0x65, 0x73, 0x74, 0x0, - ]; - assert_eq!(test_buffer_info.serialize().unwrap(), bytes); -} - -#[test] -pub fn deserialize_buffer_info() { - let test_buffer_info = BufferInfo { - id: 0, - network_id: 0, - buffer_type: BufferType::Status, - name: "test".to_string(), - }; - - let bytes = vec![ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, - 0x74, 0x65, 0x73, 0x74, 0x0, - ]; - let (len, res) = BufferInfo::parse(&bytes).unwrap(); - - assert_eq!(len, 23); - assert_eq!(res, test_buffer_info); -} diff --git a/src/util.rs b/src/util.rs index eeeda4e..6051a96 100644 --- a/src/util.rs +++ b/src/util.rs @@ -38,3 +38,22 @@ pub fn insert_bytes(pos: usize, buf: &mut Vec<u8>, input: &mut [u8]) { buf.insert(pos, *i) } } + +#[macro_export] +macro_rules! map { + // map-like + ($($k:expr => $v:expr),* $(,)?) => { + std::iter::Iterator::collect(std::array::IntoIter::new([$(($k, $v),)*])) + }; + // set-like + ($($v:expr),* $(,)?) => { + std::iter::Iterator::collect(std::array::IntoIter::new([$($v,)*])) + }; +} + +#[macro_export] +macro_rules! s { + ($values:expr) => { + std::string::String::from($values) + }; +} |
