]> git.lizzy.rs Git - rust.git/blob - library/alloc/tests/str.rs
Rollup merge of #74872 - JohnTitor:ping-risc-v, r=Mark-Simulacrum
[rust.git] / library / alloc / tests / str.rs
1 use std::borrow::Cow;
2 use std::cmp::Ordering::{Equal, Greater, Less};
3 use std::str::from_utf8;
4
5 #[test]
6 fn test_le() {
7     assert!("" <= "");
8     assert!("" <= "foo");
9     assert!("foo" <= "foo");
10     assert_ne!("foo", "bar");
11 }
12
13 #[test]
14 fn test_find() {
15     assert_eq!("hello".find('l'), Some(2));
16     assert_eq!("hello".find(|c: char| c == 'o'), Some(4));
17     assert!("hello".find('x').is_none());
18     assert!("hello".find(|c: char| c == 'x').is_none());
19     assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
20     assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
21 }
22
23 #[test]
24 fn test_rfind() {
25     assert_eq!("hello".rfind('l'), Some(3));
26     assert_eq!("hello".rfind(|c: char| c == 'o'), Some(4));
27     assert!("hello".rfind('x').is_none());
28     assert!("hello".rfind(|c: char| c == 'x').is_none());
29     assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
30     assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
31 }
32
33 #[test]
34 fn test_collect() {
35     let empty = "";
36     let s: String = empty.chars().collect();
37     assert_eq!(empty, s);
38     let data = "ประเทศไทย中";
39     let s: String = data.chars().collect();
40     assert_eq!(data, s);
41 }
42
43 #[test]
44 fn test_into_bytes() {
45     let data = String::from("asdf");
46     let buf = data.into_bytes();
47     assert_eq!(buf, b"asdf");
48 }
49
50 #[test]
51 fn test_find_str() {
52     // byte positions
53     assert_eq!("".find(""), Some(0));
54     assert!("banana".find("apple pie").is_none());
55
56     let data = "abcabc";
57     assert_eq!(data[0..6].find("ab"), Some(0));
58     assert_eq!(data[2..6].find("ab"), Some(3 - 2));
59     assert!(data[2..4].find("ab").is_none());
60
61     let string = "ประเทศไทย中华Việt Nam";
62     let mut data = String::from(string);
63     data.push_str(string);
64     assert!(data.find("ไท华").is_none());
65     assert_eq!(data[0..43].find(""), Some(0));
66     assert_eq!(data[6..43].find(""), Some(6 - 6));
67
68     assert_eq!(data[0..43].find("ประ"), Some(0));
69     assert_eq!(data[0..43].find("ทศไ"), Some(12));
70     assert_eq!(data[0..43].find("ย中"), Some(24));
71     assert_eq!(data[0..43].find("iệt"), Some(34));
72     assert_eq!(data[0..43].find("Nam"), Some(40));
73
74     assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
75     assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
76     assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
77     assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
78     assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
79
80     // find every substring -- assert that it finds it, or an earlier occurrence.
81     let string = "Việt Namacbaabcaabaaba";
82     for (i, ci) in string.char_indices() {
83         let ip = i + ci.len_utf8();
84         for j in string[ip..].char_indices().map(|(i, _)| i).chain(Some(string.len() - ip)) {
85             let pat = &string[i..ip + j];
86             assert!(match string.find(pat) {
87                 None => false,
88                 Some(x) => x <= i,
89             });
90             assert!(match string.rfind(pat) {
91                 None => false,
92                 Some(x) => x >= i,
93             });
94         }
95     }
96 }
97
98 fn s(x: &str) -> String {
99     x.to_string()
100 }
101
102 macro_rules! test_concat {
103     ($expected: expr, $string: expr) => {{
104         let s: String = $string.concat();
105         assert_eq!($expected, s);
106     }};
107 }
108
109 #[test]
110 fn test_concat_for_different_types() {
111     test_concat!("ab", vec![s("a"), s("b")]);
112     test_concat!("ab", vec!["a", "b"]);
113 }
114
115 #[test]
116 fn test_concat_for_different_lengths() {
117     let empty: &[&str] = &[];
118     test_concat!("", empty);
119     test_concat!("a", ["a"]);
120     test_concat!("ab", ["a", "b"]);
121     test_concat!("abc", ["", "a", "bc"]);
122 }
123
124 macro_rules! test_join {
125     ($expected: expr, $string: expr, $delim: expr) => {{
126         let s = $string.join($delim);
127         assert_eq!($expected, s);
128     }};
129 }
130
131 #[test]
132 fn test_join_for_different_types() {
133     test_join!("a-b", ["a", "b"], "-");
134     let hyphen = "-".to_string();
135     test_join!("a-b", [s("a"), s("b")], &*hyphen);
136     test_join!("a-b", vec!["a", "b"], &*hyphen);
137     test_join!("a-b", &*vec!["a", "b"], "-");
138     test_join!("a-b", vec![s("a"), s("b")], "-");
139 }
140
141 #[test]
142 fn test_join_for_different_lengths() {
143     let empty: &[&str] = &[];
144     test_join!("", empty, "-");
145     test_join!("a", ["a"], "-");
146     test_join!("a-b", ["a", "b"], "-");
147     test_join!("-a-bc", ["", "a", "bc"], "-");
148 }
149
150 // join has fast paths for small separators up to 4 bytes
151 // this tests the slow paths.
152 #[test]
153 fn test_join_for_different_lengths_with_long_separator() {
154     assert_eq!("~~~~~".len(), 15);
155
156     let empty: &[&str] = &[];
157     test_join!("", empty, "~~~~~");
158     test_join!("a", ["a"], "~~~~~");
159     test_join!("a~~~~~b", ["a", "b"], "~~~~~");
160     test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
161 }
162
163 #[test]
164 #[cfg_attr(miri, ignore)] // Miri is too slow
165 fn test_unsafe_slice() {
166     assert_eq!("ab", unsafe { "abc".get_unchecked(0..2) });
167     assert_eq!("bc", unsafe { "abc".get_unchecked(1..3) });
168     assert_eq!("", unsafe { "abc".get_unchecked(1..1) });
169     fn a_million_letter_a() -> String {
170         let mut i = 0;
171         let mut rs = String::new();
172         while i < 100000 {
173             rs.push_str("aaaaaaaaaa");
174             i += 1;
175         }
176         rs
177     }
178     fn half_a_million_letter_a() -> String {
179         let mut i = 0;
180         let mut rs = String::new();
181         while i < 100000 {
182             rs.push_str("aaaaa");
183             i += 1;
184         }
185         rs
186     }
187     let letters = a_million_letter_a();
188     assert_eq!(half_a_million_letter_a(), unsafe { letters.get_unchecked(0..500000) });
189 }
190
191 #[test]
192 fn test_starts_with() {
193     assert!("".starts_with(""));
194     assert!("abc".starts_with(""));
195     assert!("abc".starts_with("a"));
196     assert!(!"a".starts_with("abc"));
197     assert!(!"".starts_with("abc"));
198     assert!(!"ödd".starts_with("-"));
199     assert!("ödd".starts_with("öd"));
200 }
201
202 #[test]
203 fn test_ends_with() {
204     assert!("".ends_with(""));
205     assert!("abc".ends_with(""));
206     assert!("abc".ends_with("c"));
207     assert!(!"a".ends_with("abc"));
208     assert!(!"".ends_with("abc"));
209     assert!(!"ddö".ends_with("-"));
210     assert!("ddö".ends_with("dö"));
211 }
212
213 #[test]
214 fn test_is_empty() {
215     assert!("".is_empty());
216     assert!(!"a".is_empty());
217 }
218
219 #[test]
220 fn test_replacen() {
221     assert_eq!("".replacen('a', "b", 5), "");
222     assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
223     assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
224
225     let test = "test";
226     assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
227     assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
228     assert_eq!(" test test ".replacen(test, "", 5), "   ");
229
230     assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
231 }
232
233 #[test]
234 fn test_replace() {
235     let a = "a";
236     assert_eq!("".replace(a, "b"), "");
237     assert_eq!("a".replace(a, "b"), "b");
238     assert_eq!("ab".replace(a, "b"), "bb");
239     let test = "test";
240     assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
241     assert_eq!(" test test ".replace(test, ""), "   ");
242 }
243
244 #[test]
245 fn test_replace_2a() {
246     let data = "ประเทศไทย中华";
247     let repl = "دولة الكويت";
248
249     let a = "ประเ";
250     let a2 = "دولة الكويتทศไทย中华";
251     assert_eq!(data.replace(a, repl), a2);
252 }
253
254 #[test]
255 fn test_replace_2b() {
256     let data = "ประเทศไทย中华";
257     let repl = "دولة الكويت";
258
259     let b = "ะเ";
260     let b2 = "ปรدولة الكويتทศไทย中华";
261     assert_eq!(data.replace(b, repl), b2);
262 }
263
264 #[test]
265 fn test_replace_2c() {
266     let data = "ประเทศไทย中华";
267     let repl = "دولة الكويت";
268
269     let c = "中华";
270     let c2 = "ประเทศไทยدولة الكويت";
271     assert_eq!(data.replace(c, repl), c2);
272 }
273
274 #[test]
275 fn test_replace_2d() {
276     let data = "ประเทศไทย中华";
277     let repl = "دولة الكويت";
278
279     let d = "ไท华";
280     assert_eq!(data.replace(d, repl), data);
281 }
282
283 #[test]
284 fn test_replace_pattern() {
285     let data = "abcdαβγδabcdαβγδ";
286     assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
287     assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
288     assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
289     assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
290 }
291
292 // The current implementation of SliceIndex fails to handle methods
293 // orthogonally from range types; therefore, it is worth testing
294 // all of the indexing operations on each input.
295 mod slice_index {
296     // Test a slicing operation **that should succeed,**
297     // testing it on all of the indexing methods.
298     //
299     // This is not suitable for testing failure on invalid inputs.
300     macro_rules! assert_range_eq {
301         ($s:expr, $range:expr, $expected:expr) => {
302             let mut s: String = $s.to_owned();
303             let mut expected: String = $expected.to_owned();
304             {
305                 let s: &str = &s;
306                 let expected: &str = &expected;
307
308                 assert_eq!(&s[$range], expected, "(in assertion for: index)");
309                 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
310                 unsafe {
311                     assert_eq!(
312                         s.get_unchecked($range),
313                         expected,
314                         "(in assertion for: get_unchecked)",
315                     );
316                 }
317             }
318             {
319                 let s: &mut str = &mut s;
320                 let expected: &mut str = &mut expected;
321
322                 assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",);
323                 assert_eq!(
324                     s.get_mut($range),
325                     Some(&mut expected[..]),
326                     "(in assertion for: get_mut)",
327                 );
328                 unsafe {
329                     assert_eq!(
330                         s.get_unchecked_mut($range),
331                         expected,
332                         "(in assertion for: get_unchecked_mut)",
333                     );
334                 }
335             }
336         };
337     }
338
339     // Make sure the macro can actually detect bugs,
340     // because if it can't, then what are we even doing here?
341     //
342     // (Be aware this only demonstrates the ability to detect bugs
343     //  in the FIRST method that panics, as the macro is not designed
344     //  to be used in `should_panic`)
345     #[test]
346     #[should_panic(expected = "out of bounds")]
347     fn assert_range_eq_can_fail_by_panic() {
348         assert_range_eq!("abc", 0..5, "abc");
349     }
350
351     // (Be aware this only demonstrates the ability to detect bugs
352     //  in the FIRST method it calls, as the macro is not designed
353     //  to be used in `should_panic`)
354     #[test]
355     #[should_panic(expected = "==")]
356     fn assert_range_eq_can_fail_by_inequality() {
357         assert_range_eq!("abc", 0..2, "abc");
358     }
359
360     // Generates test cases for bad index operations.
361     //
362     // This generates `should_panic` test cases for Index/IndexMut
363     // and `None` test cases for get/get_mut.
364     macro_rules! panic_cases {
365         ($(
366             in mod $case_name:ident {
367                 data: $data:expr;
368
369                 // optional:
370                 //
371                 // a similar input for which DATA[input] succeeds, and the corresponding
372                 // output str. This helps validate "critical points" where an input range
373                 // straddles the boundary between valid and invalid.
374                 // (such as the input `len..len`, which is just barely valid)
375                 $(
376                     good: data[$good:expr] == $output:expr;
377                 )*
378
379                 bad: data[$bad:expr];
380                 message: $expect_msg:expr; // must be a literal
381             }
382         )*) => {$(
383             mod $case_name {
384                 #[test]
385                 fn pass() {
386                     let mut v: String = $data.into();
387
388                     $( assert_range_eq!(v, $good, $output); )*
389
390                     {
391                         let v: &str = &v;
392                         assert_eq!(v.get($bad), None, "(in None assertion for get)");
393                     }
394
395                     {
396                         let v: &mut str = &mut v;
397                         assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
398                     }
399                 }
400
401                 #[test]
402                 #[should_panic(expected = $expect_msg)]
403                 fn index_fail() {
404                     let v: String = $data.into();
405                     let v: &str = &v;
406                     let _v = &v[$bad];
407                 }
408
409                 #[test]
410                 #[should_panic(expected = $expect_msg)]
411                 fn index_mut_fail() {
412                     let mut v: String = $data.into();
413                     let v: &mut str = &mut v;
414                     let _v = &mut v[$bad];
415                 }
416             }
417         )*};
418     }
419
420     #[test]
421     fn simple_ascii() {
422         assert_range_eq!("abc", .., "abc");
423
424         assert_range_eq!("abc", 0..2, "ab");
425         assert_range_eq!("abc", 0..=1, "ab");
426         assert_range_eq!("abc", ..2, "ab");
427         assert_range_eq!("abc", ..=1, "ab");
428
429         assert_range_eq!("abc", 1..3, "bc");
430         assert_range_eq!("abc", 1..=2, "bc");
431         assert_range_eq!("abc", 1..1, "");
432         assert_range_eq!("abc", 1..=0, "");
433     }
434
435     #[test]
436     fn simple_unicode() {
437         // 日本
438         assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
439
440         assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
441         assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
442         assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
443         assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
444
445         assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
446         assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
447         assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
448
449         let data = "ประเทศไทย中华";
450         assert_range_eq!(data, 0..3, "ป");
451         assert_range_eq!(data, 3..6, "ร");
452         assert_range_eq!(data, 3..3, "");
453         assert_range_eq!(data, 30..33, "华");
454
455         /*0: 中
456          3: 华
457          6: V
458          7: i
459          8: ệ
460         11: t
461         12:
462         13: N
463         14: a
464         15: m */
465         let ss = "中华Việt Nam";
466         assert_range_eq!(ss, 3..6, "华");
467         assert_range_eq!(ss, 6..16, "Việt Nam");
468         assert_range_eq!(ss, 6..=15, "Việt Nam");
469         assert_range_eq!(ss, 6.., "Việt Nam");
470
471         assert_range_eq!(ss, 0..3, "中");
472         assert_range_eq!(ss, 3..7, "华V");
473         assert_range_eq!(ss, 3..=6, "华V");
474         assert_range_eq!(ss, 3..3, "");
475         assert_range_eq!(ss, 3..=2, "");
476     }
477
478     #[test]
479     #[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM
480     #[cfg_attr(miri, ignore)] // Miri is too slow
481     fn simple_big() {
482         fn a_million_letter_x() -> String {
483             let mut i = 0;
484             let mut rs = String::new();
485             while i < 100000 {
486                 rs.push_str("华华华华华华华华华华");
487                 i += 1;
488             }
489             rs
490         }
491         fn half_a_million_letter_x() -> String {
492             let mut i = 0;
493             let mut rs = String::new();
494             while i < 100000 {
495                 rs.push_str("华华华华华");
496                 i += 1;
497             }
498             rs
499         }
500         let letters = a_million_letter_x();
501         assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
502     }
503
504     #[test]
505     #[should_panic]
506     fn test_slice_fail() {
507         &"中华Việt Nam"[0..2];
508     }
509
510     panic_cases! {
511         in mod rangefrom_len {
512             data: "abcdef";
513             good: data[6..] == "";
514             bad: data[7..];
515             message: "out of bounds";
516         }
517
518         in mod rangeto_len {
519             data: "abcdef";
520             good: data[..6] == "abcdef";
521             bad: data[..7];
522             message: "out of bounds";
523         }
524
525         in mod rangetoinclusive_len {
526             data: "abcdef";
527             good: data[..=5] == "abcdef";
528             bad: data[..=6];
529             message: "out of bounds";
530         }
531
532         in mod range_len_len {
533             data: "abcdef";
534             good: data[6..6] == "";
535             bad: data[7..7];
536             message: "out of bounds";
537         }
538
539         in mod rangeinclusive_len_len {
540             data: "abcdef";
541             good: data[6..=5] == "";
542             bad: data[7..=6];
543             message: "out of bounds";
544         }
545     }
546
547     panic_cases! {
548         in mod range_neg_width {
549             data: "abcdef";
550             good: data[4..4] == "";
551             bad: data[4..3];
552             message: "begin <= end (4 <= 3)";
553         }
554
555         in mod rangeinclusive_neg_width {
556             data: "abcdef";
557             good: data[4..=3] == "";
558             bad: data[4..=2];
559             message: "begin <= end (4 <= 3)";
560         }
561     }
562
563     mod overflow {
564         panic_cases! {
565             in mod rangeinclusive {
566                 data: "hello";
567                 // note: using 0 specifically ensures that the result of overflowing is 0..0,
568                 //       so that `get` doesn't simply return None for the wrong reason.
569                 bad: data[0..=usize::MAX];
570                 message: "maximum usize";
571             }
572
573             in mod rangetoinclusive {
574                 data: "hello";
575                 bad: data[..=usize::MAX];
576                 message: "maximum usize";
577             }
578         }
579     }
580
581     mod boundary {
582         const DATA: &str = "abcαβγ";
583
584         const BAD_START: usize = 4;
585         const GOOD_START: usize = 3;
586         const BAD_END: usize = 6;
587         const GOOD_END: usize = 7;
588         const BAD_END_INCL: usize = BAD_END - 1;
589         const GOOD_END_INCL: usize = GOOD_END - 1;
590
591         // it is especially important to test all of the different range types here
592         // because some of the logic may be duplicated as part of micro-optimizations
593         // to dodge unicode boundary checks on half-ranges.
594         panic_cases! {
595             in mod range_1 {
596                 data: super::DATA;
597                 bad: data[super::BAD_START..super::GOOD_END];
598                 message:
599                     "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
600             }
601
602             in mod range_2 {
603                 data: super::DATA;
604                 bad: data[super::GOOD_START..super::BAD_END];
605                 message:
606                     "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
607             }
608
609             in mod rangefrom {
610                 data: super::DATA;
611                 bad: data[super::BAD_START..];
612                 message:
613                     "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
614             }
615
616             in mod rangeto {
617                 data: super::DATA;
618                 bad: data[..super::BAD_END];
619                 message:
620                     "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
621             }
622
623             in mod rangeinclusive_1 {
624                 data: super::DATA;
625                 bad: data[super::BAD_START..=super::GOOD_END_INCL];
626                 message:
627                     "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
628             }
629
630             in mod rangeinclusive_2 {
631                 data: super::DATA;
632                 bad: data[super::GOOD_START..=super::BAD_END_INCL];
633                 message:
634                     "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
635             }
636
637             in mod rangetoinclusive {
638                 data: super::DATA;
639                 bad: data[..=super::BAD_END_INCL];
640                 message:
641                     "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
642             }
643         }
644     }
645
646     const LOREM_PARAGRAPH: &str = "\
647     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \
648     sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \
649     quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \
650     nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \
651     tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \
652     gravida nec quam.";
653
654     // check the panic includes the prefix of the sliced string
655     #[test]
656     #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
657     fn test_slice_fail_truncated_1() {
658         &LOREM_PARAGRAPH[..1024];
659     }
660     // check the truncation in the panic message
661     #[test]
662     #[should_panic(expected = "luctus, im`[...]")]
663     fn test_slice_fail_truncated_2() {
664         &LOREM_PARAGRAPH[..1024];
665     }
666 }
667
668 #[test]
669 fn test_str_slice_rangetoinclusive_ok() {
670     let s = "abcαβγ";
671     assert_eq!(&s[..=2], "abc");
672     assert_eq!(&s[..=4], "abcα");
673 }
674
675 #[test]
676 #[should_panic]
677 fn test_str_slice_rangetoinclusive_notok() {
678     let s = "abcαβγ";
679     &s[..=3];
680 }
681
682 #[test]
683 fn test_str_slicemut_rangetoinclusive_ok() {
684     let mut s = "abcαβγ".to_owned();
685     let s: &mut str = &mut s;
686     assert_eq!(&mut s[..=2], "abc");
687     assert_eq!(&mut s[..=4], "abcα");
688 }
689
690 #[test]
691 #[should_panic]
692 fn test_str_slicemut_rangetoinclusive_notok() {
693     let mut s = "abcαβγ".to_owned();
694     let s: &mut str = &mut s;
695     &mut s[..=3];
696 }
697
698 #[test]
699 fn test_is_char_boundary() {
700     let s = "ศไทย中华Việt Nam β-release 🐱123";
701     assert!(s.is_char_boundary(0));
702     assert!(s.is_char_boundary(s.len()));
703     assert!(!s.is_char_boundary(s.len() + 1));
704     for (i, ch) in s.char_indices() {
705         // ensure character locations are boundaries and continuation bytes are not
706         assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
707         for j in 1..ch.len_utf8() {
708             assert!(
709                 !s.is_char_boundary(i + j),
710                 "{} should not be a char boundary in {:?}",
711                 i + j,
712                 s
713             );
714         }
715     }
716 }
717
718 #[test]
719 fn test_trim_start_matches() {
720     let v: &[char] = &[];
721     assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
722     let chars: &[char] = &['*', ' '];
723     assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
724     assert_eq!(" ***  *** ".trim_start_matches(chars), "");
725     assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
726
727     assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
728     let chars: &[char] = &['1', '2'];
729     assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
730     assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
731 }
732
733 #[test]
734 fn test_trim_end_matches() {
735     let v: &[char] = &[];
736     assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
737     let chars: &[char] = &['*', ' '];
738     assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
739     assert_eq!(" ***  *** ".trim_end_matches(chars), "");
740     assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
741
742     assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
743     let chars: &[char] = &['1', '2'];
744     assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
745     assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
746 }
747
748 #[test]
749 fn test_trim_matches() {
750     let v: &[char] = &[];
751     assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
752     let chars: &[char] = &['*', ' '];
753     assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
754     assert_eq!(" ***  *** ".trim_matches(chars), "");
755     assert_eq!("foo".trim_matches(chars), "foo");
756
757     assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
758     let chars: &[char] = &['1', '2'];
759     assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
760     assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
761 }
762
763 #[test]
764 fn test_trim_start() {
765     assert_eq!("".trim_start(), "");
766     assert_eq!("a".trim_start(), "a");
767     assert_eq!("    ".trim_start(), "");
768     assert_eq!("     blah".trim_start(), "blah");
769     assert_eq!("   \u{3000}  wut".trim_start(), "wut");
770     assert_eq!("hey ".trim_start(), "hey ");
771 }
772
773 #[test]
774 fn test_trim_end() {
775     assert_eq!("".trim_end(), "");
776     assert_eq!("a".trim_end(), "a");
777     assert_eq!("    ".trim_end(), "");
778     assert_eq!("blah     ".trim_end(), "blah");
779     assert_eq!("wut   \u{3000}  ".trim_end(), "wut");
780     assert_eq!(" hey".trim_end(), " hey");
781 }
782
783 #[test]
784 fn test_trim() {
785     assert_eq!("".trim(), "");
786     assert_eq!("a".trim(), "a");
787     assert_eq!("    ".trim(), "");
788     assert_eq!("    blah     ".trim(), "blah");
789     assert_eq!("\nwut   \u{3000}  ".trim(), "wut");
790     assert_eq!(" hey dude ".trim(), "hey dude");
791 }
792
793 #[test]
794 fn test_is_whitespace() {
795     assert!("".chars().all(|c| c.is_whitespace()));
796     assert!(" ".chars().all(|c| c.is_whitespace()));
797     assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
798     assert!("  \n\t   ".chars().all(|c| c.is_whitespace()));
799     assert!(!"   _   ".chars().all(|c| c.is_whitespace()));
800 }
801
802 #[test]
803 fn test_is_utf8() {
804     // deny overlong encodings
805     assert!(from_utf8(&[0xc0, 0x80]).is_err());
806     assert!(from_utf8(&[0xc0, 0xae]).is_err());
807     assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
808     assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
809     assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
810     assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
811     assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
812
813     // deny surrogates
814     assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
815     assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
816
817     assert!(from_utf8(&[0xC2, 0x80]).is_ok());
818     assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
819     assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
820     assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
821     assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
822     assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
823     assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
824     assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
825 }
826
827 #[test]
828 fn from_utf8_mostly_ascii() {
829     // deny invalid bytes embedded in long stretches of ascii
830     for i in 32..64 {
831         let mut data = [0; 128];
832         data[i] = 0xC0;
833         assert!(from_utf8(&data).is_err());
834         data[i] = 0xC2;
835         assert!(from_utf8(&data).is_err());
836     }
837 }
838
839 #[test]
840 fn from_utf8_error() {
841     macro_rules! test {
842         ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
843             let error = from_utf8($input).unwrap_err();
844             assert_eq!(error.valid_up_to(), $expected_valid_up_to);
845             assert_eq!(error.error_len(), $expected_error_len);
846         };
847     }
848     test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
849     test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
850     test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
851     test!(b"A\xC3\xA9 \xC1", 4, Some(1));
852     test!(b"A\xC3\xA9 \xC2", 4, None);
853     test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
854     test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
855     test!(b"A\xC3\xA9 \xE0", 4, None);
856     test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
857     test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
858     test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
859     test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
860     test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
861     test!(b"A\xC3\xA9 \xF1", 4, None);
862     test!(b"A\xC3\xA9 \xF1\x80", 4, None);
863     test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
864     test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
865     test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
866     test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
867 }
868
869 #[test]
870 fn test_as_bytes() {
871     // no null
872     let v = [
873         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
874         86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
875     ];
876     let b: &[u8] = &[];
877     assert_eq!("".as_bytes(), b);
878     assert_eq!("abc".as_bytes(), b"abc");
879     assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
880 }
881
882 #[test]
883 #[should_panic]
884 fn test_as_bytes_fail() {
885     // Don't double free. (I'm not sure if this exercises the
886     // original problem code path anymore.)
887     let s = String::from("");
888     let _bytes = s.as_bytes();
889     panic!();
890 }
891
892 #[test]
893 fn test_as_ptr() {
894     let buf = "hello".as_ptr();
895     unsafe {
896         assert_eq!(*buf.offset(0), b'h');
897         assert_eq!(*buf.offset(1), b'e');
898         assert_eq!(*buf.offset(2), b'l');
899         assert_eq!(*buf.offset(3), b'l');
900         assert_eq!(*buf.offset(4), b'o');
901     }
902 }
903
904 #[test]
905 fn vec_str_conversions() {
906     let s1: String = String::from("All mimsy were the borogoves");
907
908     let v: Vec<u8> = s1.as_bytes().to_vec();
909     let s2: String = String::from(from_utf8(&v).unwrap());
910     let mut i = 0;
911     let n1 = s1.len();
912     let n2 = v.len();
913     assert_eq!(n1, n2);
914     while i < n1 {
915         let a: u8 = s1.as_bytes()[i];
916         let b: u8 = s2.as_bytes()[i];
917         assert_eq!(a, b);
918         i += 1;
919     }
920 }
921
922 #[test]
923 fn test_contains() {
924     assert!("abcde".contains("bcd"));
925     assert!("abcde".contains("abcd"));
926     assert!("abcde".contains("bcde"));
927     assert!("abcde".contains(""));
928     assert!("".contains(""));
929     assert!(!"abcde".contains("def"));
930     assert!(!"".contains("a"));
931
932     let data = "ประเทศไทย中华Việt Nam";
933     assert!(data.contains("ประเ"));
934     assert!(data.contains("ะเ"));
935     assert!(data.contains("中华"));
936     assert!(!data.contains("ไท华"));
937 }
938
939 #[test]
940 fn test_contains_char() {
941     assert!("abc".contains('b'));
942     assert!("a".contains('a'));
943     assert!(!"abc".contains('d'));
944     assert!(!"".contains('a'));
945 }
946
947 #[test]
948 fn test_split_at() {
949     let s = "ศไทย中华Việt Nam";
950     for (index, _) in s.char_indices() {
951         let (a, b) = s.split_at(index);
952         assert_eq!(&s[..a.len()], a);
953         assert_eq!(&s[a.len()..], b);
954     }
955     let (a, b) = s.split_at(s.len());
956     assert_eq!(a, s);
957     assert_eq!(b, "");
958 }
959
960 #[test]
961 fn test_split_at_mut() {
962     let mut s = "Hello World".to_string();
963     {
964         let (a, b) = s.split_at_mut(5);
965         a.make_ascii_uppercase();
966         b.make_ascii_lowercase();
967     }
968     assert_eq!(s, "HELLO world");
969 }
970
971 #[test]
972 #[should_panic]
973 fn test_split_at_boundscheck() {
974     let s = "ศไทย中华Việt Nam";
975     s.split_at(1);
976 }
977
978 #[test]
979 fn test_escape_unicode() {
980     assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}");
981     assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
982     assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
983     assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
984     assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
985     assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
986     assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
987     assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
988     assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}");
989 }
990
991 #[test]
992 fn test_escape_debug() {
993     // Note that there are subtleties with the number of backslashes
994     // on the left- and right-hand sides. In particular, Unicode code points
995     // are usually escaped with two backslashes on the right-hand side, as
996     // they are escaped. However, when the character is unescaped (e.g., for
997     // printable characters), only a single backslash appears (as the character
998     // itself appears in the debug string).
999     assert_eq!("abc".escape_debug().to_string(), "abc");
1000     assert_eq!("a c".escape_debug().to_string(), "a c");
1001     assert_eq!("éèê".escape_debug().to_string(), "éèê");
1002     assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1003     assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1004     assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1005     assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1006     assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1007     assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1008     assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1009     assert_eq!(
1010         "\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1011         "\\u{301}a\u{301}bé\\u{e000}"
1012     );
1013 }
1014
1015 #[test]
1016 fn test_escape_default() {
1017     assert_eq!("abc".escape_default().to_string(), "abc");
1018     assert_eq!("a c".escape_default().to_string(), "a c");
1019     assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1020     assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1021     assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1022     assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1023     assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1024     assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1025     assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1026     assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1027 }
1028
1029 #[test]
1030 fn test_total_ord() {
1031     assert_eq!("1234".cmp("123"), Greater);
1032     assert_eq!("123".cmp("1234"), Less);
1033     assert_eq!("1234".cmp("1234"), Equal);
1034     assert_eq!("12345555".cmp("123456"), Less);
1035     assert_eq!("22".cmp("1234"), Greater);
1036 }
1037
1038 #[test]
1039 fn test_iterator() {
1040     let s = "ศไทย中华Việt Nam";
1041     let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1042
1043     let mut pos = 0;
1044     let it = s.chars();
1045
1046     for c in it {
1047         assert_eq!(c, v[pos]);
1048         pos += 1;
1049     }
1050     assert_eq!(pos, v.len());
1051     assert_eq!(s.chars().count(), v.len());
1052 }
1053
1054 #[test]
1055 fn test_rev_iterator() {
1056     let s = "ศไทย中华Việt Nam";
1057     let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1058
1059     let mut pos = 0;
1060     let it = s.chars().rev();
1061
1062     for c in it {
1063         assert_eq!(c, v[pos]);
1064         pos += 1;
1065     }
1066     assert_eq!(pos, v.len());
1067 }
1068
1069 #[test]
1070 #[cfg_attr(miri, ignore)] // Miri is too slow
1071 fn test_chars_decoding() {
1072     let mut bytes = [0; 4];
1073     for c in (0..0x110000).filter_map(std::char::from_u32) {
1074         let s = c.encode_utf8(&mut bytes);
1075         if Some(c) != s.chars().next() {
1076             panic!("character {:x}={} does not decode correctly", c as u32, c);
1077         }
1078     }
1079 }
1080
1081 #[test]
1082 #[cfg_attr(miri, ignore)] // Miri is too slow
1083 fn test_chars_rev_decoding() {
1084     let mut bytes = [0; 4];
1085     for c in (0..0x110000).filter_map(std::char::from_u32) {
1086         let s = c.encode_utf8(&mut bytes);
1087         if Some(c) != s.chars().rev().next() {
1088             panic!("character {:x}={} does not decode correctly", c as u32, c);
1089         }
1090     }
1091 }
1092
1093 #[test]
1094 fn test_iterator_clone() {
1095     let s = "ศไทย中华Việt Nam";
1096     let mut it = s.chars();
1097     it.next();
1098     assert!(it.clone().zip(it).all(|(x, y)| x == y));
1099 }
1100
1101 #[test]
1102 fn test_iterator_last() {
1103     let s = "ศไทย中华Việt Nam";
1104     let mut it = s.chars();
1105     it.next();
1106     assert_eq!(it.last(), Some('m'));
1107 }
1108
1109 #[test]
1110 fn test_chars_debug() {
1111     let s = "ศไทย中华Việt Nam";
1112     let c = s.chars();
1113     assert_eq!(
1114         format!("{:?}", c),
1115         r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"#
1116     );
1117 }
1118
1119 #[test]
1120 fn test_bytesator() {
1121     let s = "ศไทย中华Việt Nam";
1122     let v = [
1123         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1124         86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1125     ];
1126     let mut pos = 0;
1127
1128     for b in s.bytes() {
1129         assert_eq!(b, v[pos]);
1130         pos += 1;
1131     }
1132 }
1133
1134 #[test]
1135 fn test_bytes_revator() {
1136     let s = "ศไทย中华Việt Nam";
1137     let v = [
1138         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1139         86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1140     ];
1141     let mut pos = v.len();
1142
1143     for b in s.bytes().rev() {
1144         pos -= 1;
1145         assert_eq!(b, v[pos]);
1146     }
1147 }
1148
1149 #[test]
1150 fn test_bytesator_nth() {
1151     let s = "ศไทย中华Việt Nam";
1152     let v = [
1153         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142,
1154         86, 105, 225, 187, 135, 116, 32, 78, 97, 109,
1155     ];
1156
1157     let mut b = s.bytes();
1158     assert_eq!(b.nth(2).unwrap(), v[2]);
1159     assert_eq!(b.nth(10).unwrap(), v[10]);
1160     assert_eq!(b.nth(200), None);
1161 }
1162
1163 #[test]
1164 fn test_bytesator_count() {
1165     let s = "ศไทย中华Việt Nam";
1166
1167     let b = s.bytes();
1168     assert_eq!(b.count(), 28)
1169 }
1170
1171 #[test]
1172 fn test_bytesator_last() {
1173     let s = "ศไทย中华Việt Nam";
1174
1175     let b = s.bytes();
1176     assert_eq!(b.last().unwrap(), 109)
1177 }
1178
1179 #[test]
1180 fn test_char_indicesator() {
1181     let s = "ศไทย中华Việt Nam";
1182     let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1183     let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'];
1184
1185     let mut pos = 0;
1186     let it = s.char_indices();
1187
1188     for c in it {
1189         assert_eq!(c, (p[pos], v[pos]));
1190         pos += 1;
1191     }
1192     assert_eq!(pos, v.len());
1193     assert_eq!(pos, p.len());
1194 }
1195
1196 #[test]
1197 fn test_char_indices_revator() {
1198     let s = "ศไทย中华Việt Nam";
1199     let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1200     let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ'];
1201
1202     let mut pos = 0;
1203     let it = s.char_indices().rev();
1204
1205     for c in it {
1206         assert_eq!(c, (p[pos], v[pos]));
1207         pos += 1;
1208     }
1209     assert_eq!(pos, v.len());
1210     assert_eq!(pos, p.len());
1211 }
1212
1213 #[test]
1214 fn test_char_indices_last() {
1215     let s = "ศไทย中华Việt Nam";
1216     let mut it = s.char_indices();
1217     it.next();
1218     assert_eq!(it.last(), Some((27, 'm')));
1219 }
1220
1221 #[test]
1222 fn test_splitn_char_iterator() {
1223     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1224
1225     let split: Vec<&str> = data.splitn(4, ' ').collect();
1226     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1227
1228     let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1229     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1230
1231     // Unicode
1232     let split: Vec<&str> = data.splitn(4, 'ä').collect();
1233     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1234
1235     let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1236     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1237 }
1238
1239 #[test]
1240 fn test_split_char_iterator_no_trailing() {
1241     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1242
1243     let split: Vec<&str> = data.split('\n').collect();
1244     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1245
1246     let split: Vec<&str> = data.split_terminator('\n').collect();
1247     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1248 }
1249
1250 #[test]
1251 fn test_split_char_iterator_inclusive() {
1252     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1253
1254     let split: Vec<&str> = data.split_inclusive('\n').collect();
1255     assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]);
1256
1257     let uppercase_separated = "SheePSharKTurtlECaT";
1258     let mut first_char = true;
1259     let split: Vec<&str> = uppercase_separated
1260         .split_inclusive(|c: char| {
1261             let split = !first_char && c.is_uppercase();
1262             first_char = split;
1263             split
1264         })
1265         .collect();
1266     assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]);
1267 }
1268
1269 #[test]
1270 fn test_split_char_iterator_inclusive_rev() {
1271     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1272
1273     let split: Vec<&str> = data.split_inclusive('\n').rev().collect();
1274     assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]);
1275
1276     // Note that the predicate is stateful and thus dependent
1277     // on the iteration order.
1278     // (A different predicate is needed for reverse iterator vs normal iterator.)
1279     // Not sure if anything can be done though.
1280     let uppercase_separated = "SheePSharKTurtlECaT";
1281     let mut term_char = true;
1282     let split: Vec<&str> = uppercase_separated
1283         .split_inclusive(|c: char| {
1284             let split = term_char && c.is_uppercase();
1285             term_char = c.is_uppercase();
1286             split
1287         })
1288         .rev()
1289         .collect();
1290     assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]);
1291 }
1292
1293 #[test]
1294 fn test_rsplit() {
1295     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1296
1297     let split: Vec<&str> = data.rsplit(' ').collect();
1298     assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1299
1300     let split: Vec<&str> = data.rsplit("lämb").collect();
1301     assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1302
1303     let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1304     assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1305 }
1306
1307 #[test]
1308 fn test_rsplitn() {
1309     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1310
1311     let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1312     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1313
1314     let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1315     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1316
1317     let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1318     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1319 }
1320
1321 #[test]
1322 fn test_split_once() {
1323     assert_eq!("".split_once("->"), None);
1324     assert_eq!("-".split_once("->"), None);
1325     assert_eq!("->".split_once("->"), Some(("", "")));
1326     assert_eq!("a->".split_once("->"), Some(("a", "")));
1327     assert_eq!("->b".split_once("->"), Some(("", "b")));
1328     assert_eq!("a->b".split_once("->"), Some(("a", "b")));
1329     assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c")));
1330     assert_eq!("---".split_once("--"), Some(("", "-")));
1331 }
1332
1333 #[test]
1334 fn test_rsplit_once() {
1335     assert_eq!("".rsplit_once("->"), None);
1336     assert_eq!("-".rsplit_once("->"), None);
1337     assert_eq!("->".rsplit_once("->"), Some(("", "")));
1338     assert_eq!("a->".rsplit_once("->"), Some(("a", "")));
1339     assert_eq!("->b".rsplit_once("->"), Some(("", "b")));
1340     assert_eq!("a->b".rsplit_once("->"), Some(("a", "b")));
1341     assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c")));
1342     assert_eq!("---".rsplit_once("--"), Some(("-", "")));
1343 }
1344
1345 #[test]
1346 fn test_split_whitespace() {
1347     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
1348     let words: Vec<&str> = data.split_whitespace().collect();
1349     assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1350 }
1351
1352 #[test]
1353 fn test_lines() {
1354     let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1355     let lines: Vec<&str> = data.lines().collect();
1356     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1357
1358     let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1359     let lines: Vec<&str> = data.lines().collect();
1360     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1361 }
1362
1363 #[test]
1364 fn test_splitator() {
1365     fn t(s: &str, sep: &str, u: &[&str]) {
1366         let v: Vec<&str> = s.split(sep).collect();
1367         assert_eq!(v, u);
1368     }
1369     t("--1233345--", "12345", &["--1233345--"]);
1370     t("abc::hello::there", "::", &["abc", "hello", "there"]);
1371     t("::hello::there", "::", &["", "hello", "there"]);
1372     t("hello::there::", "::", &["hello", "there", ""]);
1373     t("::hello::there::", "::", &["", "hello", "there", ""]);
1374     t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1375     t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1376     t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1377     t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1378     t("", ".", &[""]);
1379     t("zz", "zz", &["", ""]);
1380     t("ok", "z", &["ok"]);
1381     t("zzz", "zz", &["", "z"]);
1382     t("zzzzz", "zz", &["", "", "z"]);
1383 }
1384
1385 #[test]
1386 fn test_str_default() {
1387     use std::default::Default;
1388
1389     fn t<S: Default + AsRef<str>>() {
1390         let s: S = Default::default();
1391         assert_eq!(s.as_ref(), "");
1392     }
1393
1394     t::<&str>();
1395     t::<String>();
1396     t::<&mut str>();
1397 }
1398
1399 #[test]
1400 fn test_str_container() {
1401     fn sum_len(v: &[&str]) -> usize {
1402         v.iter().map(|x| x.len()).sum()
1403     }
1404
1405     let s = "01234";
1406     assert_eq!(5, sum_len(&["012", "", "34"]));
1407     assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1408     assert_eq!(5, sum_len(&[s]));
1409 }
1410
1411 #[test]
1412 fn test_str_from_utf8() {
1413     let xs = b"hello";
1414     assert_eq!(from_utf8(xs), Ok("hello"));
1415
1416     let xs = "ศไทย中华Việt Nam".as_bytes();
1417     assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1418
1419     let xs = b"hello\xFF";
1420     assert!(from_utf8(xs).is_err());
1421 }
1422
1423 #[test]
1424 fn test_pattern_deref_forward() {
1425     let data = "aabcdaa";
1426     assert!(data.contains("bcd"));
1427     assert!(data.contains(&"bcd"));
1428     assert!(data.contains(&"bcd".to_string()));
1429 }
1430
1431 #[test]
1432 fn test_empty_match_indices() {
1433     let data = "aä中!";
1434     let vec: Vec<_> = data.match_indices("").collect();
1435     assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1436 }
1437
1438 #[test]
1439 fn test_bool_from_str() {
1440     assert_eq!("true".parse().ok(), Some(true));
1441     assert_eq!("false".parse().ok(), Some(false));
1442     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1443 }
1444
1445 fn check_contains_all_substrings(s: &str) {
1446     assert!(s.contains(""));
1447     for i in 0..s.len() {
1448         for j in i + 1..=s.len() {
1449             assert!(s.contains(&s[i..j]));
1450         }
1451     }
1452 }
1453
1454 #[test]
1455 #[cfg_attr(miri, ignore)] // Miri is too slow
1456 fn strslice_issue_16589() {
1457     assert!("bananas".contains("nana"));
1458
1459     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1460     // test all substrings for good measure
1461     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1462 }
1463
1464 #[test]
1465 fn strslice_issue_16878() {
1466     assert!(!"1234567ah012345678901ah".contains("hah"));
1467     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1468 }
1469
1470 #[test]
1471 #[cfg_attr(miri, ignore)] // Miri is too slow
1472 fn test_strslice_contains() {
1473     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1474     check_contains_all_substrings(x);
1475 }
1476
1477 #[test]
1478 fn test_rsplitn_char_iterator() {
1479     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1480
1481     let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1482     split.reverse();
1483     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1484
1485     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1486     split.reverse();
1487     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1488
1489     // Unicode
1490     let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1491     split.reverse();
1492     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1493
1494     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1495     split.reverse();
1496     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1497 }
1498
1499 #[test]
1500 fn test_split_char_iterator() {
1501     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1502
1503     let split: Vec<&str> = data.split(' ').collect();
1504     assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1505
1506     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1507     rsplit.reverse();
1508     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1509
1510     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1511     assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1512
1513     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1514     rsplit.reverse();
1515     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1516
1517     // Unicode
1518     let split: Vec<&str> = data.split('ä').collect();
1519     assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1520
1521     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1522     rsplit.reverse();
1523     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1524
1525     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1526     assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1527
1528     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1529     rsplit.reverse();
1530     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1531 }
1532
1533 #[test]
1534 fn test_rev_split_char_iterator_no_trailing() {
1535     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1536
1537     let mut split: Vec<&str> = data.split('\n').rev().collect();
1538     split.reverse();
1539     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1540
1541     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1542     split.reverse();
1543     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1544 }
1545
1546 #[test]
1547 fn test_utf16_code_units() {
1548     assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9])
1549 }
1550
1551 #[test]
1552 fn starts_with_in_unicode() {
1553     assert!(!"├── Cargo.toml".starts_with("# "));
1554 }
1555
1556 #[test]
1557 fn starts_short_long() {
1558     assert!(!"".starts_with("##"));
1559     assert!(!"##".starts_with("####"));
1560     assert!("####".starts_with("##"));
1561     assert!(!"##ä".starts_with("####"));
1562     assert!("####ä".starts_with("##"));
1563     assert!(!"##".starts_with("####ä"));
1564     assert!("##ä##".starts_with("##ä"));
1565
1566     assert!("".starts_with(""));
1567     assert!("ä".starts_with(""));
1568     assert!("#ä".starts_with(""));
1569     assert!("##ä".starts_with(""));
1570     assert!("ä###".starts_with(""));
1571     assert!("#ä##".starts_with(""));
1572     assert!("##ä#".starts_with(""));
1573 }
1574
1575 #[test]
1576 fn contains_weird_cases() {
1577     assert!("* \t".contains(' '));
1578     assert!(!"* \t".contains('?'));
1579     assert!(!"* \t".contains('\u{1F4A9}'));
1580 }
1581
1582 #[test]
1583 fn trim_ws() {
1584     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()), "a \t  ");
1585     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()), " \t  a");
1586     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()), "a \t  ");
1587     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()), " \t  a");
1588     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()), "a");
1589     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()), "");
1590     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()), "");
1591     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()), "");
1592     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()), "");
1593     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()), "");
1594 }
1595
1596 #[test]
1597 fn to_lowercase() {
1598     assert_eq!("".to_lowercase(), "");
1599     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1600
1601     // https://github.com/rust-lang/rust/issues/26035
1602     assert_eq!("ΑΣ".to_lowercase(), "ας");
1603     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1604     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1605
1606     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1607     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1608     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1609
1610     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1611     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1612
1613     assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1614     assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1615
1616     assert_eq!("Α Σ".to_lowercase(), "α σ");
1617     assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1618     assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1619
1620     assert_eq!("Σ".to_lowercase(), "σ");
1621     assert_eq!("'Σ".to_lowercase(), "'σ");
1622     assert_eq!("''Σ".to_lowercase(), "''σ");
1623
1624     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1625     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1626     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1627 }
1628
1629 #[test]
1630 fn to_uppercase() {
1631     assert_eq!("".to_uppercase(), "");
1632     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1633 }
1634
1635 #[test]
1636 fn test_into_string() {
1637     // The only way to acquire a Box<str> in the first place is through a String, so just
1638     // test that we can round-trip between Box<str> and String.
1639     let string = String::from("Some text goes here");
1640     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1641 }
1642
1643 #[test]
1644 fn test_box_slice_clone() {
1645     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1646     let data2 = data.clone().into_boxed_str().clone().into_string();
1647
1648     assert_eq!(data, data2);
1649 }
1650
1651 #[test]
1652 fn test_cow_from() {
1653     let borrowed = "borrowed";
1654     let owned = String::from("owned");
1655     match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1656         (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1657         _ => panic!("invalid `Cow::from`"),
1658     }
1659 }
1660
1661 #[test]
1662 fn test_repeat() {
1663     assert_eq!("".repeat(3), "");
1664     assert_eq!("abc".repeat(0), "");
1665     assert_eq!("α".repeat(3), "ααα");
1666 }
1667
1668 mod pattern {
1669     use std::str::pattern::SearchStep::{self, Done, Match, Reject};
1670     use std::str::pattern::{Pattern, ReverseSearcher, Searcher};
1671
1672     macro_rules! make_test {
1673         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1674             #[allow(unused_imports)]
1675             mod $name {
1676                 use std::str::pattern::SearchStep::{Match, Reject};
1677                 use super::{cmp_search_to_vec};
1678                 #[test]
1679                 fn fwd() {
1680                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1681                 }
1682                 #[test]
1683                 fn bwd() {
1684                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1685                 }
1686             }
1687         }
1688     }
1689
1690     fn cmp_search_to_vec<'a>(
1691         rev: bool,
1692         pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
1693         haystack: &'a str,
1694         right: Vec<SearchStep>,
1695     ) {
1696         let mut searcher = pat.into_searcher(haystack);
1697         let mut v = vec![];
1698         loop {
1699             match if !rev { searcher.next() } else { searcher.next_back() } {
1700                 Match(a, b) => v.push(Match(a, b)),
1701                 Reject(a, b) => v.push(Reject(a, b)),
1702                 Done => break,
1703             }
1704         }
1705         if rev {
1706             v.reverse();
1707         }
1708
1709         let mut first_index = 0;
1710         let mut err = None;
1711
1712         for (i, e) in right.iter().enumerate() {
1713             match *e {
1714                 Match(a, b) | Reject(a, b) if a <= b && a == first_index => {
1715                     first_index = b;
1716                 }
1717                 _ => {
1718                     err = Some(i);
1719                     break;
1720                 }
1721             }
1722         }
1723
1724         if let Some(err) = err {
1725             panic!("Input skipped range at {}", err);
1726         }
1727
1728         if first_index != haystack.len() {
1729             panic!("Did not cover whole input");
1730         }
1731
1732         assert_eq!(v, right);
1733     }
1734
1735     make_test!(
1736         str_searcher_ascii_haystack,
1737         "bb",
1738         "abbcbbd",
1739         [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),]
1740     );
1741     make_test!(
1742         str_searcher_ascii_haystack_seq,
1743         "bb",
1744         "abbcbbbbd",
1745         [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),]
1746     );
1747     make_test!(
1748         str_searcher_empty_needle_ascii_haystack,
1749         "",
1750         "abbcbbd",
1751         [
1752             Match(0, 0),
1753             Reject(0, 1),
1754             Match(1, 1),
1755             Reject(1, 2),
1756             Match(2, 2),
1757             Reject(2, 3),
1758             Match(3, 3),
1759             Reject(3, 4),
1760             Match(4, 4),
1761             Reject(4, 5),
1762             Match(5, 5),
1763             Reject(5, 6),
1764             Match(6, 6),
1765             Reject(6, 7),
1766             Match(7, 7),
1767         ]
1768     );
1769     make_test!(
1770         str_searcher_multibyte_haystack,
1771         " ",
1772         "├──",
1773         [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1774     );
1775     make_test!(
1776         str_searcher_empty_needle_multibyte_haystack,
1777         "",
1778         "├──",
1779         [
1780             Match(0, 0),
1781             Reject(0, 3),
1782             Match(3, 3),
1783             Reject(3, 6),
1784             Match(6, 6),
1785             Reject(6, 9),
1786             Match(9, 9),
1787         ]
1788     );
1789     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]);
1790     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []);
1791     make_test!(
1792         char_searcher_ascii_haystack,
1793         'b',
1794         "abbcbbd",
1795         [
1796             Reject(0, 1),
1797             Match(1, 2),
1798             Match(2, 3),
1799             Reject(3, 4),
1800             Match(4, 5),
1801             Match(5, 6),
1802             Reject(6, 7),
1803         ]
1804     );
1805     make_test!(
1806         char_searcher_multibyte_haystack,
1807         ' ',
1808         "├──",
1809         [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1810     );
1811     make_test!(
1812         char_searcher_short_haystack,
1813         '\u{1F4A9}',
1814         "* \t",
1815         [Reject(0, 1), Reject(1, 2), Reject(2, 3),]
1816     );
1817 }
1818
1819 macro_rules! generate_iterator_test {
1820     {
1821         $name:ident {
1822             $(
1823                 ($($arg:expr),*) -> [$($t:tt)*];
1824             )*
1825         }
1826         with $fwd:expr, $bwd:expr;
1827     } => {
1828         #[test]
1829         fn $name() {
1830             $(
1831                 {
1832                     let res = vec![$($t)*];
1833
1834                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1835                     assert_eq!(fwd_vec, res);
1836
1837                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1838                     bwd_vec.reverse();
1839                     assert_eq!(bwd_vec, res);
1840                 }
1841             )*
1842         }
1843     };
1844     {
1845         $name:ident {
1846             $(
1847                 ($($arg:expr),*) -> [$($t:tt)*];
1848             )*
1849         }
1850         with $fwd:expr;
1851     } => {
1852         #[test]
1853         fn $name() {
1854             $(
1855                 {
1856                     let res = vec![$($t)*];
1857
1858                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1859                     assert_eq!(fwd_vec, res);
1860                 }
1861             )*
1862         }
1863     }
1864 }
1865
1866 generate_iterator_test! {
1867     double_ended_split {
1868         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1869         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1870     }
1871     with str::split, str::rsplit;
1872 }
1873
1874 generate_iterator_test! {
1875     double_ended_split_terminator {
1876         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1877     }
1878     with str::split_terminator, str::rsplit_terminator;
1879 }
1880
1881 generate_iterator_test! {
1882     double_ended_matches {
1883         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1884     }
1885     with str::matches, str::rmatches;
1886 }
1887
1888 generate_iterator_test! {
1889     double_ended_match_indices {
1890         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1891     }
1892     with str::match_indices, str::rmatch_indices;
1893 }
1894
1895 generate_iterator_test! {
1896     not_double_ended_splitn {
1897         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1898     }
1899     with str::splitn;
1900 }
1901
1902 generate_iterator_test! {
1903     not_double_ended_rsplitn {
1904         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1905     }
1906     with str::rsplitn;
1907 }
1908
1909 #[test]
1910 fn different_str_pattern_forwarding_lifetimes() {
1911     use std::str::pattern::Pattern;
1912
1913     fn foo<'a, P>(p: P)
1914     where
1915         for<'b> &'b P: Pattern<'a>,
1916     {
1917         for _ in 0..3 {
1918             "asdf".find(&p);
1919         }
1920     }
1921
1922     foo::<&str>("x");
1923 }