]> git.lizzy.rs Git - rust.git/blob - src/liballoc/tests/str.rs
Auto merge of #68659 - Dylan-DPC:rollup-zo7zi9f, r=Dylan-DPC
[rust.git] / src / liballoc / 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_value()];
570                 message: "maximum usize";
571             }
572
573             in mod rangetoinclusive {
574                 data: "hello";
575                 bad: data[..=usize::max_value()];
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_rsplit() {
1252     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1253
1254     let split: Vec<&str> = data.rsplit(' ').collect();
1255     assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1256
1257     let split: Vec<&str> = data.rsplit("lämb").collect();
1258     assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1259
1260     let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1261     assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1262 }
1263
1264 #[test]
1265 fn test_rsplitn() {
1266     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1267
1268     let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1269     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1270
1271     let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1272     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1273
1274     let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1275     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1276 }
1277
1278 #[test]
1279 fn test_split_whitespace() {
1280     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
1281     let words: Vec<&str> = data.split_whitespace().collect();
1282     assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1283 }
1284
1285 #[test]
1286 fn test_lines() {
1287     let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1288     let lines: Vec<&str> = data.lines().collect();
1289     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1290
1291     let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1292     let lines: Vec<&str> = data.lines().collect();
1293     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1294 }
1295
1296 #[test]
1297 fn test_splitator() {
1298     fn t(s: &str, sep: &str, u: &[&str]) {
1299         let v: Vec<&str> = s.split(sep).collect();
1300         assert_eq!(v, u);
1301     }
1302     t("--1233345--", "12345", &["--1233345--"]);
1303     t("abc::hello::there", "::", &["abc", "hello", "there"]);
1304     t("::hello::there", "::", &["", "hello", "there"]);
1305     t("hello::there::", "::", &["hello", "there", ""]);
1306     t("::hello::there::", "::", &["", "hello", "there", ""]);
1307     t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1308     t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1309     t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1310     t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1311     t("", ".", &[""]);
1312     t("zz", "zz", &["", ""]);
1313     t("ok", "z", &["ok"]);
1314     t("zzz", "zz", &["", "z"]);
1315     t("zzzzz", "zz", &["", "", "z"]);
1316 }
1317
1318 #[test]
1319 fn test_str_default() {
1320     use std::default::Default;
1321
1322     fn t<S: Default + AsRef<str>>() {
1323         let s: S = Default::default();
1324         assert_eq!(s.as_ref(), "");
1325     }
1326
1327     t::<&str>();
1328     t::<String>();
1329     t::<&mut str>();
1330 }
1331
1332 #[test]
1333 fn test_str_container() {
1334     fn sum_len(v: &[&str]) -> usize {
1335         v.iter().map(|x| x.len()).sum()
1336     }
1337
1338     let s = "01234";
1339     assert_eq!(5, sum_len(&["012", "", "34"]));
1340     assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1341     assert_eq!(5, sum_len(&[s]));
1342 }
1343
1344 #[test]
1345 fn test_str_from_utf8() {
1346     let xs = b"hello";
1347     assert_eq!(from_utf8(xs), Ok("hello"));
1348
1349     let xs = "ศไทย中华Việt Nam".as_bytes();
1350     assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1351
1352     let xs = b"hello\xFF";
1353     assert!(from_utf8(xs).is_err());
1354 }
1355
1356 #[test]
1357 fn test_pattern_deref_forward() {
1358     let data = "aabcdaa";
1359     assert!(data.contains("bcd"));
1360     assert!(data.contains(&"bcd"));
1361     assert!(data.contains(&"bcd".to_string()));
1362 }
1363
1364 #[test]
1365 fn test_empty_match_indices() {
1366     let data = "aä中!";
1367     let vec: Vec<_> = data.match_indices("").collect();
1368     assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1369 }
1370
1371 #[test]
1372 fn test_bool_from_str() {
1373     assert_eq!("true".parse().ok(), Some(true));
1374     assert_eq!("false".parse().ok(), Some(false));
1375     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1376 }
1377
1378 fn check_contains_all_substrings(s: &str) {
1379     assert!(s.contains(""));
1380     for i in 0..s.len() {
1381         for j in i + 1..=s.len() {
1382             assert!(s.contains(&s[i..j]));
1383         }
1384     }
1385 }
1386
1387 #[test]
1388 #[cfg_attr(miri, ignore)] // Miri is too slow
1389 fn strslice_issue_16589() {
1390     assert!("bananas".contains("nana"));
1391
1392     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1393     // test all substrings for good measure
1394     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1395 }
1396
1397 #[test]
1398 fn strslice_issue_16878() {
1399     assert!(!"1234567ah012345678901ah".contains("hah"));
1400     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1401 }
1402
1403 #[test]
1404 #[cfg_attr(miri, ignore)] // Miri is too slow
1405 fn test_strslice_contains() {
1406     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1407     check_contains_all_substrings(x);
1408 }
1409
1410 #[test]
1411 fn test_rsplitn_char_iterator() {
1412     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1413
1414     let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1415     split.reverse();
1416     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1417
1418     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1419     split.reverse();
1420     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1421
1422     // Unicode
1423     let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1424     split.reverse();
1425     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1426
1427     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1428     split.reverse();
1429     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1430 }
1431
1432 #[test]
1433 fn test_split_char_iterator() {
1434     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1435
1436     let split: Vec<&str> = data.split(' ').collect();
1437     assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1438
1439     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1440     rsplit.reverse();
1441     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1442
1443     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1444     assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1445
1446     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1447     rsplit.reverse();
1448     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1449
1450     // Unicode
1451     let split: Vec<&str> = data.split('ä').collect();
1452     assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1453
1454     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1455     rsplit.reverse();
1456     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1457
1458     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1459     assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1460
1461     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1462     rsplit.reverse();
1463     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1464 }
1465
1466 #[test]
1467 fn test_rev_split_char_iterator_no_trailing() {
1468     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1469
1470     let mut split: Vec<&str> = data.split('\n').rev().collect();
1471     split.reverse();
1472     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1473
1474     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1475     split.reverse();
1476     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1477 }
1478
1479 #[test]
1480 fn test_utf16_code_units() {
1481     assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9])
1482 }
1483
1484 #[test]
1485 fn starts_with_in_unicode() {
1486     assert!(!"├── Cargo.toml".starts_with("# "));
1487 }
1488
1489 #[test]
1490 fn starts_short_long() {
1491     assert!(!"".starts_with("##"));
1492     assert!(!"##".starts_with("####"));
1493     assert!("####".starts_with("##"));
1494     assert!(!"##ä".starts_with("####"));
1495     assert!("####ä".starts_with("##"));
1496     assert!(!"##".starts_with("####ä"));
1497     assert!("##ä##".starts_with("##ä"));
1498
1499     assert!("".starts_with(""));
1500     assert!("ä".starts_with(""));
1501     assert!("#ä".starts_with(""));
1502     assert!("##ä".starts_with(""));
1503     assert!("ä###".starts_with(""));
1504     assert!("#ä##".starts_with(""));
1505     assert!("##ä#".starts_with(""));
1506 }
1507
1508 #[test]
1509 fn contains_weird_cases() {
1510     assert!("* \t".contains(' '));
1511     assert!(!"* \t".contains('?'));
1512     assert!(!"* \t".contains('\u{1F4A9}'));
1513 }
1514
1515 #[test]
1516 fn trim_ws() {
1517     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()), "a \t  ");
1518     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()), " \t  a");
1519     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()), "a \t  ");
1520     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()), " \t  a");
1521     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()), "a");
1522     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()), "");
1523     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()), "");
1524     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()), "");
1525     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()), "");
1526     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()), "");
1527 }
1528
1529 #[test]
1530 fn to_lowercase() {
1531     assert_eq!("".to_lowercase(), "");
1532     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1533
1534     // https://github.com/rust-lang/rust/issues/26035
1535     assert_eq!("ΑΣ".to_lowercase(), "ας");
1536     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1537     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1538
1539     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1540     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1541     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1542
1543     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1544     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1545
1546     assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1547     assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1548
1549     assert_eq!("Α Σ".to_lowercase(), "α σ");
1550     assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1551     assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1552
1553     assert_eq!("Σ".to_lowercase(), "σ");
1554     assert_eq!("'Σ".to_lowercase(), "'σ");
1555     assert_eq!("''Σ".to_lowercase(), "''σ");
1556
1557     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1558     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1559     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1560 }
1561
1562 #[test]
1563 fn to_uppercase() {
1564     assert_eq!("".to_uppercase(), "");
1565     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1566 }
1567
1568 #[test]
1569 fn test_into_string() {
1570     // The only way to acquire a Box<str> in the first place is through a String, so just
1571     // test that we can round-trip between Box<str> and String.
1572     let string = String::from("Some text goes here");
1573     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1574 }
1575
1576 #[test]
1577 fn test_box_slice_clone() {
1578     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1579     let data2 = data.clone().into_boxed_str().clone().into_string();
1580
1581     assert_eq!(data, data2);
1582 }
1583
1584 #[test]
1585 fn test_cow_from() {
1586     let borrowed = "borrowed";
1587     let owned = String::from("owned");
1588     match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1589         (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1590         _ => panic!("invalid `Cow::from`"),
1591     }
1592 }
1593
1594 #[test]
1595 fn test_repeat() {
1596     assert_eq!("".repeat(3), "");
1597     assert_eq!("abc".repeat(0), "");
1598     assert_eq!("α".repeat(3), "ααα");
1599 }
1600
1601 mod pattern {
1602     use std::str::pattern::SearchStep::{self, Done, Match, Reject};
1603     use std::str::pattern::{Pattern, ReverseSearcher, Searcher};
1604
1605     macro_rules! make_test {
1606         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1607             #[allow(unused_imports)]
1608             mod $name {
1609                 use std::str::pattern::SearchStep::{Match, Reject};
1610                 use super::{cmp_search_to_vec};
1611                 #[test]
1612                 fn fwd() {
1613                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1614                 }
1615                 #[test]
1616                 fn bwd() {
1617                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1618                 }
1619             }
1620         }
1621     }
1622
1623     fn cmp_search_to_vec<'a>(
1624         rev: bool,
1625         pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
1626         haystack: &'a str,
1627         right: Vec<SearchStep>,
1628     ) {
1629         let mut searcher = pat.into_searcher(haystack);
1630         let mut v = vec![];
1631         loop {
1632             match if !rev { searcher.next() } else { searcher.next_back() } {
1633                 Match(a, b) => v.push(Match(a, b)),
1634                 Reject(a, b) => v.push(Reject(a, b)),
1635                 Done => break,
1636             }
1637         }
1638         if rev {
1639             v.reverse();
1640         }
1641
1642         let mut first_index = 0;
1643         let mut err = None;
1644
1645         for (i, e) in right.iter().enumerate() {
1646             match *e {
1647                 Match(a, b) | Reject(a, b) if a <= b && a == first_index => {
1648                     first_index = b;
1649                 }
1650                 _ => {
1651                     err = Some(i);
1652                     break;
1653                 }
1654             }
1655         }
1656
1657         if let Some(err) = err {
1658             panic!("Input skipped range at {}", err);
1659         }
1660
1661         if first_index != haystack.len() {
1662             panic!("Did not cover whole input");
1663         }
1664
1665         assert_eq!(v, right);
1666     }
1667
1668     make_test!(
1669         str_searcher_ascii_haystack,
1670         "bb",
1671         "abbcbbd",
1672         [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),]
1673     );
1674     make_test!(
1675         str_searcher_ascii_haystack_seq,
1676         "bb",
1677         "abbcbbbbd",
1678         [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),]
1679     );
1680     make_test!(
1681         str_searcher_empty_needle_ascii_haystack,
1682         "",
1683         "abbcbbd",
1684         [
1685             Match(0, 0),
1686             Reject(0, 1),
1687             Match(1, 1),
1688             Reject(1, 2),
1689             Match(2, 2),
1690             Reject(2, 3),
1691             Match(3, 3),
1692             Reject(3, 4),
1693             Match(4, 4),
1694             Reject(4, 5),
1695             Match(5, 5),
1696             Reject(5, 6),
1697             Match(6, 6),
1698             Reject(6, 7),
1699             Match(7, 7),
1700         ]
1701     );
1702     make_test!(
1703         str_searcher_multibyte_haystack,
1704         " ",
1705         "├──",
1706         [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1707     );
1708     make_test!(
1709         str_searcher_empty_needle_multibyte_haystack,
1710         "",
1711         "├──",
1712         [
1713             Match(0, 0),
1714             Reject(0, 3),
1715             Match(3, 3),
1716             Reject(3, 6),
1717             Match(6, 6),
1718             Reject(6, 9),
1719             Match(9, 9),
1720         ]
1721     );
1722     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]);
1723     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []);
1724     make_test!(
1725         char_searcher_ascii_haystack,
1726         'b',
1727         "abbcbbd",
1728         [
1729             Reject(0, 1),
1730             Match(1, 2),
1731             Match(2, 3),
1732             Reject(3, 4),
1733             Match(4, 5),
1734             Match(5, 6),
1735             Reject(6, 7),
1736         ]
1737     );
1738     make_test!(
1739         char_searcher_multibyte_haystack,
1740         ' ',
1741         "├──",
1742         [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1743     );
1744     make_test!(
1745         char_searcher_short_haystack,
1746         '\u{1F4A9}',
1747         "* \t",
1748         [Reject(0, 1), Reject(1, 2), Reject(2, 3),]
1749     );
1750 }
1751
1752 macro_rules! generate_iterator_test {
1753     {
1754         $name:ident {
1755             $(
1756                 ($($arg:expr),*) -> [$($t:tt)*];
1757             )*
1758         }
1759         with $fwd:expr, $bwd:expr;
1760     } => {
1761         #[test]
1762         fn $name() {
1763             $(
1764                 {
1765                     let res = vec![$($t)*];
1766
1767                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1768                     assert_eq!(fwd_vec, res);
1769
1770                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1771                     bwd_vec.reverse();
1772                     assert_eq!(bwd_vec, res);
1773                 }
1774             )*
1775         }
1776     };
1777     {
1778         $name:ident {
1779             $(
1780                 ($($arg:expr),*) -> [$($t:tt)*];
1781             )*
1782         }
1783         with $fwd:expr;
1784     } => {
1785         #[test]
1786         fn $name() {
1787             $(
1788                 {
1789                     let res = vec![$($t)*];
1790
1791                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1792                     assert_eq!(fwd_vec, res);
1793                 }
1794             )*
1795         }
1796     }
1797 }
1798
1799 generate_iterator_test! {
1800     double_ended_split {
1801         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1802         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1803     }
1804     with str::split, str::rsplit;
1805 }
1806
1807 generate_iterator_test! {
1808     double_ended_split_terminator {
1809         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1810     }
1811     with str::split_terminator, str::rsplit_terminator;
1812 }
1813
1814 generate_iterator_test! {
1815     double_ended_matches {
1816         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1817     }
1818     with str::matches, str::rmatches;
1819 }
1820
1821 generate_iterator_test! {
1822     double_ended_match_indices {
1823         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1824     }
1825     with str::match_indices, str::rmatch_indices;
1826 }
1827
1828 generate_iterator_test! {
1829     not_double_ended_splitn {
1830         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1831     }
1832     with str::splitn;
1833 }
1834
1835 generate_iterator_test! {
1836     not_double_ended_rsplitn {
1837         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1838     }
1839     with str::rsplitn;
1840 }
1841
1842 #[test]
1843 fn different_str_pattern_forwarding_lifetimes() {
1844     use std::str::pattern::Pattern;
1845
1846     fn foo<'a, P>(p: P)
1847     where
1848         for<'b> &'b P: Pattern<'a>,
1849     {
1850         for _ in 0..3 {
1851             "asdf".find(&p);
1852         }
1853     }
1854
1855     foo::<&str>("x");
1856 }