#[cfg(test)]
mod tests {
#[test]
fn test_4h7k_extra_closing_bracket_in_flow_sequence() {
let yaml = b"[ a, b, c ] ]\n";
let mut source = BufferSource::new(yaml);
let res = parse(&mut source);
assert!(
res.is_err(),
"4H7K: Should error on extra closing bracket in flow sequence"
);
let err = res.unwrap_err().to_string();
assert!(
err.contains("Unexpected") || err.contains("]") || err.contains("bracket"),
"4H7K error message should mention unexpected bracket, got: {}",
err
);
}
use crate::test_helpers::{assert_parse_error, parse_yaml};
use crate::{BufferSource, Node, parse};
#[test]
fn test_error_on_empty_alias_name() {
use crate::error::messages::ERR_EMPTY_ALIAS_NAME;
let yaml = "---\nvalue: *\n";
assert_parse_error(yaml, ERR_EMPTY_ALIAS_NAME);
}
#[test]
fn test_error_on_empty_anchor_name() {
use crate::error::messages::ERR_EMPTY_ANCHOR_NAME;
let yaml = "---\nroot: &\n nested: 1\n";
assert_parse_error(yaml, ERR_EMPTY_ANCHOR_NAME);
}
#[test]
fn test_error_on_duplicate_anchor() {
let yaml = "---\na: &dup\n x: 1\nb: &dup\n y: 2\nc: *dup\n";
let doc = parse_yaml(yaml);
if let Node::Documents(docs) = &doc {
assert!(!docs.is_empty());
}
}
#[test]
fn test_error_on_unterminated_double_quote() {
let yaml = "---\nkey: \"unterminated string";
assert_parse_error(yaml, "Unterminated");
}
#[test]
fn test_error_on_unterminated_single_quote() {
let yaml = "---\nkey: 'unterminated string";
assert_parse_error(yaml, "Unterminated");
}
#[test]
fn test_error_on_invalid_escape_sequence() {
let yaml = "---\nkey: \"";
assert_parse_error(yaml, "Syntax error");
}
#[test]
fn test_error_on_malformed_mapping() {
let yaml = "---\n{key: value";
assert_parse_error(yaml, "Syntax error");
}
#[test]
fn test_error_on_invalid_sequence_item() {
let yaml = "---\n- item1\ninvalid item without dash";
let doc = parse_yaml(yaml);
if let Node::Documents(docs) = doc {
if let Some(Node::Document(items)) = docs.first() {
if let Some(Node::Array(arr)) = items.first() {
assert_eq!(arr.len(), 1, "Should have one sequence item");
if let Some(Node::Str(value, _, _)) = arr.first() {
assert!(value.contains("item1"));
}
}
}
}
}
#[test]
fn test_error_on_invalid_flow_mapping() {
let mut source = BufferSource::new(b"---\n{key: value, invalid:");
let res = parse(&mut source);
assert!(res.is_err());
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("Unterminated")
|| err_str.contains("Expected")
|| err_str.contains("Unexpected")
|| err_str.contains("EOF")
);
}
#[test]
fn test_error_on_invalid_flow_sequence() {
let mut source = BufferSource::new(b"---\n[item1, item2");
let res = parse(&mut source);
assert!(res.is_err());
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Expected") || err_str.contains("Unexpected"));
}
#[test]
fn test_error_on_unclosed_flow_mapping() {
let yaml = "---\n{key: value, invalid:";
assert_parse_error(yaml, "Syntax error");
}
#[test]
fn test_error_on_incomplete_flow_sequence() {
let mut source = BufferSource::new(b"---\n[item1, item2, incomplete");
let res = parse(&mut source);
assert!(res.is_err());
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Expected") || err_str.contains("Unexpected"));
}
#[test]
fn test_error_on_invalid_tag() {
let mut source = BufferSource::new(b"---\n!!invalid-tag-name value");
let res = parse(&mut source);
assert!(
res.is_ok(),
"Unknown tags should be preserved, not cause errors"
);
if let Ok(Node::Documents(docs)) = res {
if let Node::Document(nodes) = &docs[0] {
if let Node::Tagged(_, tag) = &nodes[0] {
assert_eq!(tag, "tag:yaml.org,2002:invalid-tag-name");
}
}
}
}
#[test]
fn test_parser_handles_unicode_escape_attempts() {
let mut source = BufferSource::new(b"---\nkey: \"\\u\"");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("Invalid")
|| err_str.contains("Unexpected")
|| err_str.contains("Expected")
);
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_error_on_incomplete_unicode_escape() {
let mut source = BufferSource::new(b"---\nkey: \"text\\u");
let res = parse(&mut source);
assert!(res.is_err());
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("Invalid")
|| err_str.contains("Expected")
|| err_str.contains("Unexpected")
|| err_str.contains("Unterminated")
|| err_str.contains("Unclosed")
);
}
#[test]
fn test_parser_handles_numeric_like_strings() {
let mut source = BufferSource::new(b"---\nvalue: 123.45.67");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Invalid") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_parser_handles_invalid_binary_as_string() {
let mut source = BufferSource::new(b"---\nvalue: 0b123");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Invalid") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_parser_handles_invalid_octal_as_string() {
let mut source = BufferSource::new(b"---\nvalue: 0o89");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Invalid") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_parser_handles_invalid_hex_as_string() {
let mut source = BufferSource::new(b"---\nvalue: 0xGHI");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Invalid") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_error_on_recursive_alias() {
let mut source = BufferSource::new(b"---\nanchor: &self\n recursive: *self");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("recursive")
|| err_str.contains("Undefined")
|| err_str.contains("Invalid")
);
}
}
#[test]
fn test_parser_handles_nested_content_variations() {
let mut source = BufferSource::new(b"---\nparent:\n child1\n child2: value");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Expected") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_parser_handles_mixed_whitespace() {
let mut source = BufferSource::new(b"---\nkey1:\n\tvalue1\n key2:\n\t value2");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("tab")
|| err_str.contains("indentation")
|| err_str.contains("Unexpected")
);
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_parser_handles_block_scalar_indentation() {
let mut source = BufferSource::new(b"---\nkey: |\n line1\n line2");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("indentation")
|| err_str.contains("Expected")
|| err_str.contains("Unexpected")
);
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_parser_handles_folded_block_indentation() {
let mut source = BufferSource::new(b"---\nkey: >\n line1\n line2");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("indentation")
|| err_str.contains("Expected")
|| err_str.contains("Unexpected")
);
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_error_on_empty_document_with_invalid_content() {
let mut source = BufferSource::new(b"---\n{");
let res = parse(&mut source);
assert!(res.is_err());
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Expected") || err_str.contains("Unexpected"));
}
#[test]
fn test_parser_handles_anchor_characters() {
let mut source = BufferSource::new(b"---\nvalue: &invalid-char@name test");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Invalid") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_parser_handles_multi_document_content() {
let mut source = BufferSource::new(b"---\nvalid: document\n---\ninvalid syntax here");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Expected") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_parser_handles_comment_after_colon() {
let mut source = BufferSource::new(b"---\nkey: # comment with no value");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Expected") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_error_on_extremely_nested_structure() {
let mut yaml = String::from("---\n");
for i in 0..1000 {
yaml.push_str(&format!("level{}: \n", i));
yaml.push_str(" ");
}
yaml.push_str("value: deep");
let mut source = BufferSource::new(yaml.as_bytes());
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(!err_str.is_empty());
}
}
#[test]
fn test_error_on_duplicate_keys_in_mapping() {
let mut source = BufferSource::new(b"---\nkey: value1\nkey: value2");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("duplicate") || err_str.contains("Duplicate"));
}
}
#[test]
fn test_parser_handles_control_characters() {
let mut source = BufferSource::new(b"---\nkey: \x00invalid");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Invalid") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_parser_handles_sequence_mapping_variations() {
let mut source = BufferSource::new(b"---\n- key1: value1\n- key2");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Expected") || err_str.contains("Unexpected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_error_on_invalid_yaml_version() {
let mut source = BufferSource::new(b"%YAML 2.0\n---\nkey: value");
let res = parse(&mut source);
assert!(res.is_err());
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Unexpected") || err_str.contains("Invalid"));
}
#[test]
fn test_error_on_malformed_tag_directive() {
let mut source = BufferSource::new(b"%TAG\n---\nkey: value");
let res = parse(&mut source);
assert!(res.is_err());
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("Malformed %TAG directive")
|| err_str.contains("YAML compliance error")
);
}
#[test]
fn test_parser_handles_document_marker_variations() {
let mut source = BufferSource::new(b"---invalid\nkey: value");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(err_str.contains("Unexpected") || err_str.contains("Expected"));
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_error_on_unexpected_closing_flow_sequence_after_document() {
let mut source = BufferSource::new(b"---\nkey: value\n]\n");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("Unexpected")
|| err_str.contains("closing")
|| err_str.contains("bracket"),
"Error message for stray ']' should mention it being unexpected or a bracket issue, got: {}",
err_str
);
} else {
assert!(res.is_ok());
}
}
#[test]
fn test_error_on_unexpected_closing_flow_mapping_after_document() {
let mut source = BufferSource::new(b"---\nkey: value\n}\n");
let res = parse(&mut source);
if res.is_err() {
let err = res.unwrap_err();
let err_str = err.to_string();
assert!(
err_str.contains("Unexpected")
|| err_str.contains("closing")
|| err_str.contains("brace"),
"Error message for stray closing brace should mention it being unexpected or a brace issue, got: {}",
err_str
);
} else {
assert!(res.is_ok());
}
}
}