]> git.lizzy.rs Git - rust.git/blob - library/alloc/tests/str.rs
Unify Opaque/Projection handling in region outlives code
[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(haystack: &str) {
1594     let mut modified_needle = String::new();
1595
1596     for i in 0..haystack.len() {
1597         // check different haystack lengths since we special-case short haystacks.
1598         let haystack = &haystack[0..i];
1599         assert!(haystack.contains(""));
1600         for j in 0..haystack.len() {
1601             for k in j + 1..=haystack.len() {
1602                 let needle = &haystack[j..k];
1603                 assert!(haystack.contains(needle));
1604                 modified_needle.clear();
1605                 modified_needle.push_str(needle);
1606                 modified_needle.replace_range(0..1, "\0");
1607                 assert!(!haystack.contains(&modified_needle));
1608
1609                 modified_needle.clear();
1610                 modified_needle.push_str(needle);
1611                 modified_needle.replace_range(needle.len() - 1..needle.len(), "\0");
1612                 assert!(!haystack.contains(&modified_needle));
1613             }
1614         }
1615     }
1616 }
1617
1618 #[test]
1619 #[cfg_attr(miri, ignore)] // Miri is too slow
1620 fn strslice_issue_16589() {
1621     assert!("bananas".contains("nana"));
1622
1623     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1624     // test all substrings for good measure
1625     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1626 }
1627
1628 #[test]
1629 fn strslice_issue_16878() {
1630     assert!(!"1234567ah012345678901ah".contains("hah"));
1631     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1632 }
1633
1634 #[test]
1635 fn strslice_issue_104726() {
1636     // Edge-case in the simd_contains impl.
1637     // The first and last byte are the same so it backtracks by one byte
1638     // which aligns with the end of the string. Previously incorrect offset calculations
1639     // lead to out-of-bounds slicing.
1640     #[rustfmt::skip]
1641     let needle =                        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaba";
1642     let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
1643     assert!(!haystack.contains(needle));
1644 }
1645
1646 #[test]
1647 #[cfg_attr(miri, ignore)] // Miri is too slow
1648 fn test_strslice_contains() {
1649     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1650     check_contains_all_substrings(x);
1651 }
1652
1653 #[test]
1654 fn test_rsplitn_char_iterator() {
1655     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1656
1657     let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1658     split.reverse();
1659     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1660
1661     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1662     split.reverse();
1663     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1664
1665     // Unicode
1666     let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1667     split.reverse();
1668     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1669
1670     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1671     split.reverse();
1672     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1673 }
1674
1675 #[test]
1676 fn test_split_char_iterator() {
1677     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1678
1679     let split: Vec<&str> = data.split(' ').collect();
1680     assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1681
1682     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1683     rsplit.reverse();
1684     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1685
1686     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1687     assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1688
1689     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1690     rsplit.reverse();
1691     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1692
1693     // Unicode
1694     let split: Vec<&str> = data.split('ä').collect();
1695     assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1696
1697     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1698     rsplit.reverse();
1699     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1700
1701     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1702     assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1703
1704     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1705     rsplit.reverse();
1706     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1707 }
1708
1709 #[test]
1710 fn test_rev_split_char_iterator_no_trailing() {
1711     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1712
1713     let mut split: Vec<&str> = data.split('\n').rev().collect();
1714     split.reverse();
1715     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1716
1717     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1718     split.reverse();
1719     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1720 }
1721
1722 #[test]
1723 fn test_utf16_code_units() {
1724     assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9])
1725 }
1726
1727 #[test]
1728 fn starts_with_in_unicode() {
1729     assert!(!"├── Cargo.toml".starts_with("# "));
1730 }
1731
1732 #[test]
1733 fn starts_short_long() {
1734     assert!(!"".starts_with("##"));
1735     assert!(!"##".starts_with("####"));
1736     assert!("####".starts_with("##"));
1737     assert!(!"##ä".starts_with("####"));
1738     assert!("####ä".starts_with("##"));
1739     assert!(!"##".starts_with("####ä"));
1740     assert!("##ä##".starts_with("##ä"));
1741
1742     assert!("".starts_with(""));
1743     assert!("ä".starts_with(""));
1744     assert!("#ä".starts_with(""));
1745     assert!("##ä".starts_with(""));
1746     assert!("ä###".starts_with(""));
1747     assert!("#ä##".starts_with(""));
1748     assert!("##ä#".starts_with(""));
1749 }
1750
1751 #[test]
1752 fn contains_weird_cases() {
1753     assert!("* \t".contains(' '));
1754     assert!(!"* \t".contains('?'));
1755     assert!(!"* \t".contains('\u{1F4A9}'));
1756 }
1757
1758 #[test]
1759 fn trim_ws() {
1760     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()), "a \t  ");
1761     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()), " \t  a");
1762     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()), "a \t  ");
1763     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()), " \t  a");
1764     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()), "a");
1765     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()), "");
1766     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()), "");
1767     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()), "");
1768     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()), "");
1769     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()), "");
1770 }
1771
1772 #[test]
1773 fn to_lowercase() {
1774     assert_eq!("".to_lowercase(), "");
1775     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1776
1777     // https://github.com/rust-lang/rust/issues/26035
1778     assert_eq!("ΑΣ".to_lowercase(), "ας");
1779     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1780     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1781
1782     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1783     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1784     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1785
1786     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1787     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1788
1789     assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1790     assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1791
1792     assert_eq!("Α Σ".to_lowercase(), "α σ");
1793     assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1794     assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1795
1796     assert_eq!("Σ".to_lowercase(), "σ");
1797     assert_eq!("'Σ".to_lowercase(), "'σ");
1798     assert_eq!("''Σ".to_lowercase(), "''σ");
1799
1800     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1801     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1802     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1803
1804     // a really long string that has it's lowercase form
1805     // even longer. this tests that implementations don't assume
1806     // an incorrect upper bound on allocations
1807     let upper = str::repeat("İ", 512);
1808     let lower = str::repeat("i̇", 512);
1809     assert_eq!(upper.to_lowercase(), lower);
1810
1811     // a really long ascii-only string.
1812     // This test that the ascii hot-path
1813     // functions correctly
1814     let upper = str::repeat("A", 511);
1815     let lower = str::repeat("a", 511);
1816     assert_eq!(upper.to_lowercase(), lower);
1817 }
1818
1819 #[test]
1820 fn to_uppercase() {
1821     assert_eq!("".to_uppercase(), "");
1822     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1823 }
1824
1825 #[test]
1826 fn test_into_string() {
1827     // The only way to acquire a Box<str> in the first place is through a String, so just
1828     // test that we can round-trip between Box<str> and String.
1829     let string = String::from("Some text goes here");
1830     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1831 }
1832
1833 #[test]
1834 fn test_box_slice_clone() {
1835     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1836     let data2 = data.clone().into_boxed_str().clone().into_string();
1837
1838     assert_eq!(data, data2);
1839 }
1840
1841 #[test]
1842 fn test_cow_from() {
1843     let borrowed = "borrowed";
1844     let owned = String::from("owned");
1845     match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1846         (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1847         _ => panic!("invalid `Cow::from`"),
1848     }
1849 }
1850
1851 #[test]
1852 fn test_repeat() {
1853     assert_eq!("".repeat(3), "");
1854     assert_eq!("abc".repeat(0), "");
1855     assert_eq!("α".repeat(3), "ααα");
1856 }
1857
1858 mod pattern {
1859     use std::str::pattern::SearchStep::{self, Done, Match, Reject};
1860     use std::str::pattern::{Pattern, ReverseSearcher, Searcher};
1861
1862     macro_rules! make_test {
1863         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1864             #[allow(unused_imports)]
1865             mod $name {
1866                 use std::str::pattern::SearchStep::{Match, Reject};
1867                 use super::{cmp_search_to_vec};
1868                 #[test]
1869                 fn fwd() {
1870                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1871                 }
1872                 #[test]
1873                 fn bwd() {
1874                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1875                 }
1876             }
1877         }
1878     }
1879
1880     fn cmp_search_to_vec<'a>(
1881         rev: bool,
1882         pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>,
1883         haystack: &'a str,
1884         right: Vec<SearchStep>,
1885     ) {
1886         let mut searcher = pat.into_searcher(haystack);
1887         let mut v = vec![];
1888         loop {
1889             match if !rev { searcher.next() } else { searcher.next_back() } {
1890                 Match(a, b) => v.push(Match(a, b)),
1891                 Reject(a, b) => v.push(Reject(a, b)),
1892                 Done => break,
1893             }
1894         }
1895         if rev {
1896             v.reverse();
1897         }
1898
1899         let mut first_index = 0;
1900         let mut err = None;
1901
1902         for (i, e) in right.iter().enumerate() {
1903             match *e {
1904                 Match(a, b) | Reject(a, b) if a <= b && a == first_index => {
1905                     first_index = b;
1906                 }
1907                 _ => {
1908                     err = Some(i);
1909                     break;
1910                 }
1911             }
1912         }
1913
1914         if let Some(err) = err {
1915             panic!("Input skipped range at {err}");
1916         }
1917
1918         if first_index != haystack.len() {
1919             panic!("Did not cover whole input");
1920         }
1921
1922         assert_eq!(v, right);
1923     }
1924
1925     make_test!(
1926         str_searcher_ascii_haystack,
1927         "bb",
1928         "abbcbbd",
1929         [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),]
1930     );
1931     make_test!(
1932         str_searcher_ascii_haystack_seq,
1933         "bb",
1934         "abbcbbbbd",
1935         [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),]
1936     );
1937     make_test!(
1938         str_searcher_empty_needle_ascii_haystack,
1939         "",
1940         "abbcbbd",
1941         [
1942             Match(0, 0),
1943             Reject(0, 1),
1944             Match(1, 1),
1945             Reject(1, 2),
1946             Match(2, 2),
1947             Reject(2, 3),
1948             Match(3, 3),
1949             Reject(3, 4),
1950             Match(4, 4),
1951             Reject(4, 5),
1952             Match(5, 5),
1953             Reject(5, 6),
1954             Match(6, 6),
1955             Reject(6, 7),
1956             Match(7, 7),
1957         ]
1958     );
1959     make_test!(
1960         str_searcher_multibyte_haystack,
1961         " ",
1962         "├──",
1963         [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
1964     );
1965     make_test!(
1966         str_searcher_empty_needle_multibyte_haystack,
1967         "",
1968         "├──",
1969         [
1970             Match(0, 0),
1971             Reject(0, 3),
1972             Match(3, 3),
1973             Reject(3, 6),
1974             Match(6, 6),
1975             Reject(6, 9),
1976             Match(9, 9),
1977         ]
1978     );
1979     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]);
1980     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []);
1981     make_test!(
1982         char_searcher_ascii_haystack,
1983         'b',
1984         "abbcbbd",
1985         [
1986             Reject(0, 1),
1987             Match(1, 2),
1988             Match(2, 3),
1989             Reject(3, 4),
1990             Match(4, 5),
1991             Match(5, 6),
1992             Reject(6, 7),
1993         ]
1994     );
1995     make_test!(
1996         char_searcher_multibyte_haystack,
1997         ' ',
1998         "├──",
1999         [Reject(0, 3), Reject(3, 6), Reject(6, 9),]
2000     );
2001     make_test!(
2002         char_searcher_short_haystack,
2003         '\u{1F4A9}',
2004         "* \t",
2005         [Reject(0, 1), Reject(1, 2), Reject(2, 3),]
2006     );
2007
2008     // See #85462
2009     #[test]
2010     fn str_searcher_empty_needle_after_done() {
2011         // Empty needle and haystack
2012         {
2013             let mut searcher = "".into_searcher("");
2014
2015             assert_eq!(searcher.next(), SearchStep::Match(0, 0));
2016             assert_eq!(searcher.next(), SearchStep::Done);
2017             assert_eq!(searcher.next(), SearchStep::Done);
2018             assert_eq!(searcher.next(), SearchStep::Done);
2019
2020             let mut searcher = "".into_searcher("");
2021
2022             assert_eq!(searcher.next_back(), SearchStep::Match(0, 0));
2023             assert_eq!(searcher.next_back(), SearchStep::Done);
2024             assert_eq!(searcher.next_back(), SearchStep::Done);
2025             assert_eq!(searcher.next_back(), SearchStep::Done);
2026         }
2027         // Empty needle and non-empty haystack
2028         {
2029             let mut searcher = "".into_searcher("a");
2030
2031             assert_eq!(searcher.next(), SearchStep::Match(0, 0));
2032             assert_eq!(searcher.next(), SearchStep::Reject(0, 1));
2033             assert_eq!(searcher.next(), SearchStep::Match(1, 1));
2034             assert_eq!(searcher.next(), SearchStep::Done);
2035             assert_eq!(searcher.next(), SearchStep::Done);
2036             assert_eq!(searcher.next(), SearchStep::Done);
2037
2038             let mut searcher = "".into_searcher("a");
2039
2040             assert_eq!(searcher.next_back(), SearchStep::Match(1, 1));
2041             assert_eq!(searcher.next_back(), SearchStep::Reject(0, 1));
2042             assert_eq!(searcher.next_back(), SearchStep::Match(0, 0));
2043             assert_eq!(searcher.next_back(), SearchStep::Done);
2044             assert_eq!(searcher.next_back(), SearchStep::Done);
2045             assert_eq!(searcher.next_back(), SearchStep::Done);
2046         }
2047     }
2048 }
2049
2050 macro_rules! generate_iterator_test {
2051     {
2052         $name:ident {
2053             $(
2054                 ($($arg:expr),*) -> [$($t:tt)*];
2055             )*
2056         }
2057         with $fwd:expr, $bwd:expr;
2058     } => {
2059         #[test]
2060         fn $name() {
2061             $(
2062                 {
2063                     let res = vec![$($t)*];
2064
2065                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
2066                     assert_eq!(fwd_vec, res);
2067
2068                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
2069                     bwd_vec.reverse();
2070                     assert_eq!(bwd_vec, res);
2071                 }
2072             )*
2073         }
2074     };
2075     {
2076         $name:ident {
2077             $(
2078                 ($($arg:expr),*) -> [$($t:tt)*];
2079             )*
2080         }
2081         with $fwd:expr;
2082     } => {
2083         #[test]
2084         fn $name() {
2085             $(
2086                 {
2087                     let res = vec![$($t)*];
2088
2089                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
2090                     assert_eq!(fwd_vec, res);
2091                 }
2092             )*
2093         }
2094     }
2095 }
2096
2097 generate_iterator_test! {
2098     double_ended_split {
2099         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
2100         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
2101     }
2102     with str::split, str::rsplit;
2103 }
2104
2105 generate_iterator_test! {
2106     double_ended_split_terminator {
2107         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
2108     }
2109     with str::split_terminator, str::rsplit_terminator;
2110 }
2111
2112 generate_iterator_test! {
2113     double_ended_matches {
2114         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
2115     }
2116     with str::matches, str::rmatches;
2117 }
2118
2119 generate_iterator_test! {
2120     double_ended_match_indices {
2121         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
2122     }
2123     with str::match_indices, str::rmatch_indices;
2124 }
2125
2126 generate_iterator_test! {
2127     not_double_ended_splitn {
2128         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
2129     }
2130     with str::splitn;
2131 }
2132
2133 generate_iterator_test! {
2134     not_double_ended_rsplitn {
2135         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
2136     }
2137     with str::rsplitn;
2138 }
2139
2140 #[test]
2141 fn different_str_pattern_forwarding_lifetimes() {
2142     use std::str::pattern::Pattern;
2143
2144     fn foo<'a, P>(p: P)
2145     where
2146         for<'b> &'b P: Pattern<'a>,
2147     {
2148         for _ in 0..3 {
2149             "asdf".find(&p);
2150         }
2151     }
2152
2153     foo::<&str>("x");
2154 }
2155
2156 #[test]
2157 fn test_str_multiline() {
2158     let a: String = "this \
2159 is a test"
2160         .to_string();
2161     let b: String = "this \
2162               is \
2163               another \
2164               test"
2165         .to_string();
2166     assert_eq!(a, "this is a test".to_string());
2167     assert_eq!(b, "this is another test".to_string());
2168 }
2169
2170 #[test]
2171 fn test_str_escapes() {
2172     let x = "\\\\\
2173     ";
2174     assert_eq!(x, r"\\"); // extraneous whitespace stripped
2175 }
2176
2177 #[test]
2178 fn const_str_ptr() {
2179     const A: [u8; 2] = ['h' as u8, 'i' as u8];
2180     const B: &'static [u8; 2] = &A;
2181     const C: *const u8 = B as *const u8;
2182
2183     // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131)
2184     #[cfg(not(miri))]
2185     {
2186         let foo = &A as *const u8;
2187         assert_eq!(foo, C);
2188     }
2189
2190     unsafe {
2191         assert_eq!(from_utf8_unchecked(&A), "hi");
2192         assert_eq!(*C, A[0]);
2193         assert_eq!(*(&B[0] as *const u8), A[0]);
2194     }
2195 }
2196
2197 #[test]
2198 fn utf8() {
2199     let yen: char = '¥'; // 0xa5
2200     let c_cedilla: char = 'ç'; // 0xe7
2201     let thorn: char = 'þ'; // 0xfe
2202     let y_diaeresis: char = 'ÿ'; // 0xff
2203     let pi: char = 'Π'; // 0x3a0
2204
2205     assert_eq!(yen as isize, 0xa5);
2206     assert_eq!(c_cedilla as isize, 0xe7);
2207     assert_eq!(thorn as isize, 0xfe);
2208     assert_eq!(y_diaeresis as isize, 0xff);
2209     assert_eq!(pi as isize, 0x3a0);
2210
2211     assert_eq!(pi as isize, '\u{3a0}' as isize);
2212     assert_eq!('\x0a' as isize, '\n' as isize);
2213
2214     let bhutan: String = "འབྲུག་ཡུལ།".to_string();
2215     let japan: String = "日本".to_string();
2216     let uzbekistan: String = "Ўзбекистон".to_string();
2217     let austria: String = "Österreich".to_string();
2218
2219     let bhutan_e: String =
2220         "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string();
2221     let japan_e: String = "\u{65e5}\u{672c}".to_string();
2222     let uzbekistan_e: String =
2223         "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string();
2224     let austria_e: String = "\u{d6}sterreich".to_string();
2225
2226     let oo: char = 'Ö';
2227     assert_eq!(oo as isize, 0xd6);
2228
2229     fn check_str_eq(a: String, b: String) {
2230         let mut i: isize = 0;
2231         for ab in a.bytes() {
2232             println!("{i}");
2233             println!("{ab}");
2234             let bb: u8 = b.as_bytes()[i as usize];
2235             println!("{bb}");
2236             assert_eq!(ab, bb);
2237             i += 1;
2238         }
2239     }
2240
2241     check_str_eq(bhutan, bhutan_e);
2242     check_str_eq(japan, japan_e);
2243     check_str_eq(uzbekistan, uzbekistan_e);
2244     check_str_eq(austria, austria_e);
2245 }
2246
2247 #[test]
2248 fn utf8_chars() {
2249     // Chars of 1, 2, 3, and 4 bytes
2250     let chs: Vec<char> = vec!['e', 'é', '€', '\u{10000}'];
2251     let s: String = chs.iter().cloned().collect();
2252     let schs: Vec<char> = s.chars().collect();
2253
2254     assert_eq!(s.len(), 10);
2255     assert_eq!(s.chars().count(), 4);
2256     assert_eq!(schs.len(), 4);
2257     assert_eq!(schs.iter().cloned().collect::<String>(), s);
2258
2259     assert!((from_utf8(s.as_bytes()).is_ok()));
2260     // invalid prefix
2261     assert!((!from_utf8(&[0x80]).is_ok()));
2262     // invalid 2 byte prefix
2263     assert!((!from_utf8(&[0xc0]).is_ok()));
2264     assert!((!from_utf8(&[0xc0, 0x10]).is_ok()));
2265     // invalid 3 byte prefix
2266     assert!((!from_utf8(&[0xe0]).is_ok()));
2267     assert!((!from_utf8(&[0xe0, 0x10]).is_ok()));
2268     assert!((!from_utf8(&[0xe0, 0xff, 0x10]).is_ok()));
2269     // invalid 4 byte prefix
2270     assert!((!from_utf8(&[0xf0]).is_ok()));
2271     assert!((!from_utf8(&[0xf0, 0x10]).is_ok()));
2272     assert!((!from_utf8(&[0xf0, 0xff, 0x10]).is_ok()));
2273     assert!((!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok()));
2274 }
2275
2276 #[test]
2277 fn utf8_char_counts() {
2278     let strs = [("e", 1), ("é", 1), ("€", 1), ("\u{10000}", 1), ("eé€\u{10000}", 4)];
2279     let spread = if cfg!(miri) { 4 } else { 8 };
2280     let mut reps = [8, 64, 256, 512]
2281         .iter()
2282         .copied()
2283         .flat_map(|n| n - spread..=n + spread)
2284         .collect::<Vec<usize>>();
2285     if cfg!(not(miri)) {
2286         reps.extend([1024, 1 << 16].iter().copied().flat_map(|n| n - spread..=n + spread));
2287     }
2288     let counts = if cfg!(miri) { 0..1 } else { 0..8 };
2289     let padding = counts.map(|len| " ".repeat(len)).collect::<Vec<String>>();
2290
2291     for repeat in reps {
2292         for (tmpl_str, tmpl_char_count) in strs {
2293             for pad_start in &padding {
2294                 for pad_end in &padding {
2295                     // Create a string with padding...
2296                     let with_padding =
2297                         format!("{}{}{}", pad_start, tmpl_str.repeat(repeat), pad_end);
2298                     // ...and then skip past that padding. This should ensure
2299                     // that we test several different alignments for both head
2300                     // and tail.
2301                     let si = pad_start.len();
2302                     let ei = with_padding.len() - pad_end.len();
2303                     let target = &with_padding[si..ei];
2304
2305                     assert!(!target.starts_with(" ") && !target.ends_with(" "));
2306                     let expected_count = tmpl_char_count * repeat;
2307                     assert_eq!(
2308                         expected_count,
2309                         target.chars().count(),
2310                         "wrong count for `{:?}.repeat({})` (padding: `{:?}`)",
2311                         tmpl_str,
2312                         repeat,
2313                         (pad_start.len(), pad_end.len()),
2314                     );
2315                 }
2316             }
2317         }
2318     }
2319 }
2320
2321 #[test]
2322 fn floor_char_boundary() {
2323     fn check_many(s: &str, arg: impl IntoIterator<Item = usize>, ret: usize) {
2324         for idx in arg {
2325             assert_eq!(
2326                 s.floor_char_boundary(idx),
2327                 ret,
2328                 "{:?}.floor_char_boundary({:?}) != {:?}",
2329                 s,
2330                 idx,
2331                 ret
2332             );
2333         }
2334     }
2335
2336     // edge case
2337     check_many("", [0, 1, isize::MAX as usize, usize::MAX], 0);
2338
2339     // basic check
2340     check_many("x", [0], 0);
2341     check_many("x", [1, isize::MAX as usize, usize::MAX], 1);
2342
2343     // 1-byte chars
2344     check_many("jp", [0], 0);
2345     check_many("jp", [1], 1);
2346     check_many("jp", 2..4, 2);
2347
2348     // 2-byte chars
2349     check_many("ĵƥ", 0..2, 0);
2350     check_many("ĵƥ", 2..4, 2);
2351     check_many("ĵƥ", 4..6, 4);
2352
2353     // 3-byte chars
2354     check_many("日本", 0..3, 0);
2355     check_many("日本", 3..6, 3);
2356     check_many("日本", 6..8, 6);
2357
2358     // 4-byte chars
2359     check_many("🇯🇵", 0..4, 0);
2360     check_many("🇯🇵", 4..8, 4);
2361     check_many("🇯🇵", 8..10, 8);
2362 }
2363
2364 #[test]
2365 fn ceil_char_boundary() {
2366     fn check_many(s: &str, arg: impl IntoIterator<Item = usize>, ret: usize) {
2367         for idx in arg {
2368             assert_eq!(
2369                 s.ceil_char_boundary(idx),
2370                 ret,
2371                 "{:?}.ceil_char_boundary({:?}) != {:?}",
2372                 s,
2373                 idx,
2374                 ret
2375             );
2376         }
2377     }
2378
2379     // edge case
2380     check_many("", [0], 0);
2381
2382     // basic check
2383     check_many("x", [0], 0);
2384     check_many("x", [1], 1);
2385
2386     // 1-byte chars
2387     check_many("jp", [0], 0);
2388     check_many("jp", [1], 1);
2389     check_many("jp", [2], 2);
2390
2391     // 2-byte chars
2392     check_many("ĵƥ", 0..=0, 0);
2393     check_many("ĵƥ", 1..=2, 2);
2394     check_many("ĵƥ", 3..=4, 4);
2395
2396     // 3-byte chars
2397     check_many("日本", 0..=0, 0);
2398     check_many("日本", 1..=3, 3);
2399     check_many("日本", 4..=6, 6);
2400
2401     // 4-byte chars
2402     check_many("🇯🇵", 0..=0, 0);
2403     check_many("🇯🇵", 1..=4, 4);
2404     check_many("🇯🇵", 5..=8, 8);
2405 }
2406
2407 #[test]
2408 #[should_panic]
2409 fn ceil_char_boundary_above_len_panic() {
2410     let _ = "x".ceil_char_boundary(2);
2411 }