1 | #[cfg (test)] |
2 | mod test { |
3 | #[cfg (feature = "alloc" )] |
4 | use crate::{branch::alt, bytes::complete::tag_no_case, combinator::recognize, multi::many1}; |
5 | use crate::{ |
6 | bytes::complete::{is_a, is_not, tag, take, take_till, take_until}, |
7 | error::{self, ErrorKind}, |
8 | Err, IResult, |
9 | }; |
10 | |
11 | #[test ] |
12 | fn tagtr_succeed() { |
13 | const INPUT: &str = "Hello World!" ; |
14 | const TAG: &str = "Hello" ; |
15 | fn test(input: &str) -> IResult<&str, &str> { |
16 | tag(TAG)(input) |
17 | } |
18 | |
19 | match test (INPUT) { |
20 | Ok((extra, output)) => { |
21 | assert!(extra == " World!" , "Parser `tag` consumed leftover input." ); |
22 | assert!( |
23 | output == TAG, |
24 | "Parser `tag` doesn't return the tag it matched on success. \ |
25 | Expected ` {}`, got ` {}`." , |
26 | TAG, |
27 | output |
28 | ); |
29 | } |
30 | other => panic!( |
31 | "Parser `tag` didn't succeed when it should have. \ |
32 | Got ` {:?}`." , |
33 | other |
34 | ), |
35 | }; |
36 | } |
37 | |
38 | #[test ] |
39 | fn tagtr_incomplete() { |
40 | use crate::bytes::streaming::tag; |
41 | |
42 | const INPUT: &str = "Hello" ; |
43 | const TAG: &str = "Hello World!" ; |
44 | |
45 | let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT); |
46 | match res { |
47 | Err(Err::Incomplete(_)) => (), |
48 | other => { |
49 | panic!( |
50 | "Parser `tag` didn't require more input when it should have. \ |
51 | Got ` {:?}`." , |
52 | other |
53 | ); |
54 | } |
55 | }; |
56 | } |
57 | |
58 | #[test ] |
59 | fn tagtr_error() { |
60 | const INPUT: &str = "Hello World!" ; |
61 | const TAG: &str = "Random" ; // TAG must be closer than INPUT. |
62 | |
63 | let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT); |
64 | match res { |
65 | Err(Err::Error(_)) => (), |
66 | other => { |
67 | panic!( |
68 | "Parser `tag` didn't fail when it should have. Got ` {:?}`.`" , |
69 | other |
70 | ); |
71 | } |
72 | }; |
73 | } |
74 | |
75 | #[test ] |
76 | fn take_s_succeed() { |
77 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
78 | const CONSUMED: &str = "βèƒôřèÂßÇ" ; |
79 | const LEFTOVER: &str = "áƒƭèř" ; |
80 | |
81 | let res: IResult<_, _, error::Error<_>> = take(9_usize)(INPUT); |
82 | match res { |
83 | Ok((extra, output)) => { |
84 | assert!( |
85 | extra == LEFTOVER, |
86 | "Parser `take_s` consumed leftover input. Leftover ` {}`." , |
87 | extra |
88 | ); |
89 | assert!( |
90 | output == CONSUMED, |
91 | "Parser `take_s` doesn't return the string it consumed on success. Expected ` {}`, got ` {}`." , |
92 | CONSUMED, |
93 | output |
94 | ); |
95 | } |
96 | other => panic!( |
97 | "Parser `take_s` didn't succeed when it should have. \ |
98 | Got ` {:?}`." , |
99 | other |
100 | ), |
101 | }; |
102 | } |
103 | |
104 | #[test ] |
105 | fn take_until_succeed() { |
106 | const INPUT: &str = "βèƒôřèÂßÇ∂áƒƭèř" ; |
107 | const FIND: &str = "ÂßÇ∂" ; |
108 | const CONSUMED: &str = "βèƒôřè" ; |
109 | const LEFTOVER: &str = "ÂßÇ∂áƒƭèř" ; |
110 | |
111 | let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT); |
112 | match res { |
113 | Ok((extra, output)) => { |
114 | assert!( |
115 | extra == LEFTOVER, |
116 | "Parser `take_until`\ |
117 | consumed leftover input. Leftover ` {}`." , |
118 | extra |
119 | ); |
120 | assert!( |
121 | output == CONSUMED, |
122 | "Parser `take_until`\ |
123 | doesn't return the string it consumed on success. Expected ` {}`, got ` {}`." , |
124 | CONSUMED, |
125 | output |
126 | ); |
127 | } |
128 | other => panic!( |
129 | "Parser `take_until` didn't succeed when it should have. \ |
130 | Got ` {:?}`." , |
131 | other |
132 | ), |
133 | }; |
134 | } |
135 | |
136 | #[test ] |
137 | fn take_s_incomplete() { |
138 | use crate::bytes::streaming::take; |
139 | |
140 | const INPUT: &str = "βèƒôřèÂßÇá" ; |
141 | |
142 | let res: IResult<_, _, (_, ErrorKind)> = take(13_usize)(INPUT); |
143 | match res { |
144 | Err(Err::Incomplete(_)) => (), |
145 | other => panic!( |
146 | "Parser `take` didn't require more input when it should have. \ |
147 | Got ` {:?}`." , |
148 | other |
149 | ), |
150 | } |
151 | } |
152 | |
153 | use crate::internal::Needed; |
154 | |
155 | fn is_alphabetic(c: char) -> bool { |
156 | (c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A) |
157 | } |
158 | |
159 | #[test ] |
160 | fn take_while() { |
161 | use crate::bytes::streaming::take_while; |
162 | |
163 | fn f(i: &str) -> IResult<&str, &str> { |
164 | take_while(is_alphabetic)(i) |
165 | } |
166 | let a = "" ; |
167 | let b = "abcd" ; |
168 | let c = "abcd123" ; |
169 | let d = "123" ; |
170 | |
171 | assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); |
172 | assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1)))); |
173 | assert_eq!(f(&c[..]), Ok((&d[..], &b[..]))); |
174 | assert_eq!(f(&d[..]), Ok((&d[..], &a[..]))); |
175 | } |
176 | |
177 | #[test ] |
178 | fn take_while1() { |
179 | use crate::bytes::streaming::take_while1; |
180 | |
181 | fn f(i: &str) -> IResult<&str, &str> { |
182 | take_while1(is_alphabetic)(i) |
183 | } |
184 | let a = "" ; |
185 | let b = "abcd" ; |
186 | let c = "abcd123" ; |
187 | let d = "123" ; |
188 | |
189 | assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1)))); |
190 | assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1)))); |
191 | assert_eq!(f(&c[..]), Ok((&"123" [..], &b[..]))); |
192 | assert_eq!( |
193 | f(&d[..]), |
194 | Err(Err::Error(error_position!(&d[..], ErrorKind::TakeWhile1))) |
195 | ); |
196 | } |
197 | |
198 | #[test ] |
199 | fn take_till_s_succeed() { |
200 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
201 | const CONSUMED: &str = "βèƒôřèÂßÇ" ; |
202 | const LEFTOVER: &str = "áƒƭèř" ; |
203 | fn till_s(c: char) -> bool { |
204 | c == 'á' |
205 | } |
206 | fn test(input: &str) -> IResult<&str, &str> { |
207 | take_till(till_s)(input) |
208 | } |
209 | match test (INPUT) { |
210 | Ok((extra, output)) => { |
211 | assert!( |
212 | extra == LEFTOVER, |
213 | "Parser `take_till` consumed leftover input." |
214 | ); |
215 | assert!( |
216 | output == CONSUMED, |
217 | "Parser `take_till` doesn't return the string it consumed on success. \ |
218 | Expected ` {}`, got ` {}`." , |
219 | CONSUMED, |
220 | output |
221 | ); |
222 | } |
223 | other => panic!( |
224 | "Parser `take_till` didn't succeed when it should have. \ |
225 | Got ` {:?}`." , |
226 | other |
227 | ), |
228 | }; |
229 | } |
230 | |
231 | #[test ] |
232 | fn take_while_succeed_none() { |
233 | use crate::bytes::complete::take_while; |
234 | |
235 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
236 | const CONSUMED: &str = "" ; |
237 | const LEFTOVER: &str = "βèƒôřèÂßÇáƒƭèř" ; |
238 | fn while_s(c: char) -> bool { |
239 | c == '9' |
240 | } |
241 | fn test(input: &str) -> IResult<&str, &str> { |
242 | take_while(while_s)(input) |
243 | } |
244 | match test (INPUT) { |
245 | Ok((extra, output)) => { |
246 | assert!( |
247 | extra == LEFTOVER, |
248 | "Parser `take_while` consumed leftover input." |
249 | ); |
250 | assert!( |
251 | output == CONSUMED, |
252 | "Parser `take_while` doesn't return the string it consumed on success. \ |
253 | Expected ` {}`, got ` {}`." , |
254 | CONSUMED, |
255 | output |
256 | ); |
257 | } |
258 | other => panic!( |
259 | "Parser `take_while` didn't succeed when it should have. \ |
260 | Got ` {:?}`." , |
261 | other |
262 | ), |
263 | }; |
264 | } |
265 | |
266 | #[test ] |
267 | fn is_not_succeed() { |
268 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
269 | const AVOID: &str = "£úçƙ¥á" ; |
270 | const CONSUMED: &str = "βèƒôřèÂßÇ" ; |
271 | const LEFTOVER: &str = "áƒƭèř" ; |
272 | fn test(input: &str) -> IResult<&str, &str> { |
273 | is_not(AVOID)(input) |
274 | } |
275 | match test (INPUT) { |
276 | Ok((extra, output)) => { |
277 | assert!( |
278 | extra == LEFTOVER, |
279 | "Parser `is_not` consumed leftover input. Leftover ` {}`." , |
280 | extra |
281 | ); |
282 | assert!( |
283 | output == CONSUMED, |
284 | "Parser `is_not` doesn't return the string it consumed on success. Expected ` {}`, got ` {}`." , |
285 | CONSUMED, |
286 | output |
287 | ); |
288 | } |
289 | other => panic!( |
290 | "Parser `is_not` didn't succeed when it should have. \ |
291 | Got ` {:?}`." , |
292 | other |
293 | ), |
294 | }; |
295 | } |
296 | |
297 | #[test ] |
298 | fn take_while_succeed_some() { |
299 | use crate::bytes::complete::take_while; |
300 | |
301 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
302 | const CONSUMED: &str = "βèƒôřèÂßÇ" ; |
303 | const LEFTOVER: &str = "áƒƭèř" ; |
304 | fn while_s(c: char) -> bool { |
305 | c == 'β' |
306 | || c == 'è' |
307 | || c == 'ƒ' |
308 | || c == 'ô' |
309 | || c == 'ř' |
310 | || c == 'è' |
311 | || c == 'Â' |
312 | || c == 'ß' |
313 | || c == 'Ç' |
314 | } |
315 | fn test(input: &str) -> IResult<&str, &str> { |
316 | take_while(while_s)(input) |
317 | } |
318 | match test (INPUT) { |
319 | Ok((extra, output)) => { |
320 | assert!( |
321 | extra == LEFTOVER, |
322 | "Parser `take_while` consumed leftover input." |
323 | ); |
324 | assert!( |
325 | output == CONSUMED, |
326 | "Parser `take_while` doesn't return the string it consumed on success. \ |
327 | Expected ` {}`, got ` {}`." , |
328 | CONSUMED, |
329 | output |
330 | ); |
331 | } |
332 | other => panic!( |
333 | "Parser `take_while` didn't succeed when it should have. \ |
334 | Got ` {:?}`." , |
335 | other |
336 | ), |
337 | }; |
338 | } |
339 | |
340 | #[test ] |
341 | fn is_not_fail() { |
342 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
343 | const AVOID: &str = "βúçƙ¥" ; |
344 | fn test(input: &str) -> IResult<&str, &str> { |
345 | is_not(AVOID)(input) |
346 | } |
347 | match test (INPUT) { |
348 | Err(Err::Error(_)) => (), |
349 | other => panic!( |
350 | "Parser `is_not` didn't fail when it should have. Got ` {:?}`." , |
351 | other |
352 | ), |
353 | }; |
354 | } |
355 | |
356 | #[test ] |
357 | fn take_while1_succeed() { |
358 | use crate::bytes::complete::take_while1; |
359 | |
360 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
361 | const CONSUMED: &str = "βèƒôřèÂßÇ" ; |
362 | const LEFTOVER: &str = "áƒƭèř" ; |
363 | fn while1_s(c: char) -> bool { |
364 | c == 'β' |
365 | || c == 'è' |
366 | || c == 'ƒ' |
367 | || c == 'ô' |
368 | || c == 'ř' |
369 | || c == 'è' |
370 | || c == 'Â' |
371 | || c == 'ß' |
372 | || c == 'Ç' |
373 | } |
374 | fn test(input: &str) -> IResult<&str, &str> { |
375 | take_while1(while1_s)(input) |
376 | } |
377 | match test (INPUT) { |
378 | Ok((extra, output)) => { |
379 | assert!( |
380 | extra == LEFTOVER, |
381 | "Parser `take_while1` consumed leftover input." |
382 | ); |
383 | assert!( |
384 | output == CONSUMED, |
385 | "Parser `take_while1` doesn't return the string it consumed on success. \ |
386 | Expected ` {}`, got ` {}`." , |
387 | CONSUMED, |
388 | output |
389 | ); |
390 | } |
391 | other => panic!( |
392 | "Parser `take_while1` didn't succeed when it should have. \ |
393 | Got ` {:?}`." , |
394 | other |
395 | ), |
396 | }; |
397 | } |
398 | |
399 | #[test ] |
400 | fn take_until_incomplete() { |
401 | use crate::bytes::streaming::take_until; |
402 | |
403 | const INPUT: &str = "βèƒôřè" ; |
404 | const FIND: &str = "βèƒôřèÂßÇ" ; |
405 | |
406 | let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT); |
407 | match res { |
408 | Err(Err::Incomplete(_)) => (), |
409 | other => panic!( |
410 | "Parser `take_until` didn't require more input when it should have. \ |
411 | Got ` {:?}`." , |
412 | other |
413 | ), |
414 | }; |
415 | } |
416 | |
417 | #[test ] |
418 | fn is_a_succeed() { |
419 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
420 | const MATCH: &str = "βèƒôřèÂßÇ" ; |
421 | const CONSUMED: &str = "βèƒôřèÂßÇ" ; |
422 | const LEFTOVER: &str = "áƒƭèř" ; |
423 | fn test(input: &str) -> IResult<&str, &str> { |
424 | is_a(MATCH)(input) |
425 | } |
426 | match test (INPUT) { |
427 | Ok((extra, output)) => { |
428 | assert!( |
429 | extra == LEFTOVER, |
430 | "Parser `is_a` consumed leftover input. Leftover ` {}`." , |
431 | extra |
432 | ); |
433 | assert!( |
434 | output == CONSUMED, |
435 | "Parser `is_a` doesn't return the string it consumed on success. Expected ` {}`, got ` {}`." , |
436 | CONSUMED, |
437 | output |
438 | ); |
439 | } |
440 | other => panic!( |
441 | "Parser `is_a` didn't succeed when it should have. \ |
442 | Got ` {:?}`." , |
443 | other |
444 | ), |
445 | }; |
446 | } |
447 | |
448 | #[test ] |
449 | fn take_while1_fail() { |
450 | use crate::bytes::complete::take_while1; |
451 | |
452 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
453 | fn while1_s(c: char) -> bool { |
454 | c == '9' |
455 | } |
456 | fn test(input: &str) -> IResult<&str, &str> { |
457 | take_while1(while1_s)(input) |
458 | } |
459 | match test (INPUT) { |
460 | Err(Err::Error(_)) => (), |
461 | other => panic!( |
462 | "Parser `take_while1` didn't fail when it should have. \ |
463 | Got ` {:?}`." , |
464 | other |
465 | ), |
466 | }; |
467 | } |
468 | |
469 | #[test ] |
470 | fn is_a_fail() { |
471 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
472 | const MATCH: &str = "Ûñℓúçƙ¥" ; |
473 | fn test(input: &str) -> IResult<&str, &str> { |
474 | is_a(MATCH)(input) |
475 | } |
476 | match test (INPUT) { |
477 | Err(Err::Error(_)) => (), |
478 | other => panic!( |
479 | "Parser `is_a` didn't fail when it should have. Got ` {:?}`." , |
480 | other |
481 | ), |
482 | }; |
483 | } |
484 | |
485 | #[test ] |
486 | fn take_until_error() { |
487 | use crate::bytes::streaming::take_until; |
488 | |
489 | const INPUT: &str = "βèƒôřèÂßÇáƒƭèř" ; |
490 | const FIND: &str = "Ráñδô₥" ; |
491 | |
492 | let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT); |
493 | match res { |
494 | Err(Err::Incomplete(_)) => (), |
495 | other => panic!( |
496 | "Parser `take_until` didn't fail when it should have. \ |
497 | Got ` {:?}`." , |
498 | other |
499 | ), |
500 | }; |
501 | } |
502 | |
503 | #[test ] |
504 | #[cfg (feature = "alloc" )] |
505 | fn recognize_is_a() { |
506 | let a = "aabbab" ; |
507 | let b = "ababcd" ; |
508 | |
509 | fn f(i: &str) -> IResult<&str, &str> { |
510 | recognize(many1(alt((tag("a" ), tag("b" )))))(i) |
511 | } |
512 | |
513 | assert_eq!(f(&a[..]), Ok((&a[6..], &a[..]))); |
514 | assert_eq!(f(&b[..]), Ok((&b[4..], &b[..4]))); |
515 | } |
516 | |
517 | #[test ] |
518 | fn utf8_indexing() { |
519 | fn dot(i: &str) -> IResult<&str, &str> { |
520 | tag("." )(i) |
521 | } |
522 | |
523 | let _ = dot("點" ); |
524 | } |
525 | |
526 | #[cfg (feature = "alloc" )] |
527 | #[test ] |
528 | fn case_insensitive() { |
529 | fn test(i: &str) -> IResult<&str, &str> { |
530 | tag_no_case("ABcd" )(i) |
531 | } |
532 | assert_eq!(test ("aBCdefgh" ), Ok(("efgh" , "aBCd" ))); |
533 | assert_eq!(test ("abcdefgh" ), Ok(("efgh" , "abcd" ))); |
534 | assert_eq!(test ("ABCDefgh" ), Ok(("efgh" , "ABCD" ))); |
535 | } |
536 | } |
537 | |