xso: reject duplicate children

This was an oversight. Even though we apparently don't have tests for
this anywhere, it is what the old functional macros do.
This commit is contained in:
Jonas Schäfer 2024-08-03 13:28:07 +02:00 committed by Link Mauve
commit 6440209f95
5 changed files with 92 additions and 1 deletions

View file

@ -96,4 +96,36 @@ mod tests {
let serialized: Element = forwarded.into();
assert_eq!(serialized, reference);
}
#[test]
fn test_invalid_duplicate_delay() {
let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25+00:00'/><delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25+00:00'/><message xmlns='jabber:client' to='juliet@capulet.example/balcony' from='romeo@montague.example/home'/></forwarded>"
.parse()
.unwrap();
let error = Forwarded::try_from(elem).unwrap_err();
let message = match error {
FromElementError::Invalid(Error::Other(string)) => string,
_ => panic!(),
};
assert_eq!(
message,
"Element forwarded must not have more than one delay child."
);
}
#[test]
fn test_invalid_duplicate_message() {
let elem: Element = "<forwarded xmlns='urn:xmpp:forward:0'><delay xmlns='urn:xmpp:delay' from='capulet.com' stamp='2002-09-10T23:08:25+00:00'/><message xmlns='jabber:client' to='juliet@capulet.example/balcony' from='romeo@montague.example/home'/><message xmlns='jabber:client' to='juliet@capulet.example/balcony' from='romeo@montague.example/home'/></forwarded>"
.parse()
.unwrap();
let error = Forwarded::try_from(elem).unwrap_err();
let message = match error {
FromElementError::Invalid(Error::Other(string)) => string,
_ => panic!(),
};
assert_eq!(
message,
"Element forwarded must not have more than one message child."
);
}
}

View file

@ -39,3 +39,26 @@ pub struct Query {
impl IqSetPayload for Query {}
impl IqGetPayload for Query {}
impl IqResultPayload for Query {}
#[cfg(test)]
mod tests {
use super::*;
use minidom::Element;
use xso::error::{Error, FromElementError};
#[test]
fn test_invalid_duplicate_child() {
let elem: Element = "<query xmlns='jabber:iq:private'><storage xmlns='storage:bookmarks'/><storage xmlns='storage:bookmarks'/></query>"
.parse()
.unwrap();
let error = Query::try_from(elem).unwrap_err();
let message = match error {
FromElementError::Invalid(Error::Other(string)) => string,
_ => panic!(),
};
assert_eq!(
message,
"Query element must not have more than one child in field 'storage'."
);
}
}

View file

@ -522,6 +522,19 @@ fn parent_positive() {
assert_eq!(v.child.foo, "hello world!");
}
#[test]
fn parent_negative_duplicate_child() {
#[allow(unused_imports)]
use std::{
option::Option::{None, Some},
result::Result::{Err, Ok},
};
match parse_str::<Parent>("<parent xmlns='urn:example:ns1'><attr foo='hello world!'/><attr foo='hello world!'/></parent>") {
Err(::xso::error::FromElementError::Invalid(::xso::error::Error::Other(e))) if e.contains("must not have more than one") => (),
other => panic!("unexpected result: {:?}", other),
}
}
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
#[xml(namespace = NS1, name = "parent")]
struct OptionalChild {