diff --git a/parsers/Cargo.toml b/parsers/Cargo.toml index 6f233c39..3b070eb3 100644 --- a/parsers/Cargo.toml +++ b/parsers/Cargo.toml @@ -32,7 +32,7 @@ uuid = { version = "1.9.1", features = ["v4"] } # Build xmpp-parsers to make components instead of clients. component = [] # Disable validation of unknown attributes. -disable-validation = [] +disable-validation = [ "xso/non-pedantic" ] # Enable serde support in jid crate serde = [ "jid/serde" ] # Enable some additional logging in helpers diff --git a/parsers/src/bind.rs b/parsers/src/bind.rs index d8486692..4ea5e4fa 100644 --- a/parsers/src/bind.rs +++ b/parsers/src/bind.rs @@ -77,6 +77,7 @@ impl From for Jid { mod tests { use super::*; use minidom::Element; + #[cfg(not(feature = "disable-validation"))] use xso::error::{Error, FromElementError}; #[cfg(target_pointer_width = "32")] diff --git a/parsers/src/blocking.rs b/parsers/src/blocking.rs index d41fe11c..897f8657 100644 --- a/parsers/src/blocking.rs +++ b/parsers/src/blocking.rs @@ -62,6 +62,7 @@ pub struct Blocked; #[cfg(test)] mod tests { + #[cfg(not(feature = "disable-validation"))] use xso::error::{Error, FromElementError}; use super::*; diff --git a/parsers/src/bob.rs b/parsers/src/bob.rs index 1f09c8ec..40cbd3df 100644 --- a/parsers/src/bob.rs +++ b/parsers/src/bob.rs @@ -194,6 +194,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn unknown_child() { let elem: Element = "" .parse() diff --git a/parsers/src/data_forms_validate.rs b/parsers/src/data_forms_validate.rs index 37365931..57d8ce21 100644 --- a/parsers/src/data_forms_validate.rs +++ b/parsers/src/data_forms_validate.rs @@ -448,7 +448,11 @@ mod tests { } #[test] - fn test_fails_with_invalid_children() -> Result<(), Error> { + #[cfg_attr( + feature = "disable-validation", + should_panic = "Validate::try_from(element).is_err()" + )] + fn test_fails_with_invalid_children() { let cases = [ r#""#, r#""#, @@ -460,7 +464,5 @@ mod tests { .expect(&format!("Failed to parse {}", case)); assert!(Validate::try_from(element).is_err()); } - - Ok(()) } } diff --git a/parsers/src/delay.rs b/parsers/src/delay.rs index 717115c2..c103fe5f 100644 --- a/parsers/src/delay.rs +++ b/parsers/src/delay.rs @@ -81,6 +81,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { let elem: Element = "" diff --git a/parsers/src/disco.rs b/parsers/src/disco.rs index 8428bd43..1cf51063 100644 --- a/parsers/src/disco.rs +++ b/parsers/src/disco.rs @@ -258,6 +258,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid() { let elem: Element = "" diff --git a/parsers/src/ecaps2.rs b/parsers/src/ecaps2.rs index e31dc3cf..04f4c099 100644 --- a/parsers/src/ecaps2.rs +++ b/parsers/src/ecaps2.rs @@ -219,6 +219,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { let elem: Element = "K1Njy3HZBThlo4moOD5gBGhn0U0oK7/CbfLlIUDi6o4=+sDTQqBmX6iG/X3zjt06fjZMBBqL/723knFIyRf0sg8=".parse().unwrap(); let error = ECaps2::try_from(elem).unwrap_err(); diff --git a/parsers/src/eme.rs b/parsers/src/eme.rs index fafba2b4..ca75d0d0 100644 --- a/parsers/src/eme.rs +++ b/parsers/src/eme.rs @@ -72,6 +72,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { let elem: Element = "" diff --git a/parsers/src/forwarding.rs b/parsers/src/forwarding.rs index 4963b2a7..2584fc80 100644 --- a/parsers/src/forwarding.rs +++ b/parsers/src/forwarding.rs @@ -56,8 +56,9 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { - let elem: Element = "" + let elem: Element = "" .parse() .unwrap(); let error = Forwarded::try_from(elem).unwrap_err(); diff --git a/parsers/src/hashes.rs b/parsers/src/hashes.rs index 332e69af..0febefc0 100644 --- a/parsers/src/hashes.rs +++ b/parsers/src/hashes.rs @@ -305,6 +305,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { let elem: Element = "" .parse() diff --git a/parsers/src/idle.rs b/parsers/src/idle.rs index 08b14ef8..54cb235d 100644 --- a/parsers/src/idle.rs +++ b/parsers/src/idle.rs @@ -42,6 +42,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { let elem: Element = "" diff --git a/parsers/src/jingle.rs b/parsers/src/jingle.rs index 9f14da0a..f216d6d2 100644 --- a/parsers/src/jingle.rs +++ b/parsers/src/jingle.rs @@ -754,7 +754,7 @@ mod tests { } #[test] - fn test_invalid_reason() { + fn test_missing_reason_text() { let elem: Element = "".parse().unwrap(); let error = Jingle::try_from(elem).unwrap_err(); let message = match error { @@ -765,23 +765,22 @@ mod tests { message, "Missing child field 'reason' in ReasonElement element." ); + } - let elem: Element = "".parse().unwrap(); - let error = Jingle::try_from(elem).unwrap_err(); - let message = match error { - FromElementError::Invalid(Error::Other(string)) => string, - _ => panic!(), - }; - assert_eq!(message, "Unknown child in ReasonElement element."); - - let elem: Element = "".parse().unwrap(); + #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] + fn test_invalid_child_in_reason() { + let elem: Element = "".parse().unwrap(); let error = Jingle::try_from(elem).unwrap_err(); let message = match error { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; assert_eq!(message, "Unknown child in ReasonElement element."); + } + #[test] + fn test_multiple_reason_children() { let elem: Element = "".parse().unwrap(); let error = Jingle::try_from(elem).unwrap_err(); let message = match error { diff --git a/parsers/src/jingle_ft.rs b/parsers/src/jingle_ft.rs index 746581cc..23b9d155 100644 --- a/parsers/src/jingle_ft.rs +++ b/parsers/src/jingle_ft.rs @@ -304,7 +304,7 @@ mod tests { } #[test] - fn test_received() { + fn test_received_valid() { let elem: Element = "".parse().unwrap(); let received = Received::try_from(elem).unwrap(); assert_eq!(received.name, ContentId(String::from("coucou"))); @@ -313,7 +313,11 @@ mod tests { let received2 = Received::try_from(elem2).unwrap(); assert_eq!(received2.name, ContentId(String::from("coucou"))); assert_eq!(received2.creator, Creator::Initiator); + } + #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] + fn test_received_unknown_child() { let elem: Element = "".parse().unwrap(); let error = Received::try_from(elem).unwrap_err(); let message = match error { @@ -321,7 +325,10 @@ mod tests { _ => panic!(), }; assert_eq!(message, "Unknown child in Received element."); + } + #[test] + fn test_received_missing_name() { let elem: Element = "" .parse() @@ -335,7 +342,10 @@ mod tests { message, "Required attribute field 'name' on Received element missing." ); + } + #[test] + fn test_received_invalid_creator() { let elem: Element = "".parse().unwrap(); let error = Received::try_from(elem).unwrap_err(); let message = match error { @@ -361,7 +371,7 @@ mod tests { } #[test] - fn test_checksum() { + fn test_checksum_valid() { let elem: Element = "w0mcJylzCn+AfvuGdqkty2+KP48=".parse().unwrap(); let hash = vec![ 195, 73, 156, 39, 41, 115, 10, 127, 128, 126, 251, 134, 118, 169, 45, 203, 111, 138, @@ -388,15 +398,22 @@ mod tests { hash: hash.clone() }) ); + } - let elem: Element = "".parse().unwrap(); + #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] + fn test_checksum_unknown_child() { + let elem: Element = "w0mcJylzCn+AfvuGdqkty2+KP48=".parse().unwrap(); let error = Checksum::try_from(elem).unwrap_err(); let message = match error { FromElementError::Invalid(Error::Other(string)) => string, other => panic!("unexpected error: {:?}", other), }; assert_eq!(message, "Unknown child in Checksum element."); + } + #[test] + fn test_checksum_missing_name() { let elem: Element = "w0mcJylzCn+AfvuGdqkty2+KP48=".parse().unwrap(); let error = Checksum::try_from(elem).unwrap_err(); let message = match error { @@ -407,7 +424,10 @@ mod tests { message, "Required attribute field 'name' on Checksum element missing." ); + } + #[test] + fn test_checksum_invalid_creator() { let elem: Element = "w0mcJylzCn+AfvuGdqkty2+KP48=".parse().unwrap(); let error = Checksum::try_from(elem).unwrap_err(); let message = match error { diff --git a/parsers/src/media_element.rs b/parsers/src/media_element.rs index 44c617ec..d17b0da1 100644 --- a/parsers/src/media_element.rs +++ b/parsers/src/media_element.rs @@ -154,6 +154,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_unknown_child() { let elem: Element = "" .parse() diff --git a/parsers/src/message_correct.rs b/parsers/src/message_correct.rs index 9b3c2c94..200a00a8 100644 --- a/parsers/src/message_correct.rs +++ b/parsers/src/message_correct.rs @@ -62,6 +62,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { let elem: Element = "" diff --git a/parsers/src/muc/muc.rs b/parsers/src/muc/muc.rs index c9aa0b08..61398037 100644 --- a/parsers/src/muc/muc.rs +++ b/parsers/src/muc/muc.rs @@ -113,6 +113,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_muc_invalid_child() { let elem: Element = "" .parse() diff --git a/parsers/src/muc/user.rs b/parsers/src/muc/user.rs index 50cba625..9835de87 100644 --- a/parsers/src/muc/user.rs +++ b/parsers/src/muc/user.rs @@ -317,6 +317,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { let elem: Element = " @@ -490,6 +491,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_continue_invalid() { let elem: Element = "" diff --git a/parsers/src/occupant_id.rs b/parsers/src/occupant_id.rs index a175f647..040fbf96 100644 --- a/parsers/src/occupant_id.rs +++ b/parsers/src/occupant_id.rs @@ -53,6 +53,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { let elem: Element = "" diff --git a/parsers/src/roster.rs b/parsers/src/roster.rs index 67226423..6e044bb8 100644 --- a/parsers/src/roster.rs +++ b/parsers/src/roster.rs @@ -289,7 +289,7 @@ mod tests { } #[test] - fn test_invalid_item() { + fn test_item_missing_jid() { let elem: Element = "" .parse() .unwrap(); @@ -302,7 +302,10 @@ mod tests { message, "Required attribute field 'jid' on Item element missing." ); + } + #[test] + fn test_item_invalid_jid() { let elem: Element = "" .parse() .unwrap(); @@ -311,7 +314,11 @@ mod tests { format!("{error}"), "text parse error: no domain found in this JID" ); + } + #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] + fn test_item_unknown_child() { let elem: Element = "" .parse() diff --git a/parsers/src/sasl.rs b/parsers/src/sasl.rs index de4abb1b..b18c8343 100644 --- a/parsers/src/sasl.rs +++ b/parsers/src/sasl.rs @@ -157,7 +157,7 @@ pub struct Failure { /// A human-readable explanation for the failure. #[xml(extract(n = .., name = "text", fields( - attribute(type_ = String, name = "xml:lang"), + attribute(type_ = String, name = "xml:lang", default), text(type_ = String), )))] pub texts: BTreeMap, diff --git a/parsers/src/stanza_id.rs b/parsers/src/stanza_id.rs index 04575d3d..ae65cc84 100644 --- a/parsers/src/stanza_id.rs +++ b/parsers/src/stanza_id.rs @@ -76,6 +76,7 @@ mod tests { } #[test] + #[cfg_attr(feature = "disable-validation", should_panic = "Result::unwrap_err")] fn test_invalid_child() { let elem: Element = "" diff --git a/parsers/src/util/macro_tests.rs b/parsers/src/util/macro_tests.rs index 0da7e6d2..c08c5919 100644 --- a/parsers/src/util/macro_tests.rs +++ b/parsers/src/util/macro_tests.rs @@ -121,6 +121,10 @@ fn empty_namespace_mismatch() { } #[test] +#[cfg_attr( + feature = "disable-validation", + should_panic = "unexpected result: Ok(" +)] fn empty_unexpected_attribute() { #[allow(unused_imports)] use core::{ @@ -136,6 +140,10 @@ fn empty_unexpected_attribute() { } #[test] +#[cfg_attr( + feature = "disable-validation", + should_panic = "unexpected result: Ok(" +)] fn empty_unexpected_child() { #[allow(unused_imports)] use core::{ @@ -869,6 +877,10 @@ fn text_extract_negative_absent_child() { } #[test] +#[cfg_attr( + feature = "disable-validation", + should_panic = "unexpected result: Ok(" +)] fn text_extract_negative_unexpected_attribute_in_child() { #[allow(unused_imports)] use core::{ @@ -886,6 +898,10 @@ fn text_extract_negative_unexpected_attribute_in_child() { } #[test] +#[cfg_attr( + feature = "disable-validation", + should_panic = "unexpected result: Ok(" +)] fn text_extract_negative_unexpected_child_in_child() { #[allow(unused_imports)] use core::{ @@ -1807,6 +1823,10 @@ fn ignore_unknown_attributes_positive() { } #[test] +#[cfg_attr( + feature = "disable-validation", + should_panic = "unexpected result: Ok(" +)] fn ignore_unknown_attributes_negative_unexpected_child() { #[allow(unused_imports)] use core::{ @@ -1849,6 +1869,10 @@ fn ignore_unknown_children_positive() { } #[test] +#[cfg_attr( + feature = "disable-validation", + should_panic = "unexpected result: Ok(" +)] fn ignore_unknown_children_negative_unexpected_attribute() { #[allow(unused_imports)] use core::{ diff --git a/xso/Cargo.toml b/xso/Cargo.toml index 7096307e..4a0e5f36 100644 --- a/xso/Cargo.toml +++ b/xso/Cargo.toml @@ -29,6 +29,7 @@ default = [ "std" ] macros = [ "dep:xso_proc", "rxml/macros" ] minidom = [ "xso_proc/minidom"] panicking-into-impl = ["xso_proc/panicking-into-impl"] +non-pedantic = [] std = [] [package.metadata.docs.rs] diff --git a/xso/src/lib.rs b/xso/src/lib.rs index 568e1cd1..3417936e 100644 --- a/xso/src/lib.rs +++ b/xso/src/lib.rs @@ -324,13 +324,18 @@ impl AsOptionalXmlText for Option { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] pub enum UnknownAttributePolicy { /// All unknown attributes are discarded. + /// + /// This is the default policy if the crate is built with the + /// `non-pedantic` feature. + #[cfg_attr(feature = "non-pedantic", default)] Discard, /// The first unknown attribute which is encountered generates a fatal /// parsing error. /// - /// This is the default policy. - #[default] + /// This is the default policy if the crate is built **without** the + /// `non-pedantic` feature. + #[cfg_attr(not(feature = "non-pedantic"), default)] Fail, } @@ -356,13 +361,18 @@ impl UnknownAttributePolicy { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] pub enum UnknownChildPolicy { /// All unknown children are discarded. + /// + /// This is the default policy if the crate is built with the + /// `non-pedantic` feature. + #[cfg_attr(feature = "non-pedantic", default)] Discard, /// The first unknown child which is encountered generates a fatal /// parsing error. /// - /// This is the default policy. - #[default] + /// This is the default policy if the crate is built **without** the + /// `non-pedantic` feature. + #[cfg_attr(not(feature = "non-pedantic"), default)] Fail, }