1 extern crate toml;
2 
3 use toml::Value;
4 
5 macro_rules! bad {
6     ($s:expr, $msg:expr) => ({
7         match $s.parse::<Value>() {
8             Ok(s) => panic!("successfully parsed as {}", s),
9             Err(e) => {
10                 let e = e.to_string();
11                 assert!(e.contains($msg), "error: {}", e);
12             }
13         }
14     })
15 }
16 
17 #[test]
crlf()18 fn crlf() {
19     "\
20 [project]\r\n\
21 \r\n\
22 name = \"splay\"\r\n\
23 version = \"0.1.0\"\r\n\
24 authors = [\"alex@crichton.co\"]\r\n\
25 \r\n\
26 [[lib]]\r\n\
27 \r\n\
28 path = \"lib.rs\"\r\n\
29 name = \"splay\"\r\n\
30 description = \"\"\"\
31 A Rust implementation of a TAR file reader and writer. This library does not\r\n\
32 currently handle compression, but it is abstract over all I/O readers and\r\n\
33 writers. Additionally, great lengths are taken to ensure that the entire\r\n\
34 contents are never required to be entirely resident in memory all at once.\r\n\
35 \"\"\"\
36 ".parse::<Value>().unwrap();
37 }
38 
39 #[test]
fun_with_strings()40 fn fun_with_strings() {
41     let table = r#"
42 bar = "\U00000000"
43 key1 = "One\nTwo"
44 key2 = """One\nTwo"""
45 key3 = """
46 One
47 Two"""
48 
49 key4 = "The quick brown fox jumps over the lazy dog."
50 key5 = """
51 The quick brown \
52 
53 
54 fox jumps over \
55 the lazy dog."""
56 key6 = """\
57    The quick brown \
58    fox jumps over \
59    the lazy dog.\
60    """
61 # What you see is what you get.
62 winpath  = 'C:\Users\nodejs\templates'
63 winpath2 = '\\ServerX\admin$\system32\'
64 quoted   = 'Tom "Dubs" Preston-Werner'
65 regex    = '<\i\c*\s*>'
66 
67 regex2 = '''I [dw]on't need \d{2} apples'''
68 lines  = '''
69 The first newline is
70 trimmed in raw strings.
71 All other whitespace
72 is preserved.
73 '''
74 "#.parse::<Value>().unwrap();
75     assert_eq!(table["bar"].as_str(), Some("\0"));
76     assert_eq!(table["key1"].as_str(), Some("One\nTwo"));
77     assert_eq!(table["key2"].as_str(), Some("One\nTwo"));
78     assert_eq!(table["key3"].as_str(), Some("One\nTwo"));
79 
80     let msg = "The quick brown fox jumps over the lazy dog.";
81     assert_eq!(table["key4"].as_str(), Some(msg));
82     assert_eq!(table["key5"].as_str(), Some(msg));
83     assert_eq!(table["key6"].as_str(), Some(msg));
84 
85     assert_eq!(table["winpath"].as_str(), Some(r"C:\Users\nodejs\templates"));
86     assert_eq!(table["winpath2"].as_str(), Some(r"\\ServerX\admin$\system32\"));
87     assert_eq!(table["quoted"].as_str(), Some(r#"Tom "Dubs" Preston-Werner"#));
88     assert_eq!(table["regex"].as_str(), Some(r"<\i\c*\s*>"));
89     assert_eq!(table["regex2"].as_str(), Some(r"I [dw]on't need \d{2} apples"));
90     assert_eq!(table["lines"].as_str(),
91                Some("The first newline is\n\
92                      trimmed in raw strings.\n\
93                         All other whitespace\n\
94                         is preserved.\n"));
95 }
96 
97 #[test]
tables_in_arrays()98 fn tables_in_arrays() {
99     let table = r#"
100 [[foo]]
101 #…
102 [foo.bar]
103 #…
104 
105 [[foo]] # ...
106 #…
107 [foo.bar]
108 #...
109 "#.parse::<Value>().unwrap();
110     table["foo"][0]["bar"].as_table().unwrap();
111     table["foo"][1]["bar"].as_table().unwrap();
112 }
113 
114 #[test]
empty_table()115 fn empty_table() {
116     let table = r#"
117 [foo]"#.parse::<Value>().unwrap();
118     table["foo"].as_table().unwrap();
119 }
120 
121 #[test]
fruit()122 fn fruit() {
123     let table = r#"
124 [[fruit]]
125 name = "apple"
126 
127 [fruit.physical]
128 color = "red"
129 shape = "round"
130 
131 [[fruit.variety]]
132 name = "red delicious"
133 
134 [[fruit.variety]]
135 name = "granny smith"
136 
137 [[fruit]]
138 name = "banana"
139 
140 [[fruit.variety]]
141 name = "plantain"
142 "#.parse::<Value>().unwrap();
143     assert_eq!(table["fruit"][0]["name"].as_str(), Some("apple"));
144     assert_eq!(table["fruit"][0]["physical"]["color"].as_str(), Some("red"));
145     assert_eq!(table["fruit"][0]["physical"]["shape"].as_str(), Some("round"));
146     assert_eq!(table["fruit"][0]["variety"][0]["name"].as_str(), Some("red delicious"));
147     assert_eq!(table["fruit"][0]["variety"][1]["name"].as_str(), Some("granny smith"));
148     assert_eq!(table["fruit"][1]["name"].as_str(), Some("banana"));
149     assert_eq!(table["fruit"][1]["variety"][0]["name"].as_str(), Some("plantain"));
150 }
151 
152 #[test]
stray_cr()153 fn stray_cr() {
154     "\r".parse::<Value>().unwrap_err();
155     "a = [ \r ]".parse::<Value>().unwrap_err();
156     "a = \"\"\"\r\"\"\"".parse::<Value>().unwrap_err();
157     "a = \"\"\"\\  \r  \"\"\"".parse::<Value>().unwrap_err();
158     "a = '''\r'''".parse::<Value>().unwrap_err();
159     "a = '\r'".parse::<Value>().unwrap_err();
160     "a = \"\r\"".parse::<Value>().unwrap_err();
161 }
162 
163 #[test]
blank_literal_string()164 fn blank_literal_string() {
165     let table = "foo = ''".parse::<Value>().unwrap();
166     assert_eq!(table["foo"].as_str(), Some(""));
167 }
168 
169 #[test]
many_blank()170 fn many_blank() {
171     let table = "foo = \"\"\"\n\n\n\"\"\"".parse::<Value>().unwrap();
172     assert_eq!(table["foo"].as_str(), Some("\n\n"));
173 }
174 
175 #[test]
literal_eats_crlf()176 fn literal_eats_crlf() {
177     let table = "
178         foo = \"\"\"\\\r\n\"\"\"
179         bar = \"\"\"\\\r\n   \r\n   \r\n   a\"\"\"
180     ".parse::<Value>().unwrap();
181     assert_eq!(table["foo"].as_str(), Some(""));
182     assert_eq!(table["bar"].as_str(), Some("a"));
183 }
184 
185 #[test]
string_no_newline()186 fn string_no_newline() {
187     "a = \"\n\"".parse::<Value>().unwrap_err();
188     "a = '\n'".parse::<Value>().unwrap_err();
189 }
190 
191 #[test]
bad_leading_zeros()192 fn bad_leading_zeros() {
193     "a = 00".parse::<Value>().unwrap_err();
194     "a = -00".parse::<Value>().unwrap_err();
195     "a = +00".parse::<Value>().unwrap_err();
196     "a = 00.0".parse::<Value>().unwrap_err();
197     "a = -00.0".parse::<Value>().unwrap_err();
198     "a = +00.0".parse::<Value>().unwrap_err();
199     "a = 9223372036854775808".parse::<Value>().unwrap_err();
200     "a = -9223372036854775809".parse::<Value>().unwrap_err();
201 }
202 
203 #[test]
bad_floats()204 fn bad_floats() {
205     "a = 0.".parse::<Value>().unwrap_err();
206     "a = 0.e".parse::<Value>().unwrap_err();
207     "a = 0.E".parse::<Value>().unwrap_err();
208     "a = 0.0E".parse::<Value>().unwrap_err();
209     "a = 0.0e".parse::<Value>().unwrap_err();
210     "a = 0.0e-".parse::<Value>().unwrap_err();
211     "a = 0.0e+".parse::<Value>().unwrap_err();
212     "a = 0.0e+00".parse::<Value>().unwrap_err();
213 }
214 
215 #[test]
floats()216 fn floats() {
217     macro_rules! t {
218         ($actual:expr, $expected:expr) => ({
219             let f = format!("foo = {}", $actual);
220             println!("{}", f);
221             let a = f.parse::<Value>().unwrap();
222             assert_eq!(a["foo"].as_float().unwrap(), $expected);
223         })
224     }
225 
226     t!("1.0", 1.0);
227     t!("1.0e0", 1.0);
228     t!("1.0e+0", 1.0);
229     t!("1.0e-0", 1.0);
230     t!("1.001e-0", 1.001);
231     t!("2e10", 2e10);
232     t!("2e+10", 2e10);
233     t!("2e-10", 2e-10);
234     t!("2_0.0", 20.0);
235     t!("2_0.0_0e1_0", 20.0e10);
236     t!("2_0.1_0e1_0", 20.1e10);
237 }
238 
239 #[test]
bare_key_names()240 fn bare_key_names() {
241     let a = "
242         foo = 3
243         foo_3 = 3
244         foo_-2--3--r23f--4-f2-4 = 3
245         _ = 3
246         - = 3
247         8 = 8
248         \"a\" = 3
249         \"!\" = 3
250         \"a^b\" = 3
251         \"\\\"\" = 3
252         \"character encoding\" = \"value\"
253         'ʎǝʞ' = \"value\"
254     ".parse::<Value>().unwrap();
255     &a["foo"];
256     &a["-"];
257     &a["_"];
258     &a["8"];
259     &a["foo_3"];
260     &a["foo_-2--3--r23f--4-f2-4"];
261     &a["a"];
262     &a["!"];
263     &a["\""];
264     &a["character encoding"];
265     &a["ʎǝʞ"];
266 }
267 
268 #[test]
bad_keys()269 fn bad_keys() {
270     "key\n=3".parse::<Value>().unwrap_err();
271     "key=\n3".parse::<Value>().unwrap_err();
272     "key|=3".parse::<Value>().unwrap_err();
273     "\"\"=3".parse::<Value>().unwrap_err();
274     "=3".parse::<Value>().unwrap_err();
275     "\"\"|=3".parse::<Value>().unwrap_err();
276     "\"\n\"|=3".parse::<Value>().unwrap_err();
277     "\"\r\"|=3".parse::<Value>().unwrap_err();
278 }
279 
280 #[test]
bad_table_names()281 fn bad_table_names() {
282     "[]".parse::<Value>().unwrap_err();
283     "[.]".parse::<Value>().unwrap_err();
284     "[\"\".\"\"]".parse::<Value>().unwrap_err();
285     "[a.]".parse::<Value>().unwrap_err();
286     "[\"\"]".parse::<Value>().unwrap_err();
287     "[!]".parse::<Value>().unwrap_err();
288     "[\"\n\"]".parse::<Value>().unwrap_err();
289     "[a.b]\n[a.\"b\"]".parse::<Value>().unwrap_err();
290     "[']".parse::<Value>().unwrap_err();
291     "[''']".parse::<Value>().unwrap_err();
292     "['''''']".parse::<Value>().unwrap_err();
293     "['\n']".parse::<Value>().unwrap_err();
294     "['\r\n']".parse::<Value>().unwrap_err();
295 }
296 
297 #[test]
table_names()298 fn table_names() {
299     let a = "
300         [a.\"b\"]
301         [\"f f\"]
302         [\"f.f\"]
303         [\"\\\"\"]
304         ['a.a']
305         ['\"\"']
306     ".parse::<Value>().unwrap();
307     println!("{:?}", a);
308     &a["a"]["b"];
309     &a["f f"];
310     &a["f.f"];
311     &a["\""];
312     &a["\"\""];
313 }
314 
315 #[test]
invalid_bare_numeral()316 fn invalid_bare_numeral() {
317     "4".parse::<Value>().unwrap_err();
318 }
319 
320 #[test]
inline_tables()321 fn inline_tables() {
322     "a = {}".parse::<Value>().unwrap();
323     "a = {b=1}".parse::<Value>().unwrap();
324     "a = {   b   =   1    }".parse::<Value>().unwrap();
325     "a = {a=1,b=2}".parse::<Value>().unwrap();
326     "a = {a=1,b=2,c={}}".parse::<Value>().unwrap();
327     "a = {a=1,}".parse::<Value>().unwrap_err();
328     "a = {,}".parse::<Value>().unwrap_err();
329     "a = {a=1,a=1}".parse::<Value>().unwrap_err();
330     "a = {\n}".parse::<Value>().unwrap_err();
331     "a = {".parse::<Value>().unwrap_err();
332     "a = {a=[\n]}".parse::<Value>().unwrap();
333     "a = {\"a\"=[\n]}".parse::<Value>().unwrap();
334     "a = [\n{},\n{},\n]".parse::<Value>().unwrap();
335 }
336 
337 #[test]
number_underscores()338 fn number_underscores() {
339     macro_rules! t {
340         ($actual:expr, $expected:expr) => ({
341             let f = format!("foo = {}", $actual);
342             let table = f.parse::<Value>().unwrap();
343             assert_eq!(table["foo"].as_integer().unwrap(), $expected);
344         })
345     }
346 
347     t!("1_0", 10);
348     t!("1_0_0", 100);
349     t!("1_000", 1000);
350     t!("+1_000", 1000);
351     t!("-1_000", -1000);
352 }
353 
354 #[test]
bad_underscores()355 fn bad_underscores() {
356     bad!("foo = 0_", "invalid number");
357     bad!("foo = 0__0", "invalid number");
358     bad!("foo = __0", "invalid number");
359     bad!("foo = 1_0_", "invalid number");
360 }
361 
362 #[test]
bad_unicode_codepoint()363 fn bad_unicode_codepoint() {
364     bad!("foo = \"\\uD800\"", "invalid escape value");
365 }
366 
367 #[test]
bad_strings()368 fn bad_strings() {
369     bad!("foo = \"\\uxx\"", "invalid hex escape");
370     bad!("foo = \"\\u\"", "invalid hex escape");
371     bad!("foo = \"\\", "unterminated");
372     bad!("foo = '", "unterminated");
373 }
374 
375 #[test]
376 fn empty_string() {
377     assert_eq!("foo = \"\"".parse::<Value>()
378                            .unwrap()["foo"]
379                            .as_str()
380                            .unwrap(),
381                "");
382 }
383 
384 #[test]
booleans()385 fn booleans() {
386     let table = "foo = true".parse::<Value>().unwrap();
387     assert_eq!(table["foo"].as_bool(), Some(true));
388 
389     let table = "foo = false".parse::<Value>().unwrap();
390     assert_eq!(table["foo"].as_bool(), Some(false));
391 
392     assert!("foo = true2".parse::<Value>().is_err());
393     assert!("foo = false2".parse::<Value>().is_err());
394     assert!("foo = t1".parse::<Value>().is_err());
395     assert!("foo = f2".parse::<Value>().is_err());
396 }
397 
398 #[test]
bad_nesting()399 fn bad_nesting() {
400     bad!("
401         a = [2]
402         [[a]]
403         b = 5
404     ", "duplicate key: `a`");
405     bad!("
406         a = 1
407         [a.b]
408     ", "duplicate key: `a`");
409     bad!("
410         a = []
411         [a.b]
412     ", "duplicate key: `a`");
413     bad!("
414         a = []
415         [[a.b]]
416     ", "duplicate key: `a`");
417     bad!("
418         [a]
419         b = { c = 2, d = {} }
420         [a.b]
421         c = 2
422     ", "duplicate key: `b`");
423 }
424 
425 #[test]
bad_table_redefine()426 fn bad_table_redefine() {
427     bad!("
428         [a]
429         foo=\"bar\"
430         [a.b]
431         foo=\"bar\"
432         [a]
433     ", "redefinition of table `a`");
434     bad!("
435         [a]
436         foo=\"bar\"
437         b = { foo = \"bar\" }
438         [a]
439     ", "redefinition of table `a`");
440     bad!("
441         [a]
442         b = {}
443         [a.b]
444     ", "duplicate key: `b`");
445 
446     bad!("
447         [a]
448         b = {}
449         [a]
450     ", "redefinition of table `a`");
451 }
452 
453 #[test]
datetimes()454 fn datetimes() {
455     macro_rules! t {
456         ($actual:expr) => ({
457             let f = format!("foo = {}", $actual);
458             let toml = f.parse::<Value>().expect(&format!("failed: {}", f));
459             assert_eq!(toml["foo"].as_datetime().unwrap().to_string(), $actual);
460         })
461     }
462 
463     t!("2016-09-09T09:09:09Z");
464     t!("2016-09-09T09:09:09.1Z");
465     t!("2016-09-09T09:09:09.2+10:00");
466     t!("2016-09-09T09:09:09.123456789-02:00");
467     bad!("foo = 2016-09-09T09:09:09.Z", "failed to parse date");
468     bad!("foo = 2016-9-09T09:09:09Z", "failed to parse date");
469     bad!("foo = 2016-09-09T09:09:09+2:00", "failed to parse date");
470     bad!("foo = 2016-09-09T09:09:09-2:00", "failed to parse date");
471     bad!("foo = 2016-09-09T09:09:09Z-2:00", "failed to parse date");
472 }
473 
474 #[test]
require_newline_after_value()475 fn require_newline_after_value() {
476     bad!("0=0r=false", "invalid number at line 1");
477     bad!(r#"
478 0=""o=""m=""r=""00="0"q="""0"""e="""0"""
479 "#, "expected newline");
480     bad!(r#"
481 [[0000l0]]
482 0="0"[[0000l0]]
483 0="0"[[0000l0]]
484 0="0"l="0"
485 "#, "expected newline");
486     bad!(r#"
487 0=[0]00=[0,0,0]t=["0","0","0"]s=[1000-00-00T00:00:00Z,2000-00-00T00:00:00Z]
488 "#, "expected newline");
489     bad!(r#"
490 0=0r0=0r=false
491 "#, "invalid number at line 2");
492     bad!(r#"
493 0=0r0=0r=falsefal=false
494 "#, "invalid number at line 2");
495 }
496