1 use std::f64;
2 
3 use toml::toml;
4 
5 macro_rules! table {
6     ($($key:expr => $value:expr,)*) => {{
7         // https://github.com/rust-lang/rust/issues/60643
8         #[allow(unused_mut)]
9         let mut table = toml::value::Table::new();
10         $(
11             table.insert($key.to_string(), $value.into());
12         )*
13         toml::Value::Table(table)
14     }};
15 }
16 
17 macro_rules! array {
18     ($($element:expr,)*) => {{
19         // https://github.com/rust-lang/rust/issues/60643
20         #![allow(clippy::vec_init_then_push)]
21         #[allow(unused_mut)]
22         let mut array = toml::value::Array::new();
23         $(
24             array.push($element.into());
25         )*
26         toml::Value::Array(array)
27     }};
28 }
29 
30 macro_rules! datetime {
31     ($s:tt) => {
32         $s.parse::<toml::value::Datetime>().unwrap()
33     };
34 }
35 
36 #[test]
test_cargo_toml()37 fn test_cargo_toml() {
38     // Simple sanity check of:
39     //
40     //   - Ordinary tables
41     //   - Inline tables
42     //   - Inline arrays
43     //   - String values
44     //   - Table keys containing hyphen
45     //   - Table headers containing hyphen
46     let actual = toml! {
47         [package]
48         name = "toml"
49         version = "0.4.5"
50         authors = ["Alex Crichton <[email protected]>"]
51 
52         [badges]
53         travis-ci = { repository = "alexcrichton/toml-rs" }
54 
55         [dependencies]
56         serde = "1.0"
57 
58         [dev-dependencies]
59         serde_derive = "1.0"
60         serde_json = "1.0"
61     };
62 
63     let expected = table! {
64         "package" => table! {
65             "name" => "toml".to_owned(),
66             "version" => "0.4.5".to_owned(),
67             "authors" => array! {
68                 "Alex Crichton <[email protected]>".to_owned(),
69             },
70         },
71         "badges" => table! {
72             "travis-ci" => table! {
73                 "repository" => "alexcrichton/toml-rs".to_owned(),
74             },
75         },
76         "dependencies" => table! {
77             "serde" => "1.0".to_owned(),
78         },
79         "dev-dependencies" => table! {
80             "serde_derive" => "1.0".to_owned(),
81             "serde_json" => "1.0".to_owned(),
82         },
83     };
84 
85     assert_eq!(toml::Value::Table(actual), expected);
86 }
87 
88 #[test]
test_array()89 fn test_array() {
90     // Copied from the TOML spec.
91     let actual = toml! {
92         [[fruit]]
93         name = "apple"
94 
95         [fruit.physical]
96         color = "red"
97         shape = "round"
98 
99         [[fruit.variety]]
100         name = "red delicious"
101 
102         [[fruit.variety]]
103         name = "granny smith"
104 
105         [[fruit]]
106         name = "banana"
107 
108         [[fruit.variety]]
109         name = "plantain"
110     };
111 
112     let expected = table! {
113         "fruit" => array! {
114             table! {
115                 "name" => "apple",
116                 "physical" => table! {
117                     "color" => "red",
118                     "shape" => "round",
119                 },
120                 "variety" => array! {
121                     table! {
122                         "name" => "red delicious",
123                     },
124                     table! {
125                         "name" => "granny smith",
126                     },
127                 },
128             },
129             table! {
130                 "name" => "banana",
131                 "variety" => array! {
132                     table! {
133                         "name" => "plantain",
134                     },
135                 },
136             },
137         },
138     };
139 
140     assert_eq!(toml::Value::Table(actual), expected);
141 }
142 
143 #[test]
test_number()144 fn test_number() {
145     #![allow(clippy::unusual_byte_groupings)] // Verify the macro with odd formatting
146 
147     let actual = toml! {
148         positive = 1
149         negative = -1
150         table = { positive = 1, negative = -1 }
151         array = [ 1, -1 ]
152         neg_zero = -0
153         pos_zero = +0
154         float = 1.618
155 
156         sf1 = inf
157         sf2 = +inf
158         sf3 = -inf
159         sf7 = +0.0
160         sf8 = -0.0
161 
162         hex = 0xa_b_c
163         oct = 0o755
164         bin = 0b11010110
165     };
166 
167     let expected = table! {
168         "positive" => 1,
169         "negative" => -1,
170         "table" => table! {
171             "positive" => 1,
172             "negative" => -1,
173         },
174         "array" => array! {
175             1,
176             -1,
177         },
178         "neg_zero" => -0,
179         "pos_zero" => 0,
180         "float" => 1.618,
181         "sf1" => f64::INFINITY,
182         "sf2" => f64::INFINITY,
183         "sf3" => f64::NEG_INFINITY,
184         "sf7" => 0.0,
185         "sf8" => -0.0,
186         "hex" => 2748,
187         "oct" => 493,
188         "bin" => 214,
189     };
190 
191     assert_eq!(toml::Value::Table(actual), expected);
192 }
193 
194 #[test]
test_nan()195 fn test_nan() {
196     let actual = toml! {
197         sf4 = nan
198         sf5 = +nan
199         sf6 = -nan
200     };
201 
202     let sf4 = actual["sf4"].as_float().unwrap();
203     assert!(sf4.is_nan());
204     assert!(sf4.is_sign_positive());
205 
206     let sf5 = actual["sf5"].as_float().unwrap();
207     assert!(sf5.is_nan());
208     assert!(sf5.is_sign_positive());
209 
210     let sf6 = actual["sf6"].as_float().unwrap();
211     assert!(sf6.is_nan());
212     assert!(sf6.is_sign_negative());
213 }
214 
215 #[test]
test_datetime()216 fn test_datetime() {
217     let actual = toml! {
218         // Copied from the TOML spec.
219         odt1 = 1979-05-27T07:32:00Z
220         odt2 = 1979-05-27T00:32:00-07:00
221         odt3 = 1979-05-27T00:32:00.999999-07:00
222         odt4 = 1979-05-27 07:32:00Z
223         ldt1 = 1979-05-27T07:32:00
224         ldt2 = 1979-05-27T00:32:00.999999
225         ld1 = 1979-05-27
226         lt1 = 07:32:00
227         lt2 = 00:32:00.999999
228 
229         table = {
230             odt1 = 1979-05-27T07:32:00Z,
231             odt2 = 1979-05-27T00:32:00-07:00,
232             odt3 = 1979-05-27T00:32:00.999999-07:00,
233             odt4 = 1979-05-27 07:32:00Z,
234             ldt1 = 1979-05-27T07:32:00,
235             ldt2 = 1979-05-27T00:32:00.999999,
236             ld1 = 1979-05-27,
237             lt1 = 07:32:00,
238             lt2 = 00:32:00.999999,
239         }
240 
241         array = [
242             1979-05-27T07:32:00Z,
243             1979-05-27T00:32:00-07:00,
244             1979-05-27T00:32:00.999999-07:00,
245             1979-05-27 07:32:00Z,
246             1979-05-27T07:32:00,
247             1979-05-27T00:32:00.999999,
248             1979-05-27,
249             07:32:00,
250             00:32:00.999999,
251         ]
252     };
253 
254     let expected = table! {
255         "odt1" => datetime!("1979-05-27T07:32:00Z"),
256         "odt2" => datetime!("1979-05-27T00:32:00-07:00"),
257         "odt3" => datetime!("1979-05-27T00:32:00.999999-07:00"),
258         "odt4" => datetime!("1979-05-27 07:32:00Z"),
259         "ldt1" => datetime!("1979-05-27T07:32:00"),
260         "ldt2" => datetime!("1979-05-27T00:32:00.999999"),
261         "ld1" => datetime!("1979-05-27"),
262         "lt1" => datetime!("07:32:00"),
263         "lt2" => datetime!("00:32:00.999999"),
264 
265         "table" => table! {
266             "odt1" => datetime!("1979-05-27T07:32:00Z"),
267             "odt2" => datetime!("1979-05-27T00:32:00-07:00"),
268             "odt3" => datetime!("1979-05-27T00:32:00.999999-07:00"),
269             "odt4" => datetime!("1979-05-27 07:32:00Z"),
270             "ldt1" => datetime!("1979-05-27T07:32:00"),
271             "ldt2" => datetime!("1979-05-27T00:32:00.999999"),
272             "ld1" => datetime!("1979-05-27"),
273             "lt1" => datetime!("07:32:00"),
274             "lt2" => datetime!("00:32:00.999999"),
275         },
276 
277         "array" => array! {
278             datetime!("1979-05-27T07:32:00Z"),
279             datetime!("1979-05-27T00:32:00-07:00"),
280             datetime!("1979-05-27T00:32:00.999999-07:00"),
281             datetime!("1979-05-27 07:32:00Z"),
282             datetime!("1979-05-27T07:32:00"),
283             datetime!("1979-05-27T00:32:00.999999"),
284             datetime!("1979-05-27"),
285             datetime!("07:32:00"),
286             datetime!("00:32:00.999999"),
287         },
288     };
289 
290     assert_eq!(toml::Value::Table(actual), expected);
291 }
292 
293 // This test requires rustc >= 1.20.
294 #[test]
test_quoted_key()295 fn test_quoted_key() {
296     let actual = toml! {
297         "quoted" = true
298         table = { "quoted" = true }
299 
300         [target."cfg(windows)".dependencies]
301         winapi = "0.2.8"
302     };
303 
304     let expected = table! {
305         "quoted" => true,
306         "table" => table! {
307             "quoted" => true,
308         },
309         "target" => table! {
310             "cfg(windows)" => table! {
311                 "dependencies" => table! {
312                     "winapi" => "0.2.8",
313                 },
314             },
315         },
316     };
317 
318     assert_eq!(toml::Value::Table(actual), expected);
319 }
320 
321 #[test]
test_empty()322 fn test_empty() {
323     let actual = toml! {
324         empty_inline_table = {}
325         empty_inline_array = []
326 
327         [empty_table]
328 
329         [[empty_array]]
330     };
331 
332     let expected = table! {
333         "empty_inline_table" => table! {},
334         "empty_inline_array" => array! {},
335         "empty_table" => table! {},
336         "empty_array" => array! {
337             table! {},
338         },
339     };
340 
341     assert_eq!(toml::Value::Table(actual), expected);
342 }
343 
344 #[test]
test_dotted_keys()345 fn test_dotted_keys() {
346     let actual = toml! {
347         a.b = 123
348         a.c = 1979-05-27T07:32:00Z
349         [table]
350         a.b.c = 1
351         a  .  b  .  d = 2
352         in = { type.name = "cat", type.color = "blue" }
353     };
354 
355     let expected = table! {
356         "a" => table! {
357             "b" => 123,
358             "c" => datetime!("1979-05-27T07:32:00Z"),
359         },
360         "table" => table! {
361             "a" => table! {
362                 "b" => table! {
363                     "c" => 1,
364                     "d" => 2,
365                 },
366             },
367             "in" => table! {
368                 "type" => table! {
369                     "name" => "cat",
370                     "color" => "blue",
371                 },
372             },
373         },
374     };
375 
376     assert_eq!(toml::Value::Table(actual), expected);
377 }
378