1 use crate::Literal;
2 
3 
4 #[test]
empty()5 fn empty() {
6     assert_err!(Literal, "", Empty, None);
7 }
8 
9 #[test]
invalid_literals()10 fn invalid_literals() {
11     assert_err_single!(Literal::parse("."), InvalidLiteral, None);
12     assert_err_single!(Literal::parse("+"), InvalidLiteral, None);
13     assert_err_single!(Literal::parse("-"), InvalidLiteral, None);
14     assert_err_single!(Literal::parse("e"), InvalidLiteral, None);
15     assert_err_single!(Literal::parse("e8"), InvalidLiteral, None);
16     assert_err_single!(Literal::parse("f32"), InvalidLiteral, None);
17     assert_err_single!(Literal::parse("foo"), InvalidLiteral, None);
18     assert_err_single!(Literal::parse("inf"), InvalidLiteral, None);
19     assert_err_single!(Literal::parse("nan"), InvalidLiteral, None);
20     assert_err_single!(Literal::parse("NaN"), InvalidLiteral, None);
21     assert_err_single!(Literal::parse("NAN"), InvalidLiteral, None);
22     assert_err_single!(Literal::parse("_2.7"), InvalidLiteral, None);
23     assert_err_single!(Literal::parse(".5"), InvalidLiteral, None);
24 }
25 
26 #[test]
misc()27 fn misc() {
28     assert_err_single!(Literal::parse("0x44.5"), InvalidIntegerTypeSuffix, 4..6);
29     assert_err_single!(Literal::parse("a"), InvalidLiteral, None);
30     assert_err_single!(Literal::parse(";"), InvalidLiteral, None);
31     assert_err_single!(Literal::parse("0;"), UnexpectedChar, 1);
32     assert_err_single!(Literal::parse("0a"), UnexpectedChar, 1);
33     assert_err_single!(Literal::parse("0z"), UnexpectedChar, 1);
34     assert_err_single!(Literal::parse(" 0"), InvalidLiteral, None);
35     assert_err_single!(Literal::parse("0 "), UnexpectedChar, 1);
36     assert_err_single!(Literal::parse("0a3"), UnexpectedChar, 1);
37     assert_err_single!(Literal::parse("0z3"), UnexpectedChar, 1);
38     assert_err_single!(Literal::parse("_"), InvalidLiteral, None);
39     assert_err_single!(Literal::parse("_3"), InvalidLiteral, None);
40     assert_err_single!(Literal::parse("12a3"), UnexpectedChar, 2);
41     assert_err_single!(Literal::parse("12f3"), InvalidFloatTypeSuffix, 2..4);
42     assert_err_single!(Literal::parse("12f_"), InvalidFloatTypeSuffix, 2..4);
43     assert_err_single!(Literal::parse("12F_"), UnexpectedChar, 2);
44     assert_err_single!(Literal::parse("a_123"), InvalidLiteral, None);
45     assert_err_single!(Literal::parse("B_123"), InvalidLiteral, None);
46     assert_err_single!(Literal::parse("54321a64"), UnexpectedChar, 5);
47 }
48 
49 macro_rules! assert_no_panic {
50     ($input:expr) => {
51         let arr = $input;
52         let input = std::str::from_utf8(&arr).expect("not unicode");
53         let res = std::panic::catch_unwind(move || {
54             let _ = Literal::parse(input);
55             let _ = crate::BoolLit::parse(input);
56             let _ = crate::IntegerLit::parse(input);
57             let _ = crate::FloatLit::parse(input);
58             let _ = crate::CharLit::parse(input);
59             let _ = crate::StringLit::parse(input);
60             let _ = crate::ByteLit::parse(input);
61             let _ = crate::ByteStringLit::parse(input);
62         });
63 
64         if let Err(e) = res {
65             println!("\n!!! panic for: {:?}", input);
66             std::panic::resume_unwind(e);
67         }
68     };
69 }
70 
71 #[test]
72 #[ignore]
never_panic_up_to_3()73 fn never_panic_up_to_3() {
74     for a in 0..128 {
75         assert_no_panic!([a]);
76         for b in 0..128 {
77             assert_no_panic!([a, b]);
78             for c in 0..128 {
79                 assert_no_panic!([a, b, c]);
80             }
81         }
82     }
83 }
84 
85 // This test takes super long in debug mode, but in release mode it's fine.
86 #[test]
87 #[ignore]
never_panic_len_4()88 fn never_panic_len_4() {
89     for a in 0..128 {
90         for b in 0..128 {
91             for c in 0..128 {
92                 for d in 0..128 {
93                     assert_no_panic!([a, b, c, d]);
94                 }
95             }
96         }
97     }
98 }
99 
100 #[cfg(feature = "proc-macro2")]
101 #[test]
proc_macro()102 fn proc_macro() {
103     use std::convert::TryFrom;
104     use proc_macro2::{
105         self as pm2, TokenTree, Group, TokenStream, Delimiter, Spacing, Punct, Span, Ident,
106     };
107     use crate::{
108         BoolLit, ByteLit, ByteStringLit, CharLit, FloatLit, IntegerLit, StringLit, err::TokenKind
109     };
110 
111 
112     macro_rules! assert_invalid_token {
113         ($input:expr, expected: $expected:path, actual: $actual:path $(,)?) => {
114             let err = $input.unwrap_err();
115             if err.expected != $expected {
116                 panic!("err.expected was expected to be {:?}, but is {:?}", $expected, err.expected);
117             }
118             if err.actual != $actual {
119                 panic!("err.actual was expected to be {:?}, but is {:?}", $actual, err.actual);
120             }
121         };
122     }
123 
124 
125     let pm_u16_lit = pm2::Literal::u16_suffixed(2700);
126     let pm_i16_lit = pm2::Literal::i16_unsuffixed(3912);
127     let pm_f32_lit = pm2::Literal::f32_unsuffixed(3.14);
128     let pm_f64_lit = pm2::Literal::f64_suffixed(99.3);
129     let pm_string_lit = pm2::Literal::string("hello ��");
130     let pm_bytestr_lit = pm2::Literal::byte_string(b"hello \nfoxxo");
131     let pm_char_lit = pm2::Literal::character('��');
132 
133     let u16_lit = Literal::parse("2700u16".to_string()).unwrap();
134     let i16_lit = Literal::parse("3912".to_string()).unwrap();
135     let f32_lit = Literal::parse("3.14".to_string()).unwrap();
136     let f64_lit = Literal::parse("99.3f64".to_string()).unwrap();
137     let string_lit = Literal::parse(r#""hello ��""#.to_string()).unwrap();
138     let bytestr_lit = Literal::parse(r#"b"hello \nfoxxo""#.to_string()).unwrap();
139     let char_lit = Literal::parse("'��'".to_string()).unwrap();
140 
141     assert_eq!(Literal::from(&pm_u16_lit), u16_lit);
142     assert_eq!(Literal::from(&pm_i16_lit), i16_lit);
143     assert_eq!(Literal::from(&pm_f32_lit), f32_lit);
144     assert_eq!(Literal::from(&pm_f64_lit), f64_lit);
145     assert_eq!(Literal::from(&pm_string_lit), string_lit);
146     assert_eq!(Literal::from(&pm_bytestr_lit), bytestr_lit);
147     assert_eq!(Literal::from(&pm_char_lit), char_lit);
148 
149 
150     let group = TokenTree::from(Group::new(Delimiter::Brace, TokenStream::new()));
151     let punct = TokenTree::from(Punct::new(':', Spacing::Alone));
152     let ident = TokenTree::from(Ident::new("peter", Span::call_site()));
153 
154     assert_eq!(
155         Literal::try_from(TokenTree::Literal(pm2::Literal::string("hello ��"))).unwrap(),
156         Literal::String(StringLit::parse(r#""hello ��""#.to_string()).unwrap()),
157     );
158     assert_invalid_token!(
159         Literal::try_from(punct.clone()),
160         expected: TokenKind::Literal,
161         actual: TokenKind::Punct,
162     );
163     assert_invalid_token!(
164         Literal::try_from(group.clone()),
165         expected: TokenKind::Literal,
166         actual: TokenKind::Group,
167     );
168     assert_invalid_token!(
169         Literal::try_from(ident.clone()),
170         expected: TokenKind::Literal,
171         actual: TokenKind::Ident,
172     );
173 
174 
175     assert_eq!(Literal::from(IntegerLit::try_from(pm_u16_lit.clone()).unwrap()), u16_lit);
176     assert_eq!(Literal::from(IntegerLit::try_from(pm_i16_lit.clone()).unwrap()), i16_lit);
177     assert_eq!(Literal::from(FloatLit::try_from(pm_f32_lit.clone()).unwrap()), f32_lit);
178     assert_eq!(Literal::from(FloatLit::try_from(pm_f64_lit.clone()).unwrap()), f64_lit);
179     assert_eq!(Literal::from(StringLit::try_from(pm_string_lit.clone()).unwrap()), string_lit);
180     assert_eq!(Literal::from(ByteStringLit::try_from(pm_bytestr_lit.clone()).unwrap()), bytestr_lit);
181     assert_eq!(Literal::from(CharLit::try_from(pm_char_lit.clone()).unwrap()), char_lit);
182 
183     assert_invalid_token!(
184         StringLit::try_from(pm_u16_lit.clone()),
185         expected: TokenKind::StringLit,
186         actual: TokenKind::IntegerLit,
187     );
188     assert_invalid_token!(
189         StringLit::try_from(pm_f32_lit.clone()),
190         expected: TokenKind::StringLit,
191         actual: TokenKind::FloatLit,
192     );
193     assert_invalid_token!(
194         ByteLit::try_from(pm_bytestr_lit.clone()),
195         expected: TokenKind::ByteLit,
196         actual: TokenKind::ByteStringLit,
197     );
198     assert_invalid_token!(
199         ByteLit::try_from(pm_i16_lit.clone()),
200         expected: TokenKind::ByteLit,
201         actual: TokenKind::IntegerLit,
202     );
203     assert_invalid_token!(
204         IntegerLit::try_from(pm_string_lit.clone()),
205         expected: TokenKind::IntegerLit,
206         actual: TokenKind::StringLit,
207     );
208     assert_invalid_token!(
209         IntegerLit::try_from(pm_char_lit.clone()),
210         expected: TokenKind::IntegerLit,
211         actual: TokenKind::CharLit,
212     );
213 
214 
215     assert_eq!(
216         Literal::from(IntegerLit::try_from(TokenTree::from(pm_u16_lit.clone())).unwrap()),
217         u16_lit,
218     );
219     assert_eq!(
220         Literal::from(IntegerLit::try_from(TokenTree::from(pm_i16_lit.clone())).unwrap()),
221         i16_lit,
222     );
223     assert_eq!(
224         Literal::from(FloatLit::try_from(TokenTree::from(pm_f32_lit.clone())).unwrap()),
225         f32_lit,
226     );
227     assert_eq!(
228         Literal::from(FloatLit::try_from(TokenTree::from(pm_f64_lit.clone())).unwrap()),
229         f64_lit,
230     );
231     assert_eq!(
232         Literal::from(StringLit::try_from(TokenTree::from(pm_string_lit.clone())).unwrap()),
233         string_lit,
234     );
235     assert_eq!(
236         Literal::from(ByteStringLit::try_from(TokenTree::from(pm_bytestr_lit.clone())).unwrap()),
237         bytestr_lit,
238     );
239     assert_eq!(
240         Literal::from(CharLit::try_from(TokenTree::from(pm_char_lit.clone())).unwrap()),
241         char_lit,
242     );
243 
244     assert_invalid_token!(
245         StringLit::try_from(TokenTree::from(pm_u16_lit.clone())),
246         expected: TokenKind::StringLit,
247         actual: TokenKind::IntegerLit,
248     );
249     assert_invalid_token!(
250         StringLit::try_from(TokenTree::from(pm_f32_lit.clone())),
251         expected: TokenKind::StringLit,
252         actual: TokenKind::FloatLit,
253     );
254     assert_invalid_token!(
255         BoolLit::try_from(TokenTree::from(pm_bytestr_lit.clone())),
256         expected: TokenKind::BoolLit,
257         actual: TokenKind::ByteStringLit,
258     );
259     assert_invalid_token!(
260         BoolLit::try_from(TokenTree::from(pm_i16_lit.clone())),
261         expected: TokenKind::BoolLit,
262         actual: TokenKind::IntegerLit,
263     );
264     assert_invalid_token!(
265         IntegerLit::try_from(TokenTree::from(pm_string_lit.clone())),
266         expected: TokenKind::IntegerLit,
267         actual: TokenKind::StringLit,
268     );
269     assert_invalid_token!(
270         IntegerLit::try_from(TokenTree::from(pm_char_lit.clone())),
271         expected: TokenKind::IntegerLit,
272         actual: TokenKind::CharLit,
273     );
274 
275     assert_invalid_token!(
276         StringLit::try_from(TokenTree::from(group)),
277         expected: TokenKind::StringLit,
278         actual: TokenKind::Group,
279     );
280     assert_invalid_token!(
281         BoolLit::try_from(TokenTree::from(punct)),
282         expected: TokenKind::BoolLit,
283         actual: TokenKind::Punct,
284     );
285     assert_invalid_token!(
286         FloatLit::try_from(TokenTree::from(ident)),
287         expected: TokenKind::FloatLit,
288         actual: TokenKind::Ident,
289     );
290 }
291 
292 #[cfg(feature = "proc-macro2")]
293 #[test]
bool_try_from_tt()294 fn bool_try_from_tt() {
295     use std::convert::TryFrom;
296     use proc_macro2::{Ident, Span, TokenTree};
297     use crate::BoolLit;
298 
299 
300     let ident = |s: &str| Ident::new(s, Span::call_site());
301 
302     assert_eq!(BoolLit::try_from(TokenTree::Ident(ident("true"))).unwrap(), BoolLit::True);
303     assert_eq!(BoolLit::try_from(TokenTree::Ident(ident("false"))).unwrap(), BoolLit::False);
304 
305     assert!(BoolLit::try_from(TokenTree::Ident(ident("falsex"))).is_err());
306     assert!(BoolLit::try_from(TokenTree::Ident(ident("_false"))).is_err());
307     assert!(BoolLit::try_from(TokenTree::Ident(ident("False"))).is_err());
308     assert!(BoolLit::try_from(TokenTree::Ident(ident("True"))).is_err());
309     assert!(BoolLit::try_from(TokenTree::Ident(ident("ltrue"))).is_err());
310 
311 
312     assert_eq!(
313         Literal::try_from(TokenTree::Ident(ident("true"))).unwrap(),
314         Literal::Bool(BoolLit::True),
315     );
316     assert_eq!(
317         Literal::try_from(TokenTree::Ident(ident("false"))).unwrap(),
318         Literal::Bool(BoolLit::False),
319     );
320 
321     assert!(Literal::try_from(TokenTree::Ident(ident("falsex"))).is_err());
322     assert!(Literal::try_from(TokenTree::Ident(ident("_false"))).is_err());
323     assert!(Literal::try_from(TokenTree::Ident(ident("False"))).is_err());
324     assert!(Literal::try_from(TokenTree::Ident(ident("True"))).is_err());
325     assert!(Literal::try_from(TokenTree::Ident(ident("ltrue"))).is_err());
326 }
327 
328 #[cfg(feature = "proc-macro2")]
329 #[test]
invalid_token_display()330 fn invalid_token_display() {
331     use crate::{InvalidToken, err::TokenKind};
332 
333     let span = crate::err::Span::Two(proc_macro2::Span::call_site());
334     assert_eq!(
335         InvalidToken {
336             actual: TokenKind::StringLit,
337             expected: TokenKind::FloatLit,
338             span,
339         }.to_string(),
340         r#"expected a float literal (e.g. `3.14`), but found a string literal (e.g. "Ferris")"#,
341     );
342 
343     assert_eq!(
344         InvalidToken {
345             actual: TokenKind::Punct,
346             expected: TokenKind::Literal,
347             span,
348         }.to_string(),
349         r#"expected a literal, but found a punctuation character"#,
350     );
351 }
352