use ddex_parser::parser::security::SecurityConfig;
use ddex_parser::{error::ParseError, DDEXParser};
use std::io::Cursor;
#[test]
fn test_mismatched_opening_closing_tags() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG001</ern:MessageId>
<ern:MessageSender>
<ern:PartyId>SENDER001</ern:PartyId>
</ern:MessageSender>
<ern:MessageRecipient>
<ern:PartyId>RECIPIENT001</ern:PartyId>
</ern:MessageRecipient>
</ern:MessageHeader>
<ern:ReleaseList>
<ern:Release>
<ern:ReleaseId>REL001</ern:ReleaseId>
</ern:WrongTag>
</ern:ReleaseList>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
match result {
Err(ParseError::MismatchedTags {
expected, found, ..
}) => {
assert_eq!(expected, "Release");
assert_eq!(found, "WrongTag");
}
other => panic!("Expected MismatchedTags error, got: {:?}", other),
}
}
#[test]
fn test_unexpected_closing_tag() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG002</ern:MessageId>
<ern:MessageSender>
<ern:PartyId>SENDER002</ern:PartyId>
</ern:MessageSender>
<ern:MessageRecipient>
<ern:PartyId>RECIPIENT002</ern:PartyId>
</ern:MessageRecipient>
</ern:MessageHeader>
<ern:ReleaseList>
<ern:Release>
<ern:ReleaseId>REL002</ern:ReleaseId>
</ern:Release>
</ern:UnexpectedTag>
</ern:ReleaseList>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
match result {
Err(ParseError::UnexpectedClosingTag { tag, .. }) => {
assert_eq!(tag, "UnexpectedTag");
}
other => panic!("Expected UnexpectedClosingTag error, got: {:?}", other),
}
}
#[test]
fn test_unclosed_tags() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG003</ern:MessageId>
<ern:MessageSender>
<ern:PartyId>SENDER003</ern:PartyId>
</ern:MessageSender>
<ern:MessageRecipient>
<ern:PartyId>RECIPIENT003</ern:PartyId>
</ern:MessageRecipient>
</ern:MessageHeader>
<ern:ReleaseList>
<ern:Release>
<ern:ReleaseId>REL003</ern:ReleaseId>
<!-- Missing closing tags -->"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
match result {
Err(ParseError::UnclosedTags { tags, .. }) => {
assert!(tags.contains(&"Release".to_string()));
assert!(tags.contains(&"ReleaseList".to_string()));
assert!(tags.contains(&"NewReleaseMessage".to_string()));
}
other => panic!("Expected UnclosedTags error, got: {:?}", other),
}
}
#[test]
fn test_invalid_element_name() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG004</ern:MessageId>
<123InvalidName>Invalid</123InvalidName>
</ern:MessageHeader>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
match result {
Err(ParseError::MalformedXml { message, .. }) => {
assert!(message.contains("Invalid element name"));
assert!(message.contains("123InvalidName"));
}
other => panic!("Expected MalformedXml error, got: {:?}", other),
}
}
#[test]
fn test_duplicate_attributes() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId id="first" id="second">MSG005</ern:MessageId>
</ern:MessageHeader>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
match result {
Err(ParseError::InvalidAttribute { message, .. }) => {
assert!(message.contains("Duplicate attribute"));
assert!(message.contains("id"));
}
other => panic!("Expected InvalidAttribute error, got: {:?}", other),
}
}
#[test]
fn test_invalid_attribute_characters() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId value="test < invalid">MSG006</ern:MessageId>
</ern:MessageHeader>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
match result {
Err(ParseError::InvalidAttribute { message, .. }) => {
assert!(message.contains("Invalid character in attribute value"));
}
other => panic!("Expected InvalidAttribute error, got: {:?}", other),
}
}
#[test]
fn test_malformed_cdata() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG007</ern:MessageId>
<ern:Description><![CDATA[This contains ]]> in the middle]]></ern:Description>
</ern:MessageHeader>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
match result {
Err(ParseError::MalformedXml { message, .. }) => {
assert!(message.contains("CDATA section contains ']]>' in the middle"));
}
other => panic!("Expected MalformedXml error, got: {:?}", other),
}
}
#[test]
fn test_empty_element_name() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG008</ern:MessageId>
<>Empty</>
</ern:MessageHeader>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
match result {
Err(ParseError::XmlError { .. }) | Err(ParseError::MalformedXml { .. }) => {
}
other => panic!(
"Expected parsing error for empty element name, got: {:?}",
other
),
}
}
#[test]
fn test_nested_elements_depth_tracking() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG009</ern:MessageId>
<ern:MessageSender>
<ern:PartyId>SENDER009</ern:PartyId>
</ern:MessageSender>
<ern:MessageRecipient>
<ern:PartyId>RECIPIENT009</ern:PartyId>
</ern:MessageRecipient>
</ern:MessageHeader>
<ern:ReleaseList>
<ern:Release>
<ern:ReleaseId>REL009</ern:ReleaseId>
<ern:ReleaseReference>R009</ern:ReleaseReference>
<ern:Title>
<ern:TitleText>Valid Nested Structure</ern:TitleText>
</ern:Title>
</ern:Release>
</ern:ReleaseList>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
assert!(
result.is_ok(),
"Well-formed nested XML should parse successfully"
);
}
#[test]
fn test_xml_with_comments_and_processing_instructions() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<!-- This is a comment -->
<?processing-instruction data?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<!-- Another comment -->
<ern:MessageId>MSG010</ern:MessageId>
<ern:MessageSender>
<ern:PartyId>SENDER010</ern:PartyId>
</ern:MessageSender>
<ern:MessageRecipient>
<ern:PartyId>RECIPIENT010</ern:PartyId>
</ern:MessageRecipient>
</ern:MessageHeader>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
assert!(
result.is_ok(),
"XML with comments and processing instructions should parse successfully"
);
}
#[test]
fn test_self_closing_elements() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG011</ern:MessageId>
<ern:MessageSender/>
<ern:MessageRecipient>
<ern:PartyId>RECIPIENT011</ern:PartyId>
</ern:MessageRecipient>
</ern:MessageHeader>
<ern:ReleaseList/>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
assert!(
result.is_ok(),
"XML with self-closing elements should parse successfully"
);
}
#[test]
fn test_complex_malformed_structure() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG012</ern:MessageId>
<ern:MessageSender>
<ern:PartyId>SENDER012</ern:PartyId>
</ern:MessageRecipient> <!-- Wrong closing tag -->
<ern:MessageRecipient>
<ern:PartyId>RECIPIENT012</ern:PartyId>
</ern:MessageSender> <!-- Wrong closing tag -->
</ern:MessageHeader>
</ern:NewReleaseMessage>"#;
let mut parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = parser.parse(cursor);
match result {
Err(ParseError::MismatchedTags {
expected, found, ..
}) => {
assert_eq!(expected, "MessageSender");
assert_eq!(found, "MessageRecipient");
}
other => panic!("Expected MismatchedTags error, got: {:?}", other),
}
}
#[test]
fn test_strict_vs_lenient_validation() {
let xml = r#"<?xml version="1.0" encoding="UTF-8"?>
<ern:NewReleaseMessage xmlns:ern="http://ddex.net/xml/ern/43">
<ern:MessageHeader>
<ern:MessageId>MSG013</ern:MessageId>
<ern:MessageSender>
<ern:PartyId>SENDER013</ern:PartyId>
</ern:MessageSender>
</ern:MessageHeader>
</ern:NewReleaseMessage>"#;
let mut strict_parser = DDEXParser::with_config(SecurityConfig::strict());
let cursor = Cursor::new(xml.as_bytes());
let result = strict_parser.parse(cursor);
assert!(
result.is_ok(),
"Well-formed XML should pass strict validation"
);
let mut default_parser = DDEXParser::new();
let cursor = Cursor::new(xml.as_bytes());
let result = default_parser.parse(cursor);
assert!(
result.is_ok(),
"Well-formed XML should pass default validation"
);
}