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