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