]> git.proxmox.com Git - rustc.git/blame - vendor/toml_edit/tests/testsuite/parse.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / vendor / toml_edit / tests / testsuite / parse.rs
CommitLineData
0a29b90c
FG
1use snapbox::assert_eq;
2use toml_edit::{Document, Key, Value};
3
4macro_rules! parse {
5 ($s:expr, $ty:ty) => {{
6 let v = $s.parse::<$ty>();
7 assert!(v.is_ok(), "Failed with {}", v.unwrap_err());
8 v.unwrap()
9 }};
10}
11
12macro_rules! parse_value {
13 ($s:expr) => {
14 parse!($s, Value)
15 };
16}
17
18macro_rules! test_key {
19 ($s:expr, $expected:expr) => {{
20 let key = parse!($s, Key);
21 assert_eq!($expected, key.get(), "");
22 }};
23}
24
25#[test]
26fn test_key_from_str() {
27 test_key!("a", "a");
28 test_key!(r#"'hello key'"#, "hello key");
29 test_key!(
30 r#""Jos\u00E9\U000A0000\n\t\r\f\b\"""#,
31 "Jos\u{00E9}\u{A0000}\n\t\r\u{c}\u{8}\""
32 );
33 test_key!("\"\"", "");
34 test_key!("\"'hello key'bla\"", "'hello key'bla");
35 test_key!(
36 "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\cargo-edit-test.YizxPxxElXn9'",
37 "C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\cargo-edit-test.YizxPxxElXn9"
38 );
39}
40
41#[test]
42fn test_value_from_str() {
43 assert!(parse_value!("1979-05-27T00:32:00.999999-07:00").is_datetime());
44 assert!(parse_value!("1979-05-27T00:32:00.999999Z").is_datetime());
45 assert!(parse_value!("1979-05-27T00:32:00.999999").is_datetime());
46 assert!(parse_value!("1979-05-27T00:32:00").is_datetime());
47 assert!(parse_value!("1979-05-27").is_datetime());
48 assert!(parse_value!("00:32:00").is_datetime());
49 assert!(parse_value!("-239").is_integer());
50 assert!(parse_value!("1e200").is_float());
51 assert!(parse_value!("9_224_617.445_991_228_313").is_float());
52 assert!(parse_value!(r#""basic string\nJos\u00E9\n""#).is_str());
53 assert!(parse_value!(
54 r#""""
55multiline basic string
56""""#
57 )
58 .is_str());
59 assert!(parse_value!(r#"'literal string\ \'"#).is_str());
60 assert!(parse_value!(
61 r#"'''multiline
62literal \ \
63string'''"#
64 )
65 .is_str());
66 assert!(parse_value!(r#"{ hello = "world", a = 1}"#).is_inline_table());
67 assert!(
68 parse_value!(r#"[ { x = 1, a = "2" }, {a = "a",b = "b", c = "c"} ]"#).is_array()
69 );
70 let wp = "C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\cargo-edit-test.YizxPxxElXn9";
71 let lwp = "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\cargo-edit-test.YizxPxxElXn9'";
72 assert_eq!(Value::from(wp).as_str(), parse_value!(lwp).as_str());
73 assert!(parse_value!(r#""\\\"\b\f\n\r\t\u00E9\U000A0000""#).is_str());
74}
75
76#[test]
77fn test_key_unification() {
78 let toml = r#"
79[a]
80[a.'b'.c]
81[a."b".c.e]
82[a.b.c.d]
83"#;
84 let expected = r#"
85[a]
86[a.'b'.c]
87[a.'b'.c.e]
88[a.'b'.c.d]
89"#;
90 let doc = toml.parse::<Document>();
91 assert!(doc.is_ok());
92 let doc = doc.unwrap();
93
94 assert_eq(expected, doc.to_string());
95}
96
97macro_rules! bad {
98 ($toml:expr, $msg:expr) => {
99 match $toml.parse::<Document>() {
100 Ok(s) => panic!("parsed to: {:#?}", s),
101 Err(e) => snapbox::assert_eq($msg, e.to_string()),
102 }
103 };
104}
105
106#[test]
107fn crlf() {
108 "\
109 [project]\r\n\
110 \r\n\
111 name = \"splay\"\r\n\
112 version = \"0.1.0\"\r\n\
113 authors = [\"alex@crichton.co\"]\r\n\
114 \r\n\
115 [[lib]]\r\n\
116 \r\n\
117 path = \"lib.rs\"\r\n\
118 name = \"splay\"\r\n\
119 description = \"\"\"\
120 A Rust implementation of a TAR file reader and writer. This library does not\r\n\
121 currently handle compression, but it is abstract over all I/O readers and\r\n\
122 writers. Additionally, great lengths are taken to ensure that the entire\r\n\
123 contents are never required to be entirely resident in memory all at once.\r\n\
124 \"\"\"\
125 "
126 .parse::<Document>()
127 .unwrap();
128}
129
130#[test]
131fn fun_with_strings() {
132 let table = r#"
133bar = "\U00000000"
134key1 = "One\nTwo"
135key2 = """One\nTwo"""
136key3 = """
137One
138Two"""
139
140key4 = "The quick brown fox jumps over the lazy dog."
141key5 = """
142The quick brown \
143
144
145fox jumps over \
146the lazy dog."""
147key6 = """\
148 The quick brown \
149 fox jumps over \
150 the lazy dog.\
151 """
152# What you see is what you get.
153winpath = 'C:\Users\nodejs\templates'
154winpath2 = '\\ServerX\admin$\system32\'
155quoted = 'Tom "Dubs" Preston-Werner'
156regex = '<\i\c*\s*>'
157
158regex2 = '''I [dw]on't need \d{2} apples'''
159lines = '''
160The first newline is
161trimmed in raw strings.
162All other whitespace
163is preserved.
164'''
165"#
166 .parse::<Document>()
167 .unwrap();
168 assert_eq!(table["bar"].as_str(), Some("\0"));
169 assert_eq!(table["key1"].as_str(), Some("One\nTwo"));
170 assert_eq!(table["key2"].as_str(), Some("One\nTwo"));
171 assert_eq!(table["key3"].as_str(), Some("One\nTwo"));
172
173 let msg = "The quick brown fox jumps over the lazy dog.";
174 assert_eq!(table["key4"].as_str(), Some(msg));
175 assert_eq!(table["key5"].as_str(), Some(msg));
176 assert_eq!(table["key6"].as_str(), Some(msg));
177
178 assert_eq!(
179 table["winpath"].as_str(),
180 Some(r"C:\Users\nodejs\templates")
181 );
182 assert_eq!(
183 table["winpath2"].as_str(),
184 Some(r"\\ServerX\admin$\system32\")
185 );
186 assert_eq!(
187 table["quoted"].as_str(),
188 Some(r#"Tom "Dubs" Preston-Werner"#)
189 );
190 assert_eq!(table["regex"].as_str(), Some(r"<\i\c*\s*>"));
191 assert_eq!(
192 table["regex2"].as_str(),
193 Some(r"I [dw]on't need \d{2} apples")
194 );
195 assert_eq!(
196 table["lines"].as_str(),
197 Some(
198 "The first newline is\n\
199 trimmed in raw strings.\n\
200 All other whitespace\n\
201 is preserved.\n"
202 )
203 );
204}
205
206#[test]
207fn tables_in_arrays() {
208 let table = r#"
209[[foo]]
210#…
211[foo.bar]
212#…
213
214[[foo]] # ...
215#…
216[foo.bar]
217#...
218"#
219 .parse::<Document>()
220 .unwrap();
221 table["foo"][0]["bar"].as_table().unwrap();
222 table["foo"][1]["bar"].as_table().unwrap();
223}
224
225#[test]
226fn empty_table() {
227 let table = r#"
228[foo]"#
229 .parse::<Document>()
230 .unwrap();
231 table["foo"].as_table().unwrap();
232}
233
49aad941
FG
234#[test]
235fn mixed_table_issue_527() {
236 let input = r#"
237[package]
238metadata.msrv = "1.65.0"
239
240[package.metadata.release.pre-release-replacements]
241"#;
242 let document = input.parse::<Document>().unwrap();
243 let actual = document.to_string();
244 assert_eq(input, actual);
245}
246
0a29b90c
FG
247#[test]
248fn fruit() {
249 let table = r#"
250[[fruit]]
251name = "apple"
252
253[fruit.physical]
254color = "red"
255shape = "round"
256
257[[fruit.variety]]
258name = "red delicious"
259
260[[fruit.variety]]
261name = "granny smith"
262
263[[fruit]]
264name = "banana"
265
266[[fruit.variety]]
267name = "plantain"
268"#
269 .parse::<Document>()
270 .unwrap();
271 assert_eq!(table["fruit"][0]["name"].as_str(), Some("apple"));
272 assert_eq!(table["fruit"][0]["physical"]["color"].as_str(), Some("red"));
273 assert_eq!(
274 table["fruit"][0]["physical"]["shape"].as_str(),
275 Some("round")
276 );
277 assert_eq!(
278 table["fruit"][0]["variety"][0]["name"].as_str(),
279 Some("red delicious")
280 );
281 assert_eq!(
282 table["fruit"][0]["variety"][1]["name"].as_str(),
283 Some("granny smith")
284 );
285 assert_eq!(table["fruit"][1]["name"].as_str(), Some("banana"));
286 assert_eq!(
287 table["fruit"][1]["variety"][0]["name"].as_str(),
288 Some("plantain")
289 );
290}
291
292#[test]
293fn stray_cr() {
294 bad!(
295 "\r",
296 "\
297TOML parse error at line 1, column 1
298 |
2991 | \r
300 | ^
301
302"
303 );
304 bad!(
305 "a = [ \r ]",
306 "\
307TOML parse error at line 1, column 7
308 |
3091 | a = [ \r
310 ]
311 | ^
312invalid array
313expected `]`
314"
315 );
316 bad!(
317 "a = \"\"\"\r\"\"\"",
318 "\
319TOML parse error at line 1, column 8
320 |
3211 | a = \"\"\"\r
322\"\"\"
323 | ^
324invalid multiline basic string
325"
326 );
327 bad!(
328 "a = \"\"\"\\ \r \"\"\"",
329 "\
330TOML parse error at line 1, column 10
331 |
3321 | a = \"\"\"\\ \r
333 \"\"\"
334 | ^
335invalid escape sequence
336expected `b`, `f`, `n`, `r`, `t`, `u`, `U`, `\\`, `\"`
337"
338 );
339 bad!(
340 "a = '''\r'''",
341 "\
342TOML parse error at line 1, column 8
343 |
3441 | a = '''\r
345'''
346 | ^
347invalid multiline literal string
348"
349 );
350 bad!(
351 "a = '\r'",
352 "\
353TOML parse error at line 1, column 6
354 |
3551 | a = '\r
356'
357 | ^
358invalid literal string
359"
360 );
361 bad!(
362 "a = \"\r\"",
363 "\
364TOML parse error at line 1, column 6
365 |
3661 | a = \"\r
367\"
368 | ^
369invalid basic string
370"
371 );
372}
373
374#[test]
375fn blank_literal_string() {
376 let table = "foo = ''".parse::<Document>().unwrap();
377 assert_eq!(table["foo"].as_str(), Some(""));
378}
379
380#[test]
381fn many_blank() {
382 let table = "foo = \"\"\"\n\n\n\"\"\"".parse::<Document>().unwrap();
383 assert_eq!(table["foo"].as_str(), Some("\n\n"));
384}
385
386#[test]
387fn literal_eats_crlf() {
388 let table = "
389 foo = \"\"\"\\\r\n\"\"\"
390 bar = \"\"\"\\\r\n \r\n \r\n a\"\"\"
391 "
392 .parse::<Document>()
393 .unwrap();
394 assert_eq!(table["foo"].as_str(), Some(""));
395 assert_eq!(table["bar"].as_str(), Some("a"));
396}
397
398#[test]
399fn string_no_newline() {
400 bad!(
401 "a = \"\n\"",
402 "\
403TOML parse error at line 1, column 6
404 |
4051 | a = \"
406 | ^
407invalid basic string
408"
409 );
410 bad!(
411 "a = '\n'",
412 "\
413TOML parse error at line 1, column 6
414 |
4151 | a = '
416 | ^
417invalid literal string
418"
419 );
420}
421
422#[test]
423fn bad_leading_zeros() {
424 bad!(
425 "a = 00",
426 "\
427TOML parse error at line 1, column 6
428 |
4291 | a = 00
430 | ^
431expected newline, `#`
432"
433 );
434 bad!(
435 "a = -00",
436 "\
437TOML parse error at line 1, column 7
438 |
4391 | a = -00
440 | ^
441expected newline, `#`
442"
443 );
444 bad!(
445 "a = +00",
446 "\
447TOML parse error at line 1, column 7
448 |
4491 | a = +00
450 | ^
451expected newline, `#`
452"
453 );
454 bad!(
455 "a = 00.0",
456 "\
457TOML parse error at line 1, column 6
458 |
4591 | a = 00.0
460 | ^
461expected newline, `#`
462"
463 );
464 bad!(
465 "a = -00.0",
466 "\
467TOML parse error at line 1, column 7
468 |
4691 | a = -00.0
470 | ^
471expected newline, `#`
472"
473 );
474 bad!(
475 "a = +00.0",
476 "\
477TOML parse error at line 1, column 7
478 |
4791 | a = +00.0
480 | ^
481expected newline, `#`
482"
483 );
484 bad!(
485 "a = 9223372036854775808",
486 "\
487TOML parse error at line 1, column 5
488 |
4891 | a = 9223372036854775808
490 | ^
491number too large to fit in target type
492"
493 );
494 bad!(
495 "a = -9223372036854775809",
496 "\
497TOML parse error at line 1, column 5
498 |
4991 | a = -9223372036854775809
500 | ^
501number too small to fit in target type
502"
503 );
504}
505
506#[test]
507fn bad_floats() {
508 bad!(
509 "a = 0.",
510 "\
511TOML parse error at line 1, column 7
512 |
5131 | a = 0.
514 | ^
515invalid floating-point number
516expected digit
517"
518 );
519 bad!(
520 "a = 0.e",
521 "\
522TOML parse error at line 1, column 7
523 |
5241 | a = 0.e
525 | ^
526invalid floating-point number
527expected digit
528"
529 );
530 bad!(
531 "a = 0.E",
532 "\
533TOML parse error at line 1, column 7
534 |
5351 | a = 0.E
536 | ^
537invalid floating-point number
538expected digit
539"
540 );
541 bad!(
542 "a = 0.0E",
543 "\
544TOML parse error at line 1, column 9
545 |
5461 | a = 0.0E
547 | ^
548invalid floating-point number
549"
550 );
551 bad!(
552 "a = 0.0e",
553 "\
554TOML parse error at line 1, column 9
555 |
5561 | a = 0.0e
557 | ^
558invalid floating-point number
559"
560 );
561 bad!(
562 "a = 0.0e-",
563 "\
564TOML parse error at line 1, column 10
565 |
5661 | a = 0.0e-
567 | ^
568invalid floating-point number
569"
570 );
571 bad!(
572 "a = 0.0e+",
573 "\
574TOML parse error at line 1, column 10
575 |
5761 | a = 0.0e+
577 | ^
578invalid floating-point number
579"
580 );
581}
582
583#[test]
584fn floats() {
585 macro_rules! t {
586 ($actual:expr, $expected:expr) => {{
587 let f = format!("foo = {}", $actual);
588 println!("{}", f);
589 let a = f.parse::<Document>().unwrap();
590 assert_eq!(a["foo"].as_float().unwrap(), $expected);
591 }};
592 }
593
594 t!("1.0", 1.0);
595 t!("1.0e0", 1.0);
596 t!("1.0e+0", 1.0);
597 t!("1.0e-0", 1.0);
598 t!("1E-0", 1.0);
599 t!("1.001e-0", 1.001);
600 t!("2e10", 2e10);
601 t!("2e+10", 2e10);
602 t!("2e-10", 2e-10);
603 t!("2_0.0", 20.0);
604 t!("2_0.0_0e1_0", 20.0e10);
605 t!("2_0.1_0e1_0", 20.1e10);
606}
607
608#[test]
609fn bare_key_names() {
610 let a = "
611 foo = 3
612 foo_3 = 3
613 foo_-2--3--r23f--4-f2-4 = 3
614 _ = 3
615 - = 3
616 8 = 8
617 \"a\" = 3
618 \"!\" = 3
619 \"a^b\" = 3
620 \"\\\"\" = 3
621 \"character encoding\" = \"value\"
622 'ʎǝʞ' = \"value\"
623 "
624 .parse::<Document>()
625 .unwrap();
626 let _ = &a["foo"];
627 let _ = &a["-"];
628 let _ = &a["_"];
629 let _ = &a["8"];
630 let _ = &a["foo_3"];
631 let _ = &a["foo_-2--3--r23f--4-f2-4"];
632 let _ = &a["a"];
633 let _ = &a["!"];
634 let _ = &a["\""];
635 let _ = &a["character encoding"];
636 let _ = &a["ʎǝʞ"];
637}
638
639#[test]
640fn bad_keys() {
641 bad!(
642 "key\n=3",
643 "\
644TOML parse error at line 1, column 4
645 |
6461 | key
647 | ^
648expected `.`, `=`
649"
650 );
651 bad!(
652 "key=\n3",
653 "\
654TOML parse error at line 1, column 5
655 |
6561 | key=
657 | ^
658invalid string
659expected `\"`, `'`
660"
661 );
662 bad!(
663 "key|=3",
664 "\
665TOML parse error at line 1, column 4
666 |
6671 | key|=3
668 | ^
669expected `.`, `=`
670"
671 );
672 bad!(
673 "=3",
674 "\
675TOML parse error at line 1, column 1
676 |
6771 | =3
678 | ^
679invalid key
680"
681 );
682 bad!(
683 "\"\"|=3",
684 "\
685TOML parse error at line 1, column 3
686 |
6871 | \"\"|=3
688 | ^
689expected `.`, `=`
690"
691 );
692 bad!(
693 "\"\n\"|=3",
694 "\
695TOML parse error at line 1, column 2
696 |
6971 | \"
698 | ^
699invalid basic string
700"
701 );
702 bad!(
703 "\"\r\"|=3",
704 "\
705TOML parse error at line 1, column 2
706 |
7071 | \"\r\"|=3
708 | ^
709invalid basic string
710"
711 );
712 bad!(
713 "''''''=3",
714 "\
715TOML parse error at line 1, column 3
716 |
7171 | ''''''=3
718 | ^
719expected `.`, `=`
720"
721 );
722 bad!(
723 "\"\"\"\"\"\"=3",
724 "\
725TOML parse error at line 1, column 3
726 |
7271 | \"\"\"\"\"\"=3
728 | ^
729expected `.`, `=`
730"
731 );
732 bad!(
733 "'''key'''=3",
734 "\
735TOML parse error at line 1, column 3
736 |
7371 | '''key'''=3
738 | ^
739expected `.`, `=`
740"
741 );
742 bad!(
743 "\"\"\"key\"\"\"=3",
744 "\
745TOML parse error at line 1, column 3
746 |
7471 | \"\"\"key\"\"\"=3
748 | ^
749expected `.`, `=`
750"
751 );
752}
753
754#[test]
755fn bad_table_names() {
756 bad!(
757 "[]",
758 "\
759TOML parse error at line 1, column 2
760 |
7611 | []
762 | ^
763invalid key
764"
765 );
766 bad!(
767 "[.]",
768 "\
769TOML parse error at line 1, column 2
770 |
7711 | [.]
772 | ^
773invalid key
774"
775 );
776 bad!(
777 "[a.]",
778 "\
779TOML parse error at line 1, column 3
780 |
7811 | [a.]
782 | ^
783invalid table header
784expected `.`, `]`
785"
786 );
787 bad!(
788 "[!]",
789 "\
790TOML parse error at line 1, column 2
791 |
7921 | [!]
793 | ^
794invalid key
795"
796 );
797 bad!(
798 "[\"\n\"]",
799 "\
800TOML parse error at line 1, column 3
801 |
8021 | [\"
803 | ^
804invalid basic string
805"
806 );
807 bad!(
808 "[a.b]\n[a.\"b\"]",
809 "\
810TOML parse error at line 2, column 1
811 |
8122 | [a.\"b\"]
813 | ^
814invalid table header
815duplicate key `b` in table `a`
816"
817 );
818 bad!(
819 "[']",
820 "\
821TOML parse error at line 1, column 4
822 |
8231 | [']
824 | ^
825invalid literal string
826"
827 );
828 bad!(
829 "[''']",
830 "\
831TOML parse error at line 1, column 4
832 |
8331 | [''']
834 | ^
835invalid table header
836expected `.`, `]`
837"
838 );
839 bad!(
840 "['''''']",
841 "\
842TOML parse error at line 1, column 4
843 |
8441 | ['''''']
845 | ^
846invalid table header
847expected `.`, `]`
848"
849 );
850 bad!(
851 "['''foo''']",
852 "\
853TOML parse error at line 1, column 4
854 |
8551 | ['''foo''']
856 | ^
857invalid table header
858expected `.`, `]`
859"
860 );
861 bad!(
862 "[\"\"\"bar\"\"\"]",
863 "\
864TOML parse error at line 1, column 4
865 |
8661 | [\"\"\"bar\"\"\"]
867 | ^
868invalid table header
869expected `.`, `]`
870"
871 );
872 bad!(
873 "['\n']",
874 "\
875TOML parse error at line 1, column 3
876 |
8771 | ['
878 | ^
879invalid literal string
880"
881 );
882 bad!(
883 "['\r\n']",
884 "\
885TOML parse error at line 1, column 3
886 |
8871 | ['
888 | ^
889invalid literal string
890"
891 );
892}
893
894#[test]
895fn table_names() {
896 let a = "
897 [a.\"b\"]
898 [\"f f\"]
899 [\"f.f\"]
900 [\"\\\"\"]
901 ['a.a']
902 ['\"\"']
903 "
904 .parse::<Document>()
905 .unwrap();
906 println!("{:?}", a);
907 let _ = &a["a"]["b"];
908 let _ = &a["f f"];
909 let _ = &a["f.f"];
910 let _ = &a["\""];
911 let _ = &a["\"\""];
912}
913
914#[test]
915fn invalid_bare_numeral() {
916 bad!(
917 "4",
918 "\
919TOML parse error at line 1, column 2
920 |
9211 | 4
922 | ^
923expected `.`, `=`
924"
925 );
926}
927
928#[test]
929fn inline_tables() {
930 "a = {}".parse::<Document>().unwrap();
931 "a = {b=1}".parse::<Document>().unwrap();
932 "a = { b = 1 }".parse::<Document>().unwrap();
933 "a = {a=1,b=2}".parse::<Document>().unwrap();
934 "a = {a=1,b=2,c={}}".parse::<Document>().unwrap();
935
936 bad!(
937 "a = {a=1,}",
938 "\
939TOML parse error at line 1, column 9
940 |
9411 | a = {a=1,}
942 | ^
943invalid inline table
944expected `}`
945"
946 );
947 bad!(
948 "a = {,}",
949 "\
950TOML parse error at line 1, column 6
951 |
9521 | a = {,}
953 | ^
954invalid inline table
955expected `}`
956"
957 );
958 bad!(
959 "a = {a=1,a=1}",
960 "\
961TOML parse error at line 1, column 6
962 |
9631 | a = {a=1,a=1}
964 | ^
965duplicate key `a`
966"
967 );
968 bad!(
969 "a = {\n}",
970 "\
971TOML parse error at line 1, column 6
972 |
9731 | a = {
974 | ^
975invalid inline table
976expected `}`
977"
978 );
979 bad!(
980 "a = {",
981 "\
982TOML parse error at line 1, column 6
983 |
9841 | a = {
985 | ^
986invalid inline table
987expected `}`
988"
989 );
990
991 "a = {a=[\n]}".parse::<Document>().unwrap();
992 "a = {\"a\"=[\n]}".parse::<Document>().unwrap();
993 "a = [\n{},\n{},\n]".parse::<Document>().unwrap();
994}
995
996#[test]
997fn number_underscores() {
998 macro_rules! t {
999 ($actual:expr, $expected:expr) => {{
1000 let f = format!("foo = {}", $actual);
1001 let table = f.parse::<Document>().unwrap();
1002 assert_eq!(table["foo"].as_integer().unwrap(), $expected);
1003 }};
1004 }
1005
1006 t!("1_0", 10);
1007 t!("1_0_0", 100);
1008 t!("1_000", 1000);
1009 t!("+1_000", 1000);
1010 t!("-1_000", -1000);
1011}
1012
1013#[test]
1014fn bad_underscores() {
1015 bad!(
1016 "foo = 0_",
1017 "\
1018TOML parse error at line 1, column 8
1019 |
10201 | foo = 0_
1021 | ^
1022expected newline, `#`
1023"
1024 );
1025 bad!(
1026 "foo = 0__0",
1027 "\
1028TOML parse error at line 1, column 8
1029 |
10301 | foo = 0__0
1031 | ^
1032expected newline, `#`
1033"
1034 );
1035 bad!(
1036 "foo = __0",
1037 "\
1038TOML parse error at line 1, column 7
1039 |
10401 | foo = __0
1041 | ^
1042invalid integer
1043expected leading digit
1044"
1045 );
1046 bad!(
1047 "foo = 1_0_",
1048 "\
1049TOML parse error at line 1, column 11
1050 |
10511 | foo = 1_0_
1052 | ^
1053invalid integer
1054expected digit
1055"
1056 );
1057}
1058
1059#[test]
1060fn bad_unicode_codepoint() {
1061 bad!(
1062 "foo = \"\\uD800\"",
1063 "\
1064TOML parse error at line 1, column 10
1065 |
10661 | foo = \"\\uD800\"
1067 | ^
1068invalid unicode 4-digit hex code
1069value is out of range
1070"
1071 );
1072}
1073
1074#[test]
1075fn bad_strings() {
1076 bad!(
1077 "foo = \"\\uxx\"",
1078 "\
1079TOML parse error at line 1, column 10
1080 |
10811 | foo = \"\\uxx\"
1082 | ^
1083invalid unicode 4-digit hex code
1084"
1085 );
1086 bad!(
1087 "foo = \"\\u\"",
1088 "\
1089TOML parse error at line 1, column 10
1090 |
10911 | foo = \"\\u\"
1092 | ^
1093invalid unicode 4-digit hex code
1094"
1095 );
1096 bad!(
1097 "foo = \"\\",
1098 "\
1099TOML parse error at line 1, column 8
1100 |
11011 | foo = \"\\
1102 | ^
1103invalid basic string
1104"
1105 );
1106 bad!(
1107 "foo = '",
1108 "\
1109TOML parse error at line 1, column 8
1110 |
11111 | foo = '
1112 | ^
1113invalid literal string
1114"
1115 );
1116}
1117
1118#[test]
1119fn empty_string() {
1120 assert_eq!(
1121 "foo = \"\"".parse::<Document>().unwrap()["foo"]
1122 .as_str()
1123 .unwrap(),
1124 ""
1125 );
1126}
1127
1128#[test]
1129fn booleans() {
1130 let table = "foo = true".parse::<Document>().unwrap();
1131 assert_eq!(table["foo"].as_bool(), Some(true));
1132
1133 let table = "foo = false".parse::<Document>().unwrap();
1134 assert_eq!(table["foo"].as_bool(), Some(false));
1135
1136 bad!(
1137 "foo = true2",
1138 "\
1139TOML parse error at line 1, column 11
1140 |
11411 | foo = true2
1142 | ^
1143expected newline, `#`
1144"
1145 );
1146 bad!(
1147 "foo = false2",
1148 "\
1149TOML parse error at line 1, column 12
1150 |
11511 | foo = false2
1152 | ^
1153expected newline, `#`
1154"
1155 );
1156 bad!(
1157 "foo = t1",
1158 "\
1159TOML parse error at line 1, column 7
1160 |
11611 | foo = t1
1162 | ^
1163invalid string
1164expected `\"`, `'`
1165"
1166 );
1167 bad!(
1168 "foo = f2",
1169 "\
1170TOML parse error at line 1, column 7
1171 |
11721 | foo = f2
1173 | ^
1174invalid string
1175expected `\"`, `'`
1176"
1177 );
1178}
1179
1180#[test]
1181fn bad_nesting() {
1182 bad!(
1183 "
1184 a = [2]
1185 [[a]]
1186 b = 5
1187 ",
1188 "\
1189TOML parse error at line 3, column 9
1190 |
11913 | [[a]]
1192 | ^
1193invalid table header
1194duplicate key `a` in document root
1195"
1196 );
1197 bad!(
1198 "
1199 a = 1
1200 [a.b]
1201 ",
1202 "\
1203TOML parse error at line 3, column 9
1204 |
12053 | [a.b]
1206 | ^
1207invalid table header
1208dotted key `a` attempted to extend non-table type (integer)
1209"
1210 );
1211 bad!(
1212 "
1213 a = []
1214 [a.b]
1215 ",
1216 "\
1217TOML parse error at line 3, column 9
1218 |
12193 | [a.b]
1220 | ^
1221invalid table header
1222dotted key `a` attempted to extend non-table type (array)
1223"
1224 );
1225 bad!(
1226 "
1227 a = []
1228 [[a.b]]
1229 ",
1230 "\
1231TOML parse error at line 3, column 9
1232 |
12333 | [[a.b]]
1234 | ^
1235invalid table header
1236dotted key `a` attempted to extend non-table type (array)
1237"
1238 );
1239 bad!(
1240 "
1241 [a]
1242 b = { c = 2, d = {} }
1243 [a.b]
1244 c = 2
1245 ",
1246 "\
1247TOML parse error at line 4, column 9
1248 |
12494 | [a.b]
1250 | ^
1251invalid table header
1252duplicate key `b` in table `a`
1253"
1254 );
1255}
1256
1257#[test]
1258fn bad_table_redefine() {
1259 bad!(
1260 "
1261 [a]
1262 foo=\"bar\"
1263 [a.b]
1264 foo=\"bar\"
1265 [a]
1266 ",
1267 "\
1268TOML parse error at line 6, column 9
1269 |
12706 | [a]
1271 | ^
1272invalid table header
1273duplicate key `a` in document root
1274"
1275 );
1276 bad!(
1277 "
1278 [a]
1279 foo=\"bar\"
1280 b = { foo = \"bar\" }
1281 [a]
1282 ",
1283 "\
1284TOML parse error at line 5, column 9
1285 |
12865 | [a]
1287 | ^
1288invalid table header
1289duplicate key `a` in document root
1290"
1291 );
1292 bad!(
1293 "
1294 [a]
1295 b = {}
1296 [a.b]
1297 ",
1298 "\
1299TOML parse error at line 4, column 9
1300 |
13014 | [a.b]
1302 | ^
1303invalid table header
1304duplicate key `b` in table `a`
1305"
1306 );
1307
1308 bad!(
1309 "
1310 [a]
1311 b = {}
1312 [a]
1313 ",
1314 "\
1315TOML parse error at line 4, column 9
1316 |
13174 | [a]
1318 | ^
1319invalid table header
1320duplicate key `a` in document root
1321"
1322 );
1323}
1324
1325#[test]
1326fn datetimes() {
1327 macro_rules! t {
1328 ($actual:expr) => {{
1329 let f = format!("foo = {}", $actual);
1330 let toml = f.parse::<Document>().expect(&format!("failed: {}", f));
1331 assert_eq!(toml["foo"].as_datetime().unwrap().to_string(), $actual);
1332 }};
1333 }
1334
1335 t!("2016-09-09T09:09:09Z");
1336 t!("2016-09-09T09:09:09.1Z");
1337 t!("2016-09-09T09:09:09.2+10:00");
1338 t!("2016-09-09T09:09:09.123456789-02:00");
1339 bad!(
1340 "foo = 2016-09-09T09:09:09.Z",
1341 "\
1342TOML parse error at line 1, column 26
1343 |
13441 | foo = 2016-09-09T09:09:09.Z
1345 | ^
1346expected newline, `#`
1347"
1348 );
1349 bad!(
1350 "foo = 2016-9-09T09:09:09Z",
1351 "\
1352TOML parse error at line 1, column 12
1353 |
13541 | foo = 2016-9-09T09:09:09Z
1355 | ^
1356invalid date-time
1357"
1358 );
1359 bad!(
1360 "foo = 2016-09-09T09:09:09+2:00",
1361 "\
1362TOML parse error at line 1, column 27
1363 |
13641 | foo = 2016-09-09T09:09:09+2:00
1365 | ^
1366invalid time offset
1367"
1368 );
1369 bad!(
1370 "foo = 2016-09-09T09:09:09-2:00",
1371 "\
1372TOML parse error at line 1, column 27
1373 |
13741 | foo = 2016-09-09T09:09:09-2:00
1375 | ^
1376invalid time offset
1377"
1378 );
1379 bad!(
1380 "foo = 2016-09-09T09:09:09Z-2:00",
1381 "\
1382TOML parse error at line 1, column 27
1383 |
13841 | foo = 2016-09-09T09:09:09Z-2:00
1385 | ^
1386expected newline, `#`
1387"
1388 );
1389}
1390
1391#[test]
1392fn require_newline_after_value() {
1393 bad!(
1394 "0=0r=false",
1395 "\
1396TOML parse error at line 1, column 4
1397 |
13981 | 0=0r=false
1399 | ^
1400expected newline, `#`
1401"
1402 );
1403 bad!(
1404 r#"
14050=""o=""m=""r=""00="0"q="""0"""e="""0"""
1406"#,
1407 r#"TOML parse error at line 2, column 5
1408 |
14092 | 0=""o=""m=""r=""00="0"q="""0"""e="""0"""
1410 | ^
1411expected newline, `#`
1412"#
1413 );
1414 bad!(
1415 r#"
1416[[0000l0]]
14170="0"[[0000l0]]
14180="0"[[0000l0]]
14190="0"l="0"
1420"#,
1421 r#"TOML parse error at line 3, column 6
1422 |
14233 | 0="0"[[0000l0]]
1424 | ^
1425expected newline, `#`
1426"#
1427 );
1428 bad!(
1429 r#"
14300=[0]00=[0,0,0]t=["0","0","0"]s=[1000-00-00T00:00:00Z,2000-00-00T00:00:00Z]
1431"#,
1432 r#"TOML parse error at line 2, column 6
1433 |
14342 | 0=[0]00=[0,0,0]t=["0","0","0"]s=[1000-00-00T00:00:00Z,2000-00-00T00:00:00Z]
1435 | ^
1436expected newline, `#`
1437"#
1438 );
1439 bad!(
1440 r#"
14410=0r0=0r=false
1442"#,
1443 r#"TOML parse error at line 2, column 4
1444 |
14452 | 0=0r0=0r=false
1446 | ^
1447expected newline, `#`
1448"#
1449 );
1450 bad!(
1451 r#"
14520=0r0=0r=falsefal=false
1453"#,
1454 r#"TOML parse error at line 2, column 4
1455 |
14562 | 0=0r0=0r=falsefal=false
1457 | ^
1458expected newline, `#`
1459"#
1460 );
1461}
49aad941
FG
1462
1463#[test]
1464fn dont_use_dotted_key_prefix_on_table_fuzz_57049() {
1465 // This could generate
1466 // ```toml
1467 // [
1468 // p.o]
1469 // ```
1470 let input = r#"
1471p.a=4
1472[p.o]
1473"#;
1474 let document = input.parse::<Document>().unwrap();
1475 let actual = document.to_string();
1476 assert_eq(input, actual);
1477}