Move emitter/scanner tests to their folder.
Change scanner's complex test: ```diff - *coffee: + *coffee : amount: 4 - *cookies: + *cookies : amount: 4 ``` According to https://play.yaml.io/main/parser, this example was invalid in the first place. Adding a space makes it so that the colon is not part of the alias name. Also fix colons not being able to be part of anchors.
This commit is contained in:
parent
fb8ef31546
commit
8c4ea2c838
5 changed files with 737 additions and 747 deletions
|
@ -334,302 +334,3 @@ fn need_quotes(string: &str) -> bool {
|
|||
|| string.parse::<i64>().is_ok()
|
||||
|| string.parse::<f64>().is_ok()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::similar_names)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::YamlLoader;
|
||||
|
||||
#[test]
|
||||
fn test_emit_simple() {
|
||||
let s = "
|
||||
# comment
|
||||
a0 bb: val
|
||||
a1:
|
||||
b1: 4
|
||||
b2: d
|
||||
a2: 4 # i'm comment
|
||||
a3: [1, 2, 3]
|
||||
a4:
|
||||
- [a1, a2]
|
||||
- 2
|
||||
";
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
println!("original:\n{s}");
|
||||
println!("emitted:\n{writer}");
|
||||
let docs_new = match YamlLoader::load_from_str(&writer) {
|
||||
Ok(y) => y,
|
||||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
let doc_new = &docs_new[0];
|
||||
|
||||
assert_eq!(doc, doc_new);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_emit_complex() {
|
||||
let s = r#"
|
||||
cataloge:
|
||||
product: &coffee { name: Coffee, price: 2.5 , unit: 1l }
|
||||
product: &cookies { name: Cookies!, price: 3.40 , unit: 400g}
|
||||
|
||||
products:
|
||||
*coffee:
|
||||
amount: 4
|
||||
*cookies:
|
||||
amount: 4
|
||||
[1,2,3,4]:
|
||||
array key
|
||||
2.4:
|
||||
real key
|
||||
true:
|
||||
bool key
|
||||
{}:
|
||||
empty hash key
|
||||
"#;
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
let docs_new = match YamlLoader::load_from_str(&writer) {
|
||||
Ok(y) => y,
|
||||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
let doc_new = &docs_new[0];
|
||||
assert_eq!(doc, doc_new);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_emit_avoid_quotes() {
|
||||
let s = r#"---
|
||||
a7: 你好
|
||||
boolean: "true"
|
||||
boolean2: "false"
|
||||
date: 2014-12-31
|
||||
empty_string: ""
|
||||
empty_string1: " "
|
||||
empty_string2: " a"
|
||||
empty_string3: " a "
|
||||
exp: "12e7"
|
||||
field: ":"
|
||||
field2: "{"
|
||||
field3: "\\"
|
||||
field4: "\n"
|
||||
field5: "can't avoid quote"
|
||||
float: "2.6"
|
||||
int: "4"
|
||||
nullable: "null"
|
||||
nullable2: "~"
|
||||
products:
|
||||
"*coffee":
|
||||
amount: 4
|
||||
"*cookies":
|
||||
amount: 4
|
||||
".milk":
|
||||
amount: 1
|
||||
"2.4": real key
|
||||
"[1,2,3,4]": array key
|
||||
"true": bool key
|
||||
"{}": empty hash key
|
||||
x: test
|
||||
y: avoid quoting here
|
||||
z: string with spaces"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(s, writer, "actual:\n\n{writer}\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emit_quoted_bools() {
|
||||
let input = r#"---
|
||||
string0: yes
|
||||
string1: no
|
||||
string2: "true"
|
||||
string3: "false"
|
||||
string4: "~"
|
||||
null0: ~
|
||||
[true, false]: real_bools
|
||||
[True, TRUE, False, FALSE, y,Y,yes,Yes,YES,n,N,no,No,NO,on,On,ON,off,Off,OFF]: false_bools
|
||||
bool0: true
|
||||
bool1: false"#;
|
||||
let expected = r#"---
|
||||
string0: "yes"
|
||||
string1: "no"
|
||||
string2: "true"
|
||||
string3: "false"
|
||||
string4: "~"
|
||||
null0: ~
|
||||
? - true
|
||||
- false
|
||||
: real_bools
|
||||
? - "True"
|
||||
- "TRUE"
|
||||
- "False"
|
||||
- "FALSE"
|
||||
- y
|
||||
- Y
|
||||
- "yes"
|
||||
- "Yes"
|
||||
- "YES"
|
||||
- n
|
||||
- N
|
||||
- "no"
|
||||
- "No"
|
||||
- "NO"
|
||||
- "on"
|
||||
- "On"
|
||||
- "ON"
|
||||
- "off"
|
||||
- "Off"
|
||||
- "OFF"
|
||||
: false_bools
|
||||
bool0: true
|
||||
bool1: false"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(input).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
expected, writer,
|
||||
"expected:\n{expected}\nactual:\n{writer}\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_and_nested() {
|
||||
test_empty_and_nested_flag(false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_and_nested_compact() {
|
||||
test_empty_and_nested_flag(true);
|
||||
}
|
||||
|
||||
fn test_empty_and_nested_flag(compact: bool) {
|
||||
let s = if compact {
|
||||
r#"---
|
||||
a:
|
||||
b:
|
||||
c: hello
|
||||
d: {}
|
||||
e:
|
||||
- f
|
||||
- g
|
||||
- h: []"#
|
||||
} else {
|
||||
r#"---
|
||||
a:
|
||||
b:
|
||||
c: hello
|
||||
d: {}
|
||||
e:
|
||||
- f
|
||||
- g
|
||||
-
|
||||
h: []"#
|
||||
};
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.compact(compact);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(s, writer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_arrays() {
|
||||
let s = r#"---
|
||||
a:
|
||||
- b
|
||||
- - c
|
||||
- d
|
||||
- - e
|
||||
- f"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
println!("original:\n{s}");
|
||||
println!("emitted:\n{writer}");
|
||||
|
||||
assert_eq!(s, writer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deeply_nested_arrays() {
|
||||
let s = r#"---
|
||||
a:
|
||||
- b
|
||||
- - c
|
||||
- d
|
||||
- - e
|
||||
- - f
|
||||
- - e"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
println!("original:\n{s}");
|
||||
println!("emitted:\n{writer}");
|
||||
|
||||
assert_eq!(s, writer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_hashes() {
|
||||
let s = r#"---
|
||||
a:
|
||||
b:
|
||||
c:
|
||||
d:
|
||||
e: f"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
println!("original:\n{s}");
|
||||
println!("emitted:\n{writer}");
|
||||
|
||||
assert_eq!(s, writer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -951,7 +951,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
|
|||
|
||||
self.skip();
|
||||
self.lookahead(1);
|
||||
while is_alpha(self.ch()) {
|
||||
while is_alpha(self.ch()) || self.ch_is(':') {
|
||||
string.push(self.ch());
|
||||
self.skip();
|
||||
self.lookahead(1);
|
||||
|
@ -960,7 +960,7 @@ impl<T: Iterator<Item = char>> Scanner<T> {
|
|||
if string.is_empty()
|
||||
|| match self.ch() {
|
||||
c if is_blankz(c) => false,
|
||||
'?' | ':' | ',' | ']' | '}' | '%' | '@' | '`' => false,
|
||||
'?' | ',' | ']' | '}' | '%' | '@' | '`' => false,
|
||||
_ => true,
|
||||
}
|
||||
{
|
||||
|
@ -1747,447 +1747,3 @@ impl<T: Iterator<Item = char>> Scanner<T> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::enum_glob_use)]
|
||||
mod test {
|
||||
use super::TokenType::*;
|
||||
use super::*;
|
||||
|
||||
macro_rules! next {
|
||||
($p:ident, $tk:pat) => {{
|
||||
let tok = $p.next().unwrap();
|
||||
match tok.1 {
|
||||
$tk => {}
|
||||
_ => panic!("unexpected token: {:?}", tok),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! next_scalar {
|
||||
($p:ident, $tk:expr, $v:expr) => {{
|
||||
let tok = $p.next().unwrap();
|
||||
match tok.1 {
|
||||
Scalar(style, ref v) => {
|
||||
assert_eq!(style, $tk);
|
||||
assert_eq!(v, $v);
|
||||
}
|
||||
_ => panic!("unexpected token: {:?}", tok),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! end {
|
||||
($p:ident) => {{
|
||||
assert_eq!($p.next(), None);
|
||||
}};
|
||||
}
|
||||
/// test cases in libyaml scanner.c
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
let s = "";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scalar() {
|
||||
let s = "a scalar";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_explicit_scalar() {
|
||||
let s = "---
|
||||
'a scalar'
|
||||
...
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, DocumentStart);
|
||||
next!(p, Scalar(TScalarStyle::SingleQuoted, _));
|
||||
next!(p, DocumentEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_documents() {
|
||||
let s = "
|
||||
'a scalar'
|
||||
---
|
||||
'a scalar'
|
||||
---
|
||||
'a scalar'
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, Scalar(TScalarStyle::SingleQuoted, _));
|
||||
next!(p, DocumentStart);
|
||||
next!(p, Scalar(TScalarStyle::SingleQuoted, _));
|
||||
next!(p, DocumentStart);
|
||||
next!(p, Scalar(TScalarStyle::SingleQuoted, _));
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_a_flow_sequence() {
|
||||
let s = "[item 1, item 2, item 3]";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowSequenceStart);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, FlowEntry);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, FlowEntry);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, FlowSequenceEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_a_flow_mapping() {
|
||||
let s = "
|
||||
{
|
||||
a simple key: a value, # Note that the KEY token is produced.
|
||||
? a complex key: another value,
|
||||
}
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowMappingStart);
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, FlowEntry);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a complex key");
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, FlowEntry);
|
||||
next!(p, FlowMappingEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_block_sequences() {
|
||||
let s = "
|
||||
- item 1
|
||||
- item 2
|
||||
-
|
||||
- item 3.1
|
||||
- item 3.2
|
||||
-
|
||||
key 1: value 1
|
||||
key 2: value 2
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 2");
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 3.1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 3.2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 1");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 1");
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 2");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_block_mappings() {
|
||||
let s = "
|
||||
a simple key: a value # The KEY token is produced here.
|
||||
? a complex key
|
||||
: another value
|
||||
a mapping:
|
||||
key 1: value 1
|
||||
key 2: value 2
|
||||
a sequence:
|
||||
- item 1
|
||||
- item 2
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value); // libyaml comment seems to be wrong
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, BlockEnd);
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, BlockEntry);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_block_sequence_start() {
|
||||
let s = "
|
||||
key:
|
||||
- item 1
|
||||
- item 2
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key");
|
||||
next!(p, Value);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collections_in_sequence() {
|
||||
let s = "
|
||||
- - item 1
|
||||
- item 2
|
||||
- key 1: value 1
|
||||
key 2: value 2
|
||||
- ? complex key
|
||||
: complex value
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 1");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 1");
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 2");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "complex key");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "complex value");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collections_in_mapping() {
|
||||
let s = "
|
||||
? a sequence
|
||||
: - item 1
|
||||
- item 2
|
||||
? a mapping
|
||||
: key 1: value 1
|
||||
key 2: value 2
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a sequence");
|
||||
next!(p, Value);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a mapping");
|
||||
next!(p, Value);
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 1");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 1");
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 2");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_spec_ex7_3() {
|
||||
let s = "
|
||||
{
|
||||
? foo :,
|
||||
: bar,
|
||||
}
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "foo");
|
||||
next!(p, Value);
|
||||
next!(p, FlowEntry);
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "bar");
|
||||
next!(p, FlowEntry);
|
||||
next!(p, FlowMappingEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plain_scalar_starting_with_indicators_in_flow() {
|
||||
// "Plain scalars must not begin with most indicators, as this would cause ambiguity with
|
||||
// other YAML constructs. However, the “:”, “?” and “-” indicators may be used as the first
|
||||
// character if followed by a non-space “safe” character, as this causes no ambiguity."
|
||||
|
||||
let s = "{a: :b}";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, ":b");
|
||||
next!(p, FlowMappingEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
|
||||
let s = "{a: ?b}";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "?b");
|
||||
next!(p, FlowMappingEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plain_scalar_starting_with_indicators_in_block() {
|
||||
let s = ":a";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next_scalar!(p, TScalarStyle::Plain, ":a");
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
|
||||
let s = "?a";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next_scalar!(p, TScalarStyle::Plain, "?a");
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plain_scalar_containing_indicators_in_block() {
|
||||
let s = "a:,b";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next_scalar!(p, TScalarStyle::Plain, "a:,b");
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
|
||||
let s = ":,b";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next_scalar!(p, TScalarStyle::Plain, ":,b");
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scanner_cr() {
|
||||
let s = "---\r\n- tok1\r\n- tok2";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, DocumentStart);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "tok1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "tok2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uri() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uri_escapes() {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
|
294
saphyr/tests/emitter.rs
Normal file
294
saphyr/tests/emitter.rs
Normal file
|
@ -0,0 +1,294 @@
|
|||
use yaml_rust::{YamlEmitter, YamlLoader};
|
||||
|
||||
#[allow(clippy::similar_names)]
|
||||
#[test]
|
||||
fn test_emit_simple() {
|
||||
let s = "
|
||||
# comment
|
||||
a0 bb: val
|
||||
a1:
|
||||
b1: 4
|
||||
b2: d
|
||||
a2: 4 # i'm comment
|
||||
a3: [1, 2, 3]
|
||||
a4:
|
||||
- [a1, a2]
|
||||
- 2
|
||||
";
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
println!("original:\n{s}");
|
||||
println!("emitted:\n{writer}");
|
||||
let docs_new = match YamlLoader::load_from_str(&writer) {
|
||||
Ok(y) => y,
|
||||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
let doc_new = &docs_new[0];
|
||||
|
||||
assert_eq!(doc, doc_new);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_emit_complex() {
|
||||
let s = r#"
|
||||
cataloge:
|
||||
product: &coffee { name: Coffee, price: 2.5 , unit: 1l }
|
||||
product: &cookies { name: Cookies!, price: 3.40 , unit: 400g}
|
||||
|
||||
products:
|
||||
*coffee :
|
||||
amount: 4
|
||||
*cookies :
|
||||
amount: 4
|
||||
[1,2,3,4]:
|
||||
array key
|
||||
2.4:
|
||||
real key
|
||||
true:
|
||||
bool key
|
||||
{}:
|
||||
empty hash key
|
||||
"#;
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
let docs_new = match YamlLoader::load_from_str(&writer) {
|
||||
Ok(y) => y,
|
||||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
let doc_new = &docs_new[0];
|
||||
assert_eq!(doc, doc_new);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_emit_avoid_quotes() {
|
||||
let s = r#"---
|
||||
a7: 你好
|
||||
boolean: "true"
|
||||
boolean2: "false"
|
||||
date: 2014-12-31
|
||||
empty_string: ""
|
||||
empty_string1: " "
|
||||
empty_string2: " a"
|
||||
empty_string3: " a "
|
||||
exp: "12e7"
|
||||
field: ":"
|
||||
field2: "{"
|
||||
field3: "\\"
|
||||
field4: "\n"
|
||||
field5: "can't avoid quote"
|
||||
float: "2.6"
|
||||
int: "4"
|
||||
nullable: "null"
|
||||
nullable2: "~"
|
||||
products:
|
||||
"*coffee":
|
||||
amount: 4
|
||||
"*cookies":
|
||||
amount: 4
|
||||
".milk":
|
||||
amount: 1
|
||||
"2.4": real key
|
||||
"[1,2,3,4]": array key
|
||||
"true": bool key
|
||||
"{}": empty hash key
|
||||
x: test
|
||||
y: avoid quoting here
|
||||
z: string with spaces"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(s, writer, "actual:\n\n{writer}\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emit_quoted_bools() {
|
||||
let input = r#"---
|
||||
string0: yes
|
||||
string1: no
|
||||
string2: "true"
|
||||
string3: "false"
|
||||
string4: "~"
|
||||
null0: ~
|
||||
[true, false]: real_bools
|
||||
[True, TRUE, False, FALSE, y,Y,yes,Yes,YES,n,N,no,No,NO,on,On,ON,off,Off,OFF]: false_bools
|
||||
bool0: true
|
||||
bool1: false"#;
|
||||
let expected = r#"---
|
||||
string0: "yes"
|
||||
string1: "no"
|
||||
string2: "true"
|
||||
string3: "false"
|
||||
string4: "~"
|
||||
null0: ~
|
||||
? - true
|
||||
- false
|
||||
: real_bools
|
||||
? - "True"
|
||||
- "TRUE"
|
||||
- "False"
|
||||
- "FALSE"
|
||||
- y
|
||||
- Y
|
||||
- "yes"
|
||||
- "Yes"
|
||||
- "YES"
|
||||
- n
|
||||
- N
|
||||
- "no"
|
||||
- "No"
|
||||
- "NO"
|
||||
- "on"
|
||||
- "On"
|
||||
- "ON"
|
||||
- "off"
|
||||
- "Off"
|
||||
- "OFF"
|
||||
: false_bools
|
||||
bool0: true
|
||||
bool1: false"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(input).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
expected, writer,
|
||||
"expected:\n{expected}\nactual:\n{writer}\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_and_nested() {
|
||||
test_empty_and_nested_flag(false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_and_nested_compact() {
|
||||
test_empty_and_nested_flag(true);
|
||||
}
|
||||
|
||||
fn test_empty_and_nested_flag(compact: bool) {
|
||||
let s = if compact {
|
||||
r#"---
|
||||
a:
|
||||
b:
|
||||
c: hello
|
||||
d: {}
|
||||
e:
|
||||
- f
|
||||
- g
|
||||
- h: []"#
|
||||
} else {
|
||||
r#"---
|
||||
a:
|
||||
b:
|
||||
c: hello
|
||||
d: {}
|
||||
e:
|
||||
- f
|
||||
- g
|
||||
-
|
||||
h: []"#
|
||||
};
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.compact(compact);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
|
||||
assert_eq!(s, writer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_arrays() {
|
||||
let s = r#"---
|
||||
a:
|
||||
- b
|
||||
- - c
|
||||
- d
|
||||
- - e
|
||||
- f"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
println!("original:\n{s}");
|
||||
println!("emitted:\n{writer}");
|
||||
|
||||
assert_eq!(s, writer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deeply_nested_arrays() {
|
||||
let s = r#"---
|
||||
a:
|
||||
- b
|
||||
- - c
|
||||
- d
|
||||
- - e
|
||||
- - f
|
||||
- - e"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
println!("original:\n{s}");
|
||||
println!("emitted:\n{writer}");
|
||||
|
||||
assert_eq!(s, writer);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nested_hashes() {
|
||||
let s = r#"---
|
||||
a:
|
||||
b:
|
||||
c:
|
||||
d:
|
||||
e: f"#;
|
||||
|
||||
let docs = YamlLoader::load_from_str(s).unwrap();
|
||||
let doc = &docs[0];
|
||||
let mut writer = String::new();
|
||||
{
|
||||
let mut emitter = YamlEmitter::new(&mut writer);
|
||||
emitter.dump(doc).unwrap();
|
||||
}
|
||||
println!("original:\n{s}");
|
||||
println!("emitted:\n{writer}");
|
||||
|
||||
assert_eq!(s, writer);
|
||||
}
|
440
saphyr/tests/scanner.rs
Normal file
440
saphyr/tests/scanner.rs
Normal file
|
@ -0,0 +1,440 @@
|
|||
#![allow(clippy::enum_glob_use)]
|
||||
|
||||
use yaml_rust::{scanner::TokenType::*, scanner::*};
|
||||
|
||||
macro_rules! next {
|
||||
($p:ident, $tk:pat) => {{
|
||||
let tok = $p.next().unwrap();
|
||||
match tok.1 {
|
||||
$tk => {}
|
||||
_ => panic!("unexpected token: {:?}", tok),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! next_scalar {
|
||||
($p:ident, $tk:expr, $v:expr) => {{
|
||||
let tok = $p.next().unwrap();
|
||||
match tok.1 {
|
||||
Scalar(style, ref v) => {
|
||||
assert_eq!(style, $tk);
|
||||
assert_eq!(v, $v);
|
||||
}
|
||||
_ => panic!("unexpected token: {:?}", tok),
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! end {
|
||||
($p:ident) => {{
|
||||
assert_eq!($p.next(), None);
|
||||
}};
|
||||
}
|
||||
/// test cases in libyaml scanner.c
|
||||
#[test]
|
||||
fn test_empty() {
|
||||
let s = "";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scalar() {
|
||||
let s = "a scalar";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_explicit_scalar() {
|
||||
let s = "---
|
||||
'a scalar'
|
||||
...
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, DocumentStart);
|
||||
next!(p, Scalar(TScalarStyle::SingleQuoted, _));
|
||||
next!(p, DocumentEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiple_documents() {
|
||||
let s = "
|
||||
'a scalar'
|
||||
---
|
||||
'a scalar'
|
||||
---
|
||||
'a scalar'
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, Scalar(TScalarStyle::SingleQuoted, _));
|
||||
next!(p, DocumentStart);
|
||||
next!(p, Scalar(TScalarStyle::SingleQuoted, _));
|
||||
next!(p, DocumentStart);
|
||||
next!(p, Scalar(TScalarStyle::SingleQuoted, _));
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_a_flow_sequence() {
|
||||
let s = "[item 1, item 2, item 3]";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowSequenceStart);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, FlowEntry);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, FlowEntry);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, FlowSequenceEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_a_flow_mapping() {
|
||||
let s = "
|
||||
{
|
||||
a simple key: a value, # Note that the KEY token is produced.
|
||||
? a complex key: another value,
|
||||
}
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowMappingStart);
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, FlowEntry);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a complex key");
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(TScalarStyle::Plain, _));
|
||||
next!(p, FlowEntry);
|
||||
next!(p, FlowMappingEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_block_sequences() {
|
||||
let s = "
|
||||
- item 1
|
||||
- item 2
|
||||
-
|
||||
- item 3.1
|
||||
- item 3.2
|
||||
-
|
||||
key 1: value 1
|
||||
key 2: value 2
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 2");
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 3.1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 3.2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 1");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 1");
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 2");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_block_mappings() {
|
||||
let s = "
|
||||
a simple key: a value # The KEY token is produced here.
|
||||
? a complex key
|
||||
: another value
|
||||
a mapping:
|
||||
key 1: value 1
|
||||
key 2: value 2
|
||||
a sequence:
|
||||
- item 1
|
||||
- item 2
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value); // libyaml comment seems to be wrong
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, BlockEnd);
|
||||
next!(p, Key);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, Value);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, BlockEntry);
|
||||
next!(p, Scalar(_, _));
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_block_sequence_start() {
|
||||
let s = "
|
||||
key:
|
||||
- item 1
|
||||
- item 2
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key");
|
||||
next!(p, Value);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collections_in_sequence() {
|
||||
let s = "
|
||||
- - item 1
|
||||
- item 2
|
||||
- key 1: value 1
|
||||
key 2: value 2
|
||||
- ? complex key
|
||||
: complex value
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 1");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 1");
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 2");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEntry);
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "complex key");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "complex value");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collections_in_mapping() {
|
||||
let s = "
|
||||
? a sequence
|
||||
: - item 1
|
||||
- item 2
|
||||
? a mapping
|
||||
: key 1: value 1
|
||||
key 2: value 2
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a sequence");
|
||||
next!(p, Value);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "item 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a mapping");
|
||||
next!(p, Value);
|
||||
next!(p, BlockMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 1");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 1");
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "key 2");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "value 2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_spec_ex7_3() {
|
||||
let s = "
|
||||
{
|
||||
? foo :,
|
||||
: bar,
|
||||
}
|
||||
";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "foo");
|
||||
next!(p, Value);
|
||||
next!(p, FlowEntry);
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "bar");
|
||||
next!(p, FlowEntry);
|
||||
next!(p, FlowMappingEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plain_scalar_starting_with_indicators_in_flow() {
|
||||
// "Plain scalars must not begin with most indicators, as this would cause ambiguity with
|
||||
// other YAML constructs. However, the “:”, “?” and “-” indicators may be used as the first
|
||||
// character if followed by a non-space “safe” character, as this causes no ambiguity."
|
||||
|
||||
let s = "{a: :b}";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, ":b");
|
||||
next!(p, FlowMappingEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
|
||||
let s = "{a: ?b}";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, FlowMappingStart);
|
||||
next!(p, Key);
|
||||
next_scalar!(p, TScalarStyle::Plain, "a");
|
||||
next!(p, Value);
|
||||
next_scalar!(p, TScalarStyle::Plain, "?b");
|
||||
next!(p, FlowMappingEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plain_scalar_starting_with_indicators_in_block() {
|
||||
let s = ":a";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next_scalar!(p, TScalarStyle::Plain, ":a");
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
|
||||
let s = "?a";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next_scalar!(p, TScalarStyle::Plain, "?a");
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_plain_scalar_containing_indicators_in_block() {
|
||||
let s = "a:,b";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next_scalar!(p, TScalarStyle::Plain, "a:,b");
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
|
||||
let s = ":,b";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next_scalar!(p, TScalarStyle::Plain, ":,b");
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_scanner_cr() {
|
||||
let s = "---\r\n- tok1\r\n- tok2";
|
||||
let mut p = Scanner::new(s.chars());
|
||||
next!(p, StreamStart(..));
|
||||
next!(p, DocumentStart);
|
||||
next!(p, BlockSequenceStart);
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "tok1");
|
||||
next!(p, BlockEntry);
|
||||
next_scalar!(p, TScalarStyle::Plain, "tok2");
|
||||
next!(p, BlockEnd);
|
||||
next!(p, StreamEnd);
|
||||
end!(p);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uri() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uri_escapes() {
|
||||
// TODO
|
||||
}
|
|
@ -282,6 +282,7 @@ fn expected_events(expected_tree: &str) -> Vec<String> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
static EXPECTED_FAILURES: &[&str] = &[
|
||||
// These seem to be API limited (not enough information on the event stream level)
|
||||
// No tag available for SEQ and MAP
|
||||
|
@ -339,10 +340,8 @@ static EXPECTED_FAILURES: &[&str] = &[
|
|||
"HWV9",
|
||||
"QT73",
|
||||
// Unusual characters in anchors/aliases
|
||||
"2SXE", // :
|
||||
"8XYN", // emoji!!
|
||||
"W5VH", // :@*!$"<foo>:
|
||||
"Y2GN", // : in the middle
|
||||
// Flow mapping colon on next line / multiline key in flow mapping
|
||||
"4MUZ-00",
|
||||
"4MUZ-01",
|
||||
|
|
Loading…
Reference in a new issue