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