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