#![allow(clippy::bool_assert_comparison)]
#![allow(clippy::float_cmp)]
use std::vec;
use yaml_rust2::{Yaml, YamlEmitter, YamlLoader};
#[test]
fn test_api() {
let s =
"
# from yaml-cpp example
- name: Ogre
position: [
0,
5,
0]
powers:
- name: Club
damage:
10
- name: Fist
damage:
8
- name: Dragon
position: [
1,
0,
10]
powers:
- name: Fire Breath
damage:
25
- name: Claws
damage:
15
- name: Wizard
position: [
5, -
3,
0]
powers:
- name: Acid Rain
damage:
50
- name: Staff
damage:
3
";
let docs = YamlLoader::load_from_str(s).unwrap();
let doc = &docs[
0];
assert_eq!(doc[
0][
"name"].as_str().unwrap(),
"Ogre");
let mut writer = String::new();
{
let mut emitter = YamlEmitter::new(&
mut writer);
emitter.dump(doc).unwrap();
}
assert!(!writer.is_empty());
}
#[test]
fn test_fail() {
let s =
"
# syntax error
scalar
key: [
1,
2]]
key1:a2
";
let Err(error) = YamlLoader::load_from_str(s)
else {
panic!()
};
assert_eq!(
error.info(),
"mapping values are not allowed in this context"
);
assert_eq!(
error.to_string(),
"mapping values are not allowed in this context at byte 26 line 4 column 4"
);
}
#[test]
fn test_coerce() {
let s =
"---
a:
1
b:
2.
2
c: [
1,
2]
";
let out = YamlLoader::load_from_str(s).unwrap();
let doc = &out[
0];
assert_eq!(doc[
"a"].as_i64().unwrap(),
1i64);
assert_eq!(doc[
"b"].as_f64().unwrap(),
2.
2f64);
assert_eq!(doc[
"c"][
1].as_i64().unwrap(),
2i64);
assert!(doc[
"d"][
0].is_badvalue());
}
#[test]
fn test_empty_doc() {
let s: String = String::new();
YamlLoader::load_from_str(&s).unwrap();
let s: String =
"---".to_owned();
assert_eq!(YamlLoader::load_from_str(&s).unwrap()[
0], Yaml::Null);
}
#[test]
fn test_parser() {
let s: String =
"
# comment
a0 bb: val
a1:
b1:
4
b2: d
a2:
4 # i
'm comment
a3: [
1,
2,
3]
a4:
- - a1
- a2
-
2
a5:
'single_quoted'
a6: \
"double_quoted\"
a7: 你好
"
.to_owned();
let out = YamlLoader::load_from_str(&s).unwrap();
let doc = &out[
0];
assert_eq!(doc[
"a7"].as_str().unwrap(),
"你好");
}
#[test]
fn test_multi_doc() {
let s =
"
'a scalar'
---
'a scalar'
---
'a scalar'
";
let out = YamlLoader::load_from_str(s).unwrap();
assert_eq!(out.len(),
3);
}
#[test]
fn test_anchor() {
let s =
"
a1: &DEFAULT
b1:
4
b2: d
a2: *DEFAULT
";
let out = YamlLoader::load_from_str(s).unwrap();
let doc = &out[
0];
assert_eq!(doc[
"a2"][
"b1"].as_i64().unwrap(),
4);
}
#[test]
fn test_bad_anchor() {
let s =
"
a1: &DEFAULT
b1:
4
b2: *DEFAULT
";
let out = YamlLoader::load_from_str(s).unwrap();
let doc = &out[
0];
assert_eq!(doc[
"a1"][
"b2"], Yaml::BadValue);
}
#[test]
fn test_github_27() {
// https://github.com/chyh1990/yaml-rust/issues/27
let s =
"&a";
let out = YamlLoader::load_from_str(s).unwrap();
let doc = &out[
0];
assert_eq!(*doc, Yaml::Null);
}
#[test]
fn test_plain_datatype() {
let s =
"
-
'string'
- \
"string\"
- string
-
123
- -
321
-
1.
23
- -
1e4
- ~
- null
-
true
-
false
- !!str
0
- !!int
100
- !!float
2
- !!null ~
- !!bool
true
- !!bool
false
-
0xFF
# bad values
- !!int string
- !!float string
- !!bool null
- !!null val
-
0o77
- [
0xF,
0xF ]
- +
12345
- [
true,
false ]
";
let out = YamlLoader::load_from_str(s).unwrap();
let doc = &out[
0];
assert_eq!(doc[
0].as_str().unwrap(),
"string");
assert_eq!(doc[
1].as_str().unwrap(),
"string");
assert_eq!(doc[
2].as_str().unwrap(),
"string");
assert_eq!(doc[
3].as_i64().unwrap(),
123);
assert_eq!(doc[
4].as_i64().unwrap(), -
321);
assert_eq!(doc[
5].as_f64().unwrap(),
1.
23);
assert_eq!(doc[
6].as_f64().unwrap(), -
1e4);
assert!(doc[
7].is_null());
assert!(doc[
8].is_null());
assert_eq!(doc[
9].as_bool().unwrap(),
true);
assert_eq!(doc[
10].as_bool().unwrap(),
false);
assert_eq!(doc[
11].as_str().unwrap(),
"0");
assert_eq!(doc[
12].as_i64().unwrap(),
100);
assert_eq!(doc[
13].as_f64().unwrap(),
2.
0);
assert!(doc[
14].is_null());
assert_eq!(doc[
15].as_bool().unwrap(),
true);
assert_eq!(doc[
16].as_bool().unwrap(),
false);
assert_eq!(doc[
17].as_i64().unwrap(),
255);
assert!(doc[
18].is_badvalue());
assert!(doc[
19].is_badvalue());
assert!(doc[
20].is_badvalue());
assert!(doc[
21].is_badvalue());
assert_eq!(doc[
22].as_i64().unwrap(),
63);
assert_eq!(doc[
23][
0].as_i64().unwrap(),
15);
assert_eq!(doc[
23][
1].as_i64().unwrap(),
15);
assert_eq!(doc[
24].as_i64().unwrap(),
12345);
assert!(doc[
25][
0].as_bool().unwrap());
assert!(!doc[
25][
1].as_bool().unwrap());
}
#[test]
fn test_bad_hyphen() {
// See: https://github.com/chyh1990/yaml-rust/issues/23
let s =
"{-";
assert!(YamlLoader::load_from_str(s).is_err());
}
#[test]
fn test_issue_65() {
// See: https://github.com/chyh1990/yaml-rust/issues/65
let b =
"\n\"ll\\\
"ll\\\r\n\"ll\\\
"ll\\\r\r\r\rU\r\r\rU";
assert!(YamlLoader::load_from_str(b).is_err());
}
#[test]
fn test_issue_65_mwe() {
// A MWE for `test_issue_65`. The error over there is that there is invalid trailing content
// after a double quoted string.
let b = r
#""foo" l
"#;
assert!(YamlLoader::load_from_str(b).is_err());
}
#[test]
fn test_comment_after_tag() {
// https://github.com/Ethiraric/yaml-rust2/issues/21#issuecomment-2053513507
let s =
"
%YAML
1.
2
# This is a comment
---
#-------
foobar
";
assert_eq!(
YamlLoader::load_from_str(s),
Ok(vec![Yaml::String(String::from(
"foobar"))])
);
}
#[test]
fn test_large_block_scalar_indent() {
// https://github.com/Ethiraric/yaml-rust2/issues/29
// Tests the `loop` fallback of `skip_block_scalar_indent`. The indent in the YAML string must
// be greater than `BUFFER_LEN - 2`. The second line is further indented with spaces, and the
// resulting string should be "a\n b".
let s =
"
a: |-
a
b
";
let doc = &YamlLoader::load_from_str(s).unwrap()[
0];
let Yaml::Hash(map) = doc
else {
dbg!(doc);
panic!()
};
assert_eq!(map.len(),
1);
assert_eq!(
map.get(&Yaml::String(
"a".to_string())),
Some(&Yaml::String(String::from(
"a\n b")))
);
}
#[test]
fn test_bad_docstart() {
assert!(YamlLoader::load_from_str(
"---This used to cause an infinite loop").is_ok());
assert_eq!(
YamlLoader::load_from_str(
"----"),
Ok(vec![Yaml::String(String::from(
"----"))])
);
assert_eq!(
YamlLoader::load_from_str(
"--- #here goes a comment"),
Ok(vec![Yaml::Null])
);
assert_eq!(
YamlLoader::load_from_str(
"---- #here goes a comment"),
Ok(vec![Yaml::String(String::from(
"----"))])
);
}
#[test]
fn test_plain_datatype_with_into_methods() {
let s =
"
-
'string'
- \
"string\"
- string
-
123
- -
321
-
1.
23
- -
1e4
-
true
-
false
- !!str
0
- !!int
100
- !!float
2
- !!bool
true
- !!bool
false
-
0xFF
-
0o77
- +
12345
- -.INF
- .NAN
- !!float .INF
";
let mut out = YamlLoader::load_from_str(s).unwrap().into_iter();
let mut doc = out.next().unwrap().into_iter();
assert_eq!(doc.next().unwrap().into_string().unwrap(),
"string");
assert_eq!(doc.next().unwrap().into_string().unwrap(),
"string");
assert_eq!(doc.next().unwrap().into_string().unwrap(),
"string");
assert_eq!(doc.next().unwrap().into_i64().unwrap(),
123);
assert_eq!(doc.next().unwrap().into_i64().unwrap(), -
321);
assert_eq!(doc.next().unwrap().into_f64().unwrap(),
1.
23);
assert_eq!(doc.next().unwrap().into_f64().unwrap(), -
1e4);
assert_eq!(doc.next().unwrap().into_bool().unwrap(),
true);
assert_eq!(doc.next().unwrap().into_bool().unwrap(),
false);
assert_eq!(doc.next().unwrap().into_string().unwrap(),
"0");
assert_eq!(doc.next().unwrap().into_i64().unwrap(),
100);
assert_eq!(doc.next().unwrap().into_f64().unwrap(),
2.
0);
assert_eq!(doc.next().unwrap().into_bool().unwrap(),
true);
assert_eq!(doc.next().unwrap().into_bool().unwrap(),
false);
assert_eq!(doc.next().unwrap().into_i64().unwrap(),
255);
assert_eq!(doc.next().unwrap().into_i64().unwrap(),
63);
assert_eq!(doc.next().unwrap().into_i64().unwrap(),
12345);
assert_eq!(doc.next().unwrap().into_f64().unwrap(), f64::NEG_INFINITY);
assert!(doc.next().unwrap().into_f64().is_some());
assert_eq!(doc.next().unwrap().into_f64().unwrap(), f64::INFINITY);
}
#[test]
fn test_hash_order() {
let s =
"---
b: ~
a: ~
c: ~
";
let out = YamlLoader::load_from_str(s).unwrap();
let first = out.into_iter().next().unwrap();
let mut iter = first.into_hash().unwrap().into_iter();
assert_eq!(
Some((Yaml::String(
"b".to_owned()), Yaml::Null)),
iter.next()
);
assert_eq!(
Some((Yaml::String(
"a".to_owned()), Yaml::Null)),
iter.next()
);
assert_eq!(
Some((Yaml::String(
"c".to_owned()), Yaml::Null)),
iter.next()
);
assert_eq!(None, iter.next());
}
#[test]
fn test_integer_key() {
let s =
"
0:
important:
true
1:
important:
false
";
let out = YamlLoader::load_from_str(s).unwrap();
let first = out.into_iter().next().unwrap();
assert_eq!(first[
0][
"important"].as_bool().unwrap(),
true);
}
#[test]
fn test_indentation_equality() {
let four_spaces = YamlLoader::load_from_str(
r
"
hash:
with:
indentations
",
)
.unwrap()
.into_iter()
.next()
.unwrap();
let two_spaces = YamlLoader::load_from_str(
r
"
hash:
with:
indentations
",
)
.unwrap()
.into_iter()
.next()
.unwrap();
let one_space = YamlLoader::load_from_str(
r
"
hash:
with:
indentations
",
)
.unwrap()
.into_iter()
.next()
.unwrap();
let mixed_spaces = YamlLoader::load_from_str(
r
"
hash:
with:
indentations
",
)
.unwrap()
.into_iter()
.next()
.unwrap();
assert_eq!(four_spaces, two_spaces);
assert_eq!(two_spaces, one_space);
assert_eq!(four_spaces, mixed_spaces);
}
#[test]
fn test_two_space_indentations() {
// https://github.com/kbknapp/clap-rs/issues/965
let s = r
"
subcommands:
- server:
about: server related commands
subcommands2:
- server:
about: server related commands
subcommands3:
- server:
about: server related commands
";
let out = YamlLoader::load_from_str(s).unwrap();
let doc = &out.into_iter().next().unwrap();
println!(
"{doc:#?}");
assert_eq!(doc[
"subcommands"][
0][
"server"], Yaml::Null);
assert!(doc[
"subcommands2"][
0][
"server"].as_hash().is_some());
assert!(doc[
"subcommands3"][
0][
"server"].as_hash().is_some());
}
#[test]
fn test_recursion_depth_check_objects() {
let s =
"{a:".repeat(
10_
000) + &
"}".repeat(
10_
000);
assert!(YamlLoader::load_from_str(&s).is_err());
}
#[test]
fn test_recursion_depth_check_arrays() {
let s =
"[".repeat(
10_
000) + &
"]".repeat(
10_
000);
assert!(YamlLoader::load_from_str(&s).is_err());
}
#[test]
fn test_mapping_duplicates() {
let s = r
"
a: foo
a: bar
";
assert!(YamlLoader::load_from_str(s).is_err());
}
#[test]
fn test_nominal_float_parse() {
use std::fmt::Write;
// back test for
// https://github.com/Ethiraric/yaml-rust2/issues/50
// Test cases derived from https://doc.rust-lang.org/std/primitive.f64.html#impl-FromStr-for-f64
// Generates a document that looks like so:
// ```yaml
// - +nan
// - -nan
// - nan
// - +NAN
// ```
// Every single one of these values should be parsed as a string in yaml,
// but would be parsed as a float according to rust. This test verifies they
// all end up parsed as strings.
let raw = &[
"nan",
"NAN",
"NaN",
"inf",
"infinity",
"Infinity"]
.iter()
.fold(String::new(), |
mut output, base| {
let _ = write!(output,
"- +{base}\n- -{base}\n- {base}\n");
output
});
println!(
"parsing {raw}");
let doc = YamlLoader::load_from_str(raw).expect(
"could not parse document");
let doc = doc.into_iter().next().unwrap();
assert!(doc.is_array());
for it
in doc {
assert!(it.as_str().is_some());
}
}