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