diff options
Diffstat (limited to 'vendor/basic-toml/tests/parser.rs')
-rw-r--r-- | vendor/basic-toml/tests/parser.rs | 687 |
1 files changed, 687 insertions, 0 deletions
diff --git a/vendor/basic-toml/tests/parser.rs b/vendor/basic-toml/tests/parser.rs new file mode 100644 index 000000000..22b40a54e --- /dev/null +++ b/vendor/basic-toml/tests/parser.rs @@ -0,0 +1,687 @@ +#![allow(clippy::let_underscore_untyped, clippy::uninlined_format_args)] + +use serde_json::{json, Value}; + +macro_rules! bad { + ($toml:expr, $msg:expr) => { + match basic_toml::from_str::<Value>($toml) { + Ok(s) => panic!("parsed to: {:#?}", s), + Err(e) => assert_eq!(e.to_string(), $msg), + } + }; +} + +#[test] +fn crlf() { + let toml = "\ + [project]\r\n\ + \r\n\ + name = \"splay\"\r\n\ + version = \"0.1.0\"\r\n\ + authors = [\"alex@crichton.co\"]\r\n\ + \r\n\ + [[lib]]\r\n\ + \r\n\ + path = \"lib.rs\"\r\n\ + name = \"splay\"\r\n\ + description = \"\"\"\ + A Rust implementation of a TAR file reader and writer. This library does not\r\n\ + currently handle compression, but it is abstract over all I/O readers and\r\n\ + writers. Additionally, great lengths are taken to ensure that the entire\r\n\ + contents are never required to be entirely resident in memory all at once.\r\n\ + \"\"\"\ + "; + basic_toml::from_str::<Value>(toml).unwrap(); +} + +#[test] +fn fun_with_strings() { + let toml = r#" +bar = "\U00000000" +key1 = "One\nTwo" +key2 = """One\nTwo""" +key3 = """ +One +Two""" + +key4 = "The quick brown fox jumps over the lazy dog." +key5 = """ +The quick brown \ + + +fox jumps over \ +the lazy dog.""" +key6 = """\ + The quick brown \ + fox jumps over \ + the lazy dog.\ + """ +# What you see is what you get. +winpath = 'C:\Users\nodejs\templates' +winpath2 = '\\ServerX\admin$\system32\' +quoted = 'Tom "Dubs" Preston-Werner' +regex = '<\i\c*\s*>' + +regex2 = '''I [dw]on't need \d{2} apples''' +lines = ''' +The first newline is +trimmed in raw strings. +All other whitespace +is preserved. +''' +"#; + let table: Value = basic_toml::from_str(toml).unwrap(); + assert_eq!(table["bar"], json!("\0")); + assert_eq!(table["key1"], json!("One\nTwo")); + assert_eq!(table["key2"], json!("One\nTwo")); + assert_eq!(table["key3"], json!("One\nTwo")); + + let msg = "The quick brown fox jumps over the lazy dog."; + assert_eq!(table["key4"], json!(msg)); + assert_eq!(table["key5"], json!(msg)); + assert_eq!(table["key6"], json!(msg)); + + assert_eq!(table["winpath"], json!(r"C:\Users\nodejs\templates")); + assert_eq!(table["winpath2"], json!(r"\\ServerX\admin$\system32\")); + assert_eq!(table["quoted"], json!(r#"Tom "Dubs" Preston-Werner"#)); + assert_eq!(table["regex"], json!(r"<\i\c*\s*>")); + assert_eq!(table["regex2"], json!(r"I [dw]on't need \d{2} apples")); + assert_eq!( + table["lines"], + json!( + "The first newline is\n\ + trimmed in raw strings.\n\ + All other whitespace\n\ + is preserved.\n" + ) + ); +} + +#[test] +fn tables_in_arrays() { + let toml = r#" +[[foo]] +#… +[foo.bar] +#… + +[[foo]] # ... +#… +[foo.bar] +#... +"#; + let table: Value = basic_toml::from_str(toml).unwrap(); + table["foo"][0]["bar"].as_object().unwrap(); + table["foo"][1]["bar"].as_object().unwrap(); +} + +#[test] +fn empty_table() { + let toml = r#" +[foo]"#; + let table: Value = basic_toml::from_str(toml).unwrap(); + table["foo"].as_object().unwrap(); +} + +#[test] +fn fruit() { + let toml = r#" +[[fruit]] +name = "apple" + +[fruit.physical] +color = "red" +shape = "round" + +[[fruit.variety]] +name = "red delicious" + +[[fruit.variety]] +name = "granny smith" + +[[fruit]] +name = "banana" + +[[fruit.variety]] +name = "plantain" +"#; + let table: Value = basic_toml::from_str(toml).unwrap(); + assert_eq!(table["fruit"][0]["name"], json!("apple")); + assert_eq!(table["fruit"][0]["physical"]["color"], json!("red")); + assert_eq!(table["fruit"][0]["physical"]["shape"], json!("round")); + assert_eq!( + table["fruit"][0]["variety"][0]["name"], + json!("red delicious") + ); + assert_eq!( + table["fruit"][0]["variety"][1]["name"], + json!("granny smith") + ); + assert_eq!(table["fruit"][1]["name"], json!("banana")); + assert_eq!(table["fruit"][1]["variety"][0]["name"], json!("plantain")); +} + +#[test] +fn stray_cr() { + bad!("\r", "unexpected character found: `\\r` at line 1 column 1"); + bad!( + "a = [ \r ]", + "unexpected character found: `\\r` at line 1 column 7" + ); + bad!( + "a = \"\"\"\r\"\"\"", + "invalid character in string: `\\r` at line 1 column 8" + ); + bad!( + "a = \"\"\"\\ \r \"\"\"", + "invalid escape character in string: ` ` at line 1 column 9" + ); + bad!( + "a = '''\r'''", + "invalid character in string: `\\r` at line 1 column 8" + ); + bad!( + "a = '\r'", + "invalid character in string: `\\r` at line 1 column 6" + ); + bad!( + "a = \"\r\"", + "invalid character in string: `\\r` at line 1 column 6" + ); +} + +#[test] +fn blank_literal_string() { + let table: Value = basic_toml::from_str("foo = ''").unwrap(); + assert_eq!(table["foo"], json!("")); +} + +#[test] +fn many_blank() { + let table: Value = basic_toml::from_str("foo = \"\"\"\n\n\n\"\"\"").unwrap(); + assert_eq!(table["foo"], json!("\n\n")); +} + +#[test] +fn literal_eats_crlf() { + let toml = " + foo = \"\"\"\\\r\n\"\"\" + bar = \"\"\"\\\r\n \r\n \r\n a\"\"\" + "; + let table: Value = basic_toml::from_str(toml).unwrap(); + assert_eq!(table["foo"], json!("")); + assert_eq!(table["bar"], json!("a")); +} + +#[test] +fn string_no_newline() { + bad!("a = \"\n\"", "newline in string found at line 1 column 6"); + bad!("a = '\n'", "newline in string found at line 1 column 6"); +} + +#[test] +fn bad_leading_zeros() { + bad!("a = 00", "invalid number at line 1 column 6"); + bad!("a = -00", "invalid number at line 1 column 7"); + bad!("a = +00", "invalid number at line 1 column 7"); + bad!("a = 00.0", "invalid number at line 1 column 6"); + bad!("a = -00.0", "invalid number at line 1 column 7"); + bad!("a = +00.0", "invalid number at line 1 column 7"); + bad!( + "a = 9223372036854775808", + "invalid number at line 1 column 5" + ); + bad!( + "a = -9223372036854775809", + "invalid number at line 1 column 5" + ); +} + +#[test] +fn bad_floats() { + bad!("a = 0.", "invalid number at line 1 column 7"); + bad!("a = 0.e", "invalid number at line 1 column 7"); + bad!("a = 0.E", "invalid number at line 1 column 7"); + bad!("a = 0.0E", "invalid number at line 1 column 5"); + bad!("a = 0.0e", "invalid number at line 1 column 5"); + bad!("a = 0.0e-", "invalid number at line 1 column 9"); + bad!("a = 0.0e+", "invalid number at line 1 column 5"); +} + +#[test] +fn floats() { + macro_rules! t { + ($actual:expr, $expected:expr) => {{ + let f = format!("foo = {}", $actual); + println!("{}", f); + let a: Value = basic_toml::from_str(&f).unwrap(); + assert_eq!(a["foo"], json!($expected)); + }}; + } + + t!("1.0", 1.0); + t!("1.0e0", 1.0); + t!("1.0e+0", 1.0); + t!("1.0e-0", 1.0); + t!("1E-0", 1.0); + t!("1.001e-0", 1.001); + t!("2e10", 2e10); + t!("2e+10", 2e10); + t!("2e-10", 2e-10); + t!("2_0.0", 20.0); + t!("2_0.0_0e1_0", 20.0e10); + t!("2_0.1_0e1_0", 20.1e10); +} + +#[test] +fn bare_key_names() { + let toml = " + foo = 3 + foo_3 = 3 + foo_-2--3--r23f--4-f2-4 = 3 + _ = 3 + - = 3 + 8 = 8 + \"a\" = 3 + \"!\" = 3 + \"a^b\" = 3 + \"\\\"\" = 3 + \"character encoding\" = \"value\" + 'ʎǝʞ' = \"value\" + "; + let a: Value = basic_toml::from_str(toml).unwrap(); + let _ = &a["foo"]; + let _ = &a["-"]; + let _ = &a["_"]; + let _ = &a["8"]; + let _ = &a["foo_3"]; + let _ = &a["foo_-2--3--r23f--4-f2-4"]; + let _ = &a["a"]; + let _ = &a["!"]; + let _ = &a["\""]; + let _ = &a["character encoding"]; + let _ = &a["ʎǝʞ"]; +} + +#[test] +fn bad_keys() { + bad!( + "key\n=3", + "expected an equals, found a newline at line 1 column 4" + ); + bad!( + "key=\n3", + "expected a value, found a newline at line 1 column 5" + ); + bad!( + "key|=3", + "unexpected character found: `|` at line 1 column 4" + ); + bad!( + "=3", + "expected a table key, found an equals at line 1 column 1" + ); + bad!( + "\"\"|=3", + "unexpected character found: `|` at line 1 column 3" + ); + bad!("\"\n\"|=3", "newline in string found at line 1 column 2"); + bad!( + "\"\r\"|=3", + "invalid character in string: `\\r` at line 1 column 2" + ); + bad!( + "''''''=3", + "multiline strings are not allowed for key at line 1 column 1" + ); + bad!( + "\"\"\"\"\"\"=3", + "multiline strings are not allowed for key at line 1 column 1" + ); + bad!( + "'''key'''=3", + "multiline strings are not allowed for key at line 1 column 1" + ); + bad!( + "\"\"\"key\"\"\"=3", + "multiline strings are not allowed for key at line 1 column 1" + ); +} + +#[test] +fn bad_table_names() { + bad!( + "[]", + "expected a table key, found a right bracket at line 1 column 2" + ); + bad!( + "[.]", + "expected a table key, found a period at line 1 column 2" + ); + bad!( + "[a.]", + "expected a table key, found a right bracket at line 1 column 4" + ); + bad!("[!]", "unexpected character found: `!` at line 1 column 2"); + bad!("[\"\n\"]", "newline in string found at line 1 column 3"); + bad!( + "[a.b]\n[a.\"b\"]", + "redefinition of table `a.b` for key `a.b` at line 2 column 1" + ); + bad!("[']", "unterminated string at line 1 column 2"); + bad!("[''']", "unterminated string at line 1 column 2"); + bad!( + "['''''']", + "multiline strings are not allowed for key at line 1 column 2" + ); + bad!( + "['''foo''']", + "multiline strings are not allowed for key at line 1 column 2" + ); + bad!( + "[\"\"\"bar\"\"\"]", + "multiline strings are not allowed for key at line 1 column 2" + ); + bad!("['\n']", "newline in string found at line 1 column 3"); + bad!("['\r\n']", "newline in string found at line 1 column 3"); +} + +#[test] +fn table_names() { + let toml = " + [a.\"b\"] + [\"f f\"] + [\"f.f\"] + [\"\\\"\"] + ['a.a'] + ['\"\"'] + "; + let a: Value = basic_toml::from_str(toml).unwrap(); + println!("{:?}", a); + let _ = &a["a"]["b"]; + let _ = &a["f f"]; + let _ = &a["f.f"]; + let _ = &a["\""]; + let _ = &a["\"\""]; +} + +#[test] +fn invalid_bare_numeral() { + bad!("4", "expected an equals, found eof at line 1 column 2"); +} + +#[test] +fn inline_tables() { + basic_toml::from_str::<Value>("a = {}").unwrap(); + basic_toml::from_str::<Value>("a = {b=1}").unwrap(); + basic_toml::from_str::<Value>("a = { b = 1 }").unwrap(); + basic_toml::from_str::<Value>("a = {a=1,b=2}").unwrap(); + basic_toml::from_str::<Value>("a = {a=1,b=2,c={}}").unwrap(); + + bad!( + "a = {a=1,}", + "expected a table key, found a right brace at line 1 column 10" + ); + bad!( + "a = {,}", + "expected a table key, found a comma at line 1 column 6" + ); + bad!( + "a = {a=1,a=1}", + "duplicate key: `a` for key `a` at line 1 column 10" + ); + bad!( + "a = {\n}", + "expected a table key, found a newline at line 1 column 6" + ); + bad!( + "a = {", + "expected a table key, found eof at line 1 column 6" + ); + + basic_toml::from_str::<Value>("a = {a=[\n]}").unwrap(); + basic_toml::from_str::<Value>("a = {\"a\"=[\n]}").unwrap(); + basic_toml::from_str::<Value>("a = [\n{},\n{},\n]").unwrap(); +} + +#[test] +fn number_underscores() { + macro_rules! t { + ($actual:expr, $expected:expr) => {{ + let f = format!("foo = {}", $actual); + let table: Value = basic_toml::from_str(&f).unwrap(); + assert_eq!(table["foo"], json!($expected)); + }}; + } + + t!("1_0", 10); + t!("1_0_0", 100); + t!("1_000", 1000); + t!("+1_000", 1000); + t!("-1_000", -1000); +} + +#[test] +fn bad_underscores() { + bad!("foo = 0_", "invalid number at line 1 column 7"); + bad!("foo = 0__0", "invalid number at line 1 column 7"); + bad!( + "foo = __0", + "invalid TOML value, did you mean to use a quoted string? at line 1 column 7" + ); + bad!("foo = 1_0_", "invalid number at line 1 column 7"); +} + +#[test] +fn bad_unicode_codepoint() { + bad!( + "foo = \"\\uD800\"", + "invalid escape value: `55296` at line 1 column 9" + ); +} + +#[test] +fn bad_strings() { + bad!( + "foo = \"\\uxx\"", + "invalid hex escape character in string: `x` at line 1 column 10" + ); + bad!( + "foo = \"\\u\"", + "invalid hex escape character in string: `\\\"` at line 1 column 10" + ); + bad!("foo = \"\\", "unterminated string at line 1 column 7"); + bad!("foo = '", "unterminated string at line 1 column 7"); +} + +#[test] +fn empty_string() { + let table: Value = basic_toml::from_str::<Value>("foo = \"\"").unwrap(); + assert_eq!(table["foo"], json!("")); +} + +#[test] +fn booleans() { + let table: Value = basic_toml::from_str("foo = true").unwrap(); + assert_eq!(table["foo"], json!(true)); + + let table: Value = basic_toml::from_str("foo = false").unwrap(); + assert_eq!(table["foo"], json!(false)); + + bad!( + "foo = true2", + "invalid TOML value, did you mean to use a quoted string? at line 1 column 7" + ); + bad!( + "foo = false2", + "invalid TOML value, did you mean to use a quoted string? at line 1 column 7" + ); + bad!( + "foo = t1", + "invalid TOML value, did you mean to use a quoted string? at line 1 column 7" + ); + bad!( + "foo = f2", + "invalid TOML value, did you mean to use a quoted string? at line 1 column 7" + ); +} + +#[test] +fn bad_nesting() { + bad!( + " + a = [2] + [[a]] + b = 5 + ", + "duplicate key: `a` at line 3 column 11" + ); + bad!( + " + a = 1 + [a.b] + ", + "duplicate key: `a` at line 3 column 10" + ); + bad!( + " + a = [] + [a.b] + ", + "duplicate key: `a` at line 3 column 10" + ); + bad!( + " + a = [] + [[a.b]] + ", + "duplicate key: `a` at line 3 column 11" + ); + bad!( + " + [a] + b = { c = 2, d = {} } + [a.b] + c = 2 + ", + "duplicate key: `b` for key `a` at line 4 column 12" + ); +} + +#[test] +fn bad_table_redefine() { + bad!( + " + [a] + foo=\"bar\" + [a.b] + foo=\"bar\" + [a] + ", + "redefinition of table `a` for key `a` at line 6 column 9" + ); + bad!( + " + [a] + foo=\"bar\" + b = { foo = \"bar\" } + [a] + ", + "redefinition of table `a` for key `a` at line 5 column 9" + ); + bad!( + " + [a] + b = {} + [a.b] + ", + "duplicate key: `b` for key `a` at line 4 column 12" + ); + + bad!( + " + [a] + b = {} + [a] + ", + "redefinition of table `a` for key `a` at line 4 column 9" + ); +} + +#[test] +fn datetimes() { + bad!( + "foo = 2016-09-09T09:09:09Z", + "invalid number at line 1 column 7" + ); + bad!( + "foo = 2016-09-09T09:09:09.1Z", + "invalid number at line 1 column 7" + ); + bad!( + "foo = 2016-09-09T09:09:09.2+10:00", + "invalid number at line 1 column 7" + ); + bad!( + "foo = 2016-09-09T09:09:09.123456789-02:00", + "invalid number at line 1 column 7" + ); + bad!( + "foo = 2016-09-09T09:09:09.Z", + "invalid number at line 1 column 7" + ); + bad!( + "foo = 2016-9-09T09:09:09Z", + "invalid number at line 1 column 7" + ); + bad!( + "foo = 2016-09-09T09:09:09+2:00", + "invalid number at line 1 column 7" + ); + bad!( + "foo = 2016-09-09T09:09:09-2:00", + "invalid number at line 1 column 7" + ); + bad!( + "foo = 2016-09-09T09:09:09Z-2:00", + "invalid number at line 1 column 7" + ); +} + +#[test] +fn require_newline_after_value() { + bad!("0=0r=false", "invalid number at line 1 column 3"); + bad!( + r#" +0=""o=""m=""r=""00="0"q="""0"""e="""0""" +"#, + "expected newline, found an identifier at line 2 column 5" + ); + bad!( + r#" +[[0000l0]] +0="0"[[0000l0]] +0="0"[[0000l0]] +0="0"l="0" +"#, + "expected newline, found a left bracket at line 3 column 6" + ); + bad!( + r#" +0=[0]00=[0,0,0]t=["0","0","0"]s=[1000-00-00T00:00:00Z,2000-00-00T00:00:00Z] +"#, + "expected newline, found an identifier at line 2 column 6" + ); + bad!( + r#" +0=0r0=0r=false +"#, + "invalid number at line 2 column 3" + ); + bad!( + r#" +0=0r0=0r=falsefal=false +"#, + "invalid number at line 2 column 3" + ); +} |