2 use std::cmp::Ordering::{Equal, Greater, Less};
3 use std::str::from_utf8;
9 assert!("foo" <= "foo");
10 assert!("foo" != "bar");
15 assert_eq!("hello".find('l'), Some(2));
16 assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
17 assert!("hello".find('x').is_none());
18 assert!("hello".find(|c:char| c == 'x').is_none());
19 assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
20 assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
25 assert_eq!("hello".rfind('l'), Some(3));
26 assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
27 assert!("hello".rfind('x').is_none());
28 assert!("hello".rfind(|c:char| c == 'x').is_none());
29 assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
30 assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
37 let s: String = empty.chars().collect();
39 let data = "ประเทศไทย中";
40 let s: String = data.chars().collect();
45 fn test_into_bytes() {
46 let data = String::from("asdf");
47 let buf = data.into_bytes();
48 assert_eq!(buf, b"asdf");
54 assert_eq!("".find(""), Some(0));
55 assert!("banana".find("apple pie").is_none());
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());
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));
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));
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));
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()
87 .chain(Some(string.len() - ip))
89 let pat = &string[i..ip + j];
90 assert!(match string.find(pat) {
94 assert!(match string.rfind(pat) {
102 fn s(x: &str) -> String { x.to_string() }
104 macro_rules! test_concat {
105 ($expected: expr, $string: expr) => {
107 let s: String = $string.concat();
108 assert_eq!($expected, s);
114 fn test_concat_for_different_types() {
115 test_concat!("ab", vec![s("a"), s("b")]);
116 test_concat!("ab", vec!["a", "b"]);
120 fn test_concat_for_different_lengths() {
121 let empty: &[&str] = &[];
123 test_concat!("", empty);
124 test_concat!("a", ["a"]);
125 test_concat!("ab", ["a", "b"]);
126 test_concat!("abc", ["", "a", "bc"]);
129 macro_rules! test_join {
130 ($expected: expr, $string: expr, $delim: expr) => {
132 let s = $string.join($delim);
133 assert_eq!($expected, s);
139 fn test_join_for_different_types() {
140 test_join!("a-b", ["a", "b"], "-");
141 let hyphen = "-".to_string();
142 test_join!("a-b", [s("a"), s("b")], &*hyphen);
143 test_join!("a-b", vec!["a", "b"], &*hyphen);
144 test_join!("a-b", &*vec!["a", "b"], "-");
145 test_join!("a-b", vec![s("a"), s("b")], "-");
149 fn test_join_for_different_lengths() {
150 let empty: &[&str] = &[];
152 test_join!("", empty, "-");
153 test_join!("a", ["a"], "-");
154 test_join!("a-b", ["a", "b"], "-");
155 test_join!("-a-bc", ["", "a", "bc"], "-");
158 // join has fast paths for small separators up to 4 bytes
159 // this tests the slow paths.
161 fn test_join_for_different_lengths_with_long_separator() {
162 assert_eq!("~~~~~".len(), 15);
164 let empty: &[&str] = &[];
166 test_join!("", empty, "~~~~~");
167 test_join!("a", ["a"], "~~~~~");
168 test_join!("a~~~~~b", ["a", "b"], "~~~~~");
169 test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
174 fn test_unsafe_slice() {
175 assert_eq!("ab", unsafe {"abc".get_unchecked(0..2)});
176 assert_eq!("bc", unsafe {"abc".get_unchecked(1..3)});
177 assert_eq!("", unsafe {"abc".get_unchecked(1..1)});
178 fn a_million_letter_a() -> String {
180 let mut rs = String::new();
182 rs.push_str("aaaaaaaaaa");
187 fn half_a_million_letter_a() -> String {
189 let mut rs = String::new();
191 rs.push_str("aaaaa");
196 let letters = a_million_letter_a();
197 assert_eq!(half_a_million_letter_a(),
198 unsafe { letters.get_unchecked(0..500000)});
202 fn test_starts_with() {
203 assert!("".starts_with(""));
204 assert!("abc".starts_with(""));
205 assert!("abc".starts_with("a"));
206 assert!(!"a".starts_with("abc"));
207 assert!(!"".starts_with("abc"));
208 assert!(!"ödd".starts_with("-"));
209 assert!("ödd".starts_with("öd"));
213 fn test_ends_with() {
214 assert!("".ends_with(""));
215 assert!("abc".ends_with(""));
216 assert!("abc".ends_with("c"));
217 assert!(!"a".ends_with("abc"));
218 assert!(!"".ends_with("abc"));
219 assert!(!"ddö".ends_with("-"));
220 assert!("ddö".ends_with("dö"));
225 assert!("".is_empty());
226 assert!(!"a".is_empty());
231 assert_eq!("".replacen('a', "b", 5), "");
232 assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
233 assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
236 assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
237 assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
238 assert_eq!(" test test ".replacen(test, "", 5), " ");
240 assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
247 assert_eq!("".replace(a, "b"), "");
248 assert_eq!("a".replace(a, "b"), "b");
249 assert_eq!("ab".replace(a, "b"), "bb");
251 assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
252 assert_eq!(" test test ".replace(test, ""), " ");
256 fn test_replace_2a() {
257 let data = "ประเทศไทย中华";
258 let repl = "دولة الكويت";
261 let a2 = "دولة الكويتทศไทย中华";
262 assert_eq!(data.replace(a, repl), a2);
266 fn test_replace_2b() {
267 let data = "ประเทศไทย中华";
268 let repl = "دولة الكويت";
271 let b2 = "ปรدولة الكويتทศไทย中华";
272 assert_eq!(data.replace(b, repl), b2);
276 fn test_replace_2c() {
277 let data = "ประเทศไทย中华";
278 let repl = "دولة الكويت";
281 let c2 = "ประเทศไทยدولة الكويت";
282 assert_eq!(data.replace(c, repl), c2);
286 fn test_replace_2d() {
287 let data = "ประเทศไทย中华";
288 let repl = "دولة الكويت";
291 assert_eq!(data.replace(d, repl), data);
295 fn test_replace_pattern() {
296 let data = "abcdαβγδabcdαβγδ";
297 assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
298 assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
299 assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
300 assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
303 // The current implementation of SliceIndex fails to handle methods
304 // orthogonally from range types; therefore, it is worth testing
305 // all of the indexing operations on each input.
308 // Test a slicing operation **that should succeed,**
309 // testing it on all of the indexing methods.
311 // This is not suitable for testing failure on invalid inputs.
312 macro_rules! assert_range_eq {
313 ($s:expr, $range:expr, $expected:expr)
315 let mut s: String = $s.to_owned();
316 let mut expected: String = $expected.to_owned();
319 let expected: &str = &expected;
321 assert_eq!(&s[$range], expected, "(in assertion for: index)");
322 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
325 s.get_unchecked($range), expected,
326 "(in assertion for: get_unchecked)",
331 let s: &mut str = &mut s;
332 let expected: &mut str = &mut expected;
335 &mut s[$range], expected,
336 "(in assertion for: index_mut)",
339 s.get_mut($range), Some(&mut expected[..]),
340 "(in assertion for: get_mut)",
344 s.get_unchecked_mut($range), expected,
345 "(in assertion for: get_unchecked_mut)",
352 // Make sure the macro can actually detect bugs,
353 // because if it can't, then what are we even doing here?
355 // (Be aware this only demonstrates the ability to detect bugs
356 // in the FIRST method that panics, as the macro is not designed
357 // to be used in `should_panic`)
359 #[should_panic(expected = "out of bounds")]
360 fn assert_range_eq_can_fail_by_panic() {
361 assert_range_eq!("abc", 0..5, "abc");
364 // (Be aware this only demonstrates the ability to detect bugs
365 // in the FIRST method it calls, as the macro is not designed
366 // to be used in `should_panic`)
368 #[should_panic(expected = "==")]
369 fn assert_range_eq_can_fail_by_inequality() {
370 assert_range_eq!("abc", 0..2, "abc");
373 // Generates test cases for bad index operations.
375 // This generates `should_panic` test cases for Index/IndexMut
376 // and `None` test cases for get/get_mut.
377 macro_rules! panic_cases {
379 in mod $case_name:ident {
384 // a similar input for which DATA[input] succeeds, and the corresponding
385 // output str. This helps validate "critical points" where an input range
386 // straddles the boundary between valid and invalid.
387 // (such as the input `len..len`, which is just barely valid)
389 good: data[$good:expr] == $output:expr;
392 bad: data[$bad:expr];
393 message: $expect_msg:expr; // must be a literal
399 let mut v: String = $data.into();
401 $( assert_range_eq!(v, $good, $output); )*
405 assert_eq!(v.get($bad), None, "(in None assertion for get)");
409 let v: &mut str = &mut v;
410 assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
415 #[should_panic(expected = $expect_msg)]
417 let v: String = $data.into();
423 #[should_panic(expected = $expect_msg)]
424 fn index_mut_fail() {
425 let mut v: String = $data.into();
426 let v: &mut str = &mut v;
427 let _v = &mut v[$bad];
435 assert_range_eq!("abc", .., "abc");
437 assert_range_eq!("abc", 0..2, "ab");
438 assert_range_eq!("abc", 0..=1, "ab");
439 assert_range_eq!("abc", ..2, "ab");
440 assert_range_eq!("abc", ..=1, "ab");
442 assert_range_eq!("abc", 1..3, "bc");
443 assert_range_eq!("abc", 1..=2, "bc");
444 assert_range_eq!("abc", 1..1, "");
445 assert_range_eq!("abc", 1..=0, "");
449 fn simple_unicode() {
451 assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
453 assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
454 assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
455 assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
456 assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
458 assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
459 assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
460 assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
462 let data = "ประเทศไทย中华";
463 assert_range_eq!(data, 0..3, "ป");
464 assert_range_eq!(data, 3..6, "ร");
465 assert_range_eq!(data, 3..3, "");
466 assert_range_eq!(data, 30..33, "华");
478 let ss = "中华Việt Nam";
479 assert_range_eq!(ss, 3..6, "华");
480 assert_range_eq!(ss, 6..16, "Việt Nam");
481 assert_range_eq!(ss, 6..=15, "Việt Nam");
482 assert_range_eq!(ss, 6.., "Việt Nam");
484 assert_range_eq!(ss, 0..3, "中");
485 assert_range_eq!(ss, 3..7, "华V");
486 assert_range_eq!(ss, 3..=6, "华V");
487 assert_range_eq!(ss, 3..3, "");
488 assert_range_eq!(ss, 3..=2, "");
492 #[cfg(not(target_arch = "asmjs"))] // hits an OOM
494 fn a_million_letter_x() -> String {
496 let mut rs = String::new();
498 rs.push_str("华华华华华华华华华华");
503 fn half_a_million_letter_x() -> String {
505 let mut rs = String::new();
507 rs.push_str("华华华华华");
512 let letters = a_million_letter_x();
513 assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
518 fn test_slice_fail() {
523 in mod rangefrom_len {
525 good: data[6..] == "";
527 message: "out of bounds";
532 good: data[..6] == "abcdef";
534 message: "out of bounds";
537 in mod rangetoinclusive_len {
539 good: data[..=5] == "abcdef";
541 message: "out of bounds";
544 in mod range_len_len {
546 good: data[6..6] == "";
548 message: "out of bounds";
551 in mod rangeinclusive_len_len {
553 good: data[6..=5] == "";
555 message: "out of bounds";
560 in mod range_neg_width {
562 good: data[4..4] == "";
564 message: "begin <= end (4 <= 3)";
567 in mod rangeinclusive_neg_width {
569 good: data[4..=3] == "";
571 message: "begin <= end (4 <= 3)";
577 in mod rangeinclusive {
579 // note: using 0 specifically ensures that the result of overflowing is 0..0,
580 // so that `get` doesn't simply return None for the wrong reason.
581 bad: data[0..=usize::max_value()];
582 message: "maximum usize";
585 in mod rangetoinclusive {
587 bad: data[..=usize::max_value()];
588 message: "maximum usize";
594 const DATA: &str = "abcαβγ";
596 const BAD_START: usize = 4;
597 const GOOD_START: usize = 3;
598 const BAD_END: usize = 6;
599 const GOOD_END: usize = 7;
600 const BAD_END_INCL: usize = BAD_END - 1;
601 const GOOD_END_INCL: usize = GOOD_END - 1;
603 // it is especially important to test all of the different range types here
604 // because some of the logic may be duplicated as part of micro-optimizations
605 // to dodge unicode boundary checks on half-ranges.
609 bad: data[super::BAD_START..super::GOOD_END];
611 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
616 bad: data[super::GOOD_START..super::BAD_END];
618 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
623 bad: data[super::BAD_START..];
625 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
630 bad: data[..super::BAD_END];
632 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
635 in mod rangeinclusive_1 {
637 bad: data[super::BAD_START..=super::GOOD_END_INCL];
639 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
642 in mod rangeinclusive_2 {
644 bad: data[super::GOOD_START..=super::BAD_END_INCL];
646 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
649 in mod rangetoinclusive {
651 bad: data[..=super::BAD_END_INCL];
653 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
658 const LOREM_PARAGRAPH: &str = "\
659 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \
660 sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \
661 quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \
662 nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \
663 tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \
666 // check the panic includes the prefix of the sliced string
668 #[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
669 fn test_slice_fail_truncated_1() {
670 &LOREM_PARAGRAPH[..1024];
672 // check the truncation in the panic message
674 #[should_panic(expected="luctus, im`[...]")]
675 fn test_slice_fail_truncated_2() {
676 &LOREM_PARAGRAPH[..1024];
681 fn test_str_slice_rangetoinclusive_ok() {
683 assert_eq!(&s[..=2], "abc");
684 assert_eq!(&s[..=4], "abcα");
690 fn test_str_slice_rangetoinclusive_notok() {
696 fn test_str_slicemut_rangetoinclusive_ok() {
697 let mut s = "abcαβγ".to_owned();
698 let s: &mut str = &mut s;
699 assert_eq!(&mut s[..=2], "abc");
700 assert_eq!(&mut s[..=4], "abcα");
706 fn test_str_slicemut_rangetoinclusive_notok() {
707 let mut s = "abcαβγ".to_owned();
708 let s: &mut str = &mut s;
713 fn test_is_char_boundary() {
714 let s = "ศไทย中华Việt Nam β-release 🐱123";
715 assert!(s.is_char_boundary(0));
716 assert!(s.is_char_boundary(s.len()));
717 assert!(!s.is_char_boundary(s.len() + 1));
718 for (i, ch) in s.char_indices() {
719 // ensure character locations are boundaries and continuation bytes are not
720 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
721 for j in 1..ch.len_utf8() {
722 assert!(!s.is_char_boundary(i + j),
723 "{} should not be a char boundary in {:?}", i + j, s);
729 fn test_trim_start_matches() {
730 let v: &[char] = &[];
731 assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
732 let chars: &[char] = &['*', ' '];
733 assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
734 assert_eq!(" *** *** ".trim_start_matches(chars), "");
735 assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
737 assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
738 let chars: &[char] = &['1', '2'];
739 assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
740 assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
744 fn test_trim_end_matches() {
745 let v: &[char] = &[];
746 assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
747 let chars: &[char] = &['*', ' '];
748 assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
749 assert_eq!(" *** *** ".trim_end_matches(chars), "");
750 assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
752 assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
753 let chars: &[char] = &['1', '2'];
754 assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
755 assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
759 fn test_trim_matches() {
760 let v: &[char] = &[];
761 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
762 let chars: &[char] = &['*', ' '];
763 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
764 assert_eq!(" *** *** ".trim_matches(chars), "");
765 assert_eq!("foo".trim_matches(chars), "foo");
767 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
768 let chars: &[char] = &['1', '2'];
769 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
770 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
774 fn test_trim_start() {
775 assert_eq!("".trim_start(), "");
776 assert_eq!("a".trim_start(), "a");
777 assert_eq!(" ".trim_start(), "");
778 assert_eq!(" blah".trim_start(), "blah");
779 assert_eq!(" \u{3000} wut".trim_start(), "wut");
780 assert_eq!("hey ".trim_start(), "hey ");
785 assert_eq!("".trim_end(), "");
786 assert_eq!("a".trim_end(), "a");
787 assert_eq!(" ".trim_end(), "");
788 assert_eq!("blah ".trim_end(), "blah");
789 assert_eq!("wut \u{3000} ".trim_end(), "wut");
790 assert_eq!(" hey".trim_end(), " hey");
795 assert_eq!("".trim(), "");
796 assert_eq!("a".trim(), "a");
797 assert_eq!(" ".trim(), "");
798 assert_eq!(" blah ".trim(), "blah");
799 assert_eq!("\nwut \u{3000} ".trim(), "wut");
800 assert_eq!(" hey dude ".trim(), "hey dude");
804 fn test_is_whitespace() {
805 assert!("".chars().all(|c| c.is_whitespace()));
806 assert!(" ".chars().all(|c| c.is_whitespace()));
807 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
808 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
809 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
814 // deny overlong encodings
815 assert!(from_utf8(&[0xc0, 0x80]).is_err());
816 assert!(from_utf8(&[0xc0, 0xae]).is_err());
817 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
818 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
819 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
820 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
821 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
824 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
825 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
827 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
828 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
829 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
830 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
831 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
832 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
833 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
834 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
838 fn from_utf8_mostly_ascii() {
839 // deny invalid bytes embedded in long stretches of ascii
841 let mut data = [0; 128];
843 assert!(from_utf8(&data).is_err());
845 assert!(from_utf8(&data).is_err());
850 fn from_utf8_error() {
852 ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
853 let error = from_utf8($input).unwrap_err();
854 assert_eq!(error.valid_up_to(), $expected_valid_up_to);
855 assert_eq!(error.error_len(), $expected_error_len);
858 test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
859 test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
860 test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
861 test!(b"A\xC3\xA9 \xC1", 4, Some(1));
862 test!(b"A\xC3\xA9 \xC2", 4, None);
863 test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
864 test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
865 test!(b"A\xC3\xA9 \xE0", 4, None);
866 test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
867 test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
868 test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
869 test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
870 test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
871 test!(b"A\xC3\xA9 \xF1", 4, None);
872 test!(b"A\xC3\xA9 \xF1\x80", 4, None);
873 test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
874 test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
875 test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
876 test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
883 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
884 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
888 assert_eq!("".as_bytes(), b);
889 assert_eq!("abc".as_bytes(), b"abc");
890 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
896 fn test_as_bytes_fail() {
897 // Don't double free. (I'm not sure if this exercises the
898 // original problem code path anymore.)
899 let s = String::from("");
900 let _bytes = s.as_bytes();
906 let buf = "hello".as_ptr();
908 assert_eq!(*buf.offset(0), b'h');
909 assert_eq!(*buf.offset(1), b'e');
910 assert_eq!(*buf.offset(2), b'l');
911 assert_eq!(*buf.offset(3), b'l');
912 assert_eq!(*buf.offset(4), b'o');
917 fn vec_str_conversions() {
918 let s1: String = String::from("All mimsy were the borogoves");
920 let v: Vec<u8> = s1.as_bytes().to_vec();
921 let s2: String = String::from(from_utf8(&v).unwrap());
927 let a: u8 = s1.as_bytes()[i];
928 let b: u8 = s2.as_bytes()[i];
936 assert!("abcde".contains("bcd"));
937 assert!("abcde".contains("abcd"));
938 assert!("abcde".contains("bcde"));
939 assert!("abcde".contains(""));
940 assert!("".contains(""));
941 assert!(!"abcde".contains("def"));
942 assert!(!"".contains("a"));
944 let data = "ประเทศไทย中华Việt Nam";
945 assert!(data.contains("ประเ"));
946 assert!(data.contains("ะเ"));
947 assert!(data.contains("中华"));
948 assert!(!data.contains("ไท华"));
952 fn test_contains_char() {
953 assert!("abc".contains('b'));
954 assert!("a".contains('a'));
955 assert!(!"abc".contains('d'));
956 assert!(!"".contains('a'));
961 let s = "ศไทย中华Việt Nam";
962 for (index, _) in s.char_indices() {
963 let (a, b) = s.split_at(index);
964 assert_eq!(&s[..a.len()], a);
965 assert_eq!(&s[a.len()..], b);
967 let (a, b) = s.split_at(s.len());
973 fn test_split_at_mut() {
974 let mut s = "Hello World".to_string();
976 let (a, b) = s.split_at_mut(5);
977 a.make_ascii_uppercase();
978 b.make_ascii_lowercase();
980 assert_eq!(s, "HELLO world");
986 fn test_split_at_boundscheck() {
987 let s = "ศไทย中华Việt Nam";
992 fn test_escape_unicode() {
993 assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
994 assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
995 assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
996 assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
997 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
998 assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
999 assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
1000 assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
1001 assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
1005 fn test_escape_debug() {
1006 // Note that there are subtleties with the number of backslashes
1007 // on the left- and right-hand sides. In particular, Unicode code points
1008 // are usually escaped with two backslashes on the right-hand side, as
1009 // they are escaped. However, when the character is unescaped (e.g., for
1010 // printable characters), only a single backslash appears (as the character
1011 // itself appears in the debug string).
1012 assert_eq!("abc".escape_debug(), "abc");
1013 assert_eq!("a c".escape_debug(), "a c");
1014 assert_eq!("éèê".escape_debug(), "éèê");
1015 assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
1016 assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
1017 assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
1018 assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
1019 assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
1020 assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
1021 assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
1022 assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug(), "\\u{301}a\u{301}bé\\u{e000}");
1026 fn test_escape_default() {
1027 assert_eq!("abc".escape_default(), "abc");
1028 assert_eq!("a c".escape_default(), "a c");
1029 assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
1030 assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
1031 assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
1032 assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
1033 assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
1034 assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
1035 assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
1036 assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
1040 fn test_total_ord() {
1041 assert_eq!("1234".cmp("123"), Greater);
1042 assert_eq!("123".cmp("1234"), Less);
1043 assert_eq!("1234".cmp("1234"), Equal);
1044 assert_eq!("12345555".cmp("123456"), Less);
1045 assert_eq!("22".cmp("1234"), Greater);
1049 fn test_iterator() {
1050 let s = "ศไทย中华Việt Nam";
1051 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1057 assert_eq!(c, v[pos]);
1060 assert_eq!(pos, v.len());
1061 assert_eq!(s.chars().count(), v.len());
1065 fn test_rev_iterator() {
1066 let s = "ศไทย中华Việt Nam";
1067 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1070 let it = s.chars().rev();
1073 assert_eq!(c, v[pos]);
1076 assert_eq!(pos, v.len());
1081 fn test_chars_decoding() {
1082 let mut bytes = [0; 4];
1083 for c in (0..0x110000).filter_map(std::char::from_u32) {
1084 let s = c.encode_utf8(&mut bytes);
1085 if Some(c) != s.chars().next() {
1086 panic!("character {:x}={} does not decode correctly", c as u32, c);
1093 fn test_chars_rev_decoding() {
1094 let mut bytes = [0; 4];
1095 for c in (0..0x110000).filter_map(std::char::from_u32) {
1096 let s = c.encode_utf8(&mut bytes);
1097 if Some(c) != s.chars().rev().next() {
1098 panic!("character {:x}={} does not decode correctly", c as u32, c);
1104 fn test_iterator_clone() {
1105 let s = "ศไทย中华Việt Nam";
1106 let mut it = s.chars();
1108 assert!(it.clone().zip(it).all(|(x,y)| x == y));
1112 fn test_iterator_last() {
1113 let s = "ศไทย中华Việt Nam";
1114 let mut it = s.chars();
1116 assert_eq!(it.last(), Some('m'));
1120 fn test_bytesator() {
1121 let s = "ศไทย中华Việt Nam";
1123 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1124 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1129 for b in s.bytes() {
1130 assert_eq!(b, v[pos]);
1136 fn test_bytes_revator() {
1137 let s = "ศไทย中华Việt Nam";
1139 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1140 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1143 let mut pos = v.len();
1145 for b in s.bytes().rev() {
1147 assert_eq!(b, v[pos]);
1152 fn test_bytesator_nth() {
1153 let s = "ศไทย中华Việt Nam";
1155 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1156 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1160 let mut b = s.bytes();
1161 assert_eq!(b.nth(2).unwrap(), v[2]);
1162 assert_eq!(b.nth(10).unwrap(), v[10]);
1163 assert_eq!(b.nth(200), None);
1167 fn test_bytesator_count() {
1168 let s = "ศไทย中华Việt Nam";
1171 assert_eq!(b.count(), 28)
1175 fn test_bytesator_last() {
1176 let s = "ศไทย中华Việt Nam";
1179 assert_eq!(b.last().unwrap(), 109)
1183 fn test_char_indicesator() {
1184 let s = "ศไทย中华Việt Nam";
1185 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1186 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1189 let it = s.char_indices();
1192 assert_eq!(c, (p[pos], v[pos]));
1195 assert_eq!(pos, v.len());
1196 assert_eq!(pos, p.len());
1200 fn test_char_indices_revator() {
1201 let s = "ศไทย中华Việt Nam";
1202 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1203 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1206 let it = s.char_indices().rev();
1209 assert_eq!(c, (p[pos], v[pos]));
1212 assert_eq!(pos, v.len());
1213 assert_eq!(pos, p.len());
1217 fn test_char_indices_last() {
1218 let s = "ศไทย中华Việt Nam";
1219 let mut it = s.char_indices();
1221 assert_eq!(it.last(), Some((27, 'm')));
1225 fn test_splitn_char_iterator() {
1226 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1228 let split: Vec<&str> = data.splitn(4, ' ').collect();
1229 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1231 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1232 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1235 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1236 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1238 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1239 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1243 fn test_split_char_iterator_no_trailing() {
1244 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1246 let split: Vec<&str> = data.split('\n').collect();
1247 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1249 let split: Vec<&str> = data.split_terminator('\n').collect();
1250 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1255 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1257 let split: Vec<&str> = data.rsplit(' ').collect();
1258 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1260 let split: Vec<&str> = data.rsplit("lämb").collect();
1261 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1263 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1264 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1269 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1271 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1272 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1274 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1275 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1277 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1278 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1282 fn test_split_whitespace() {
1283 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1284 let words: Vec<&str> = data.split_whitespace().collect();
1285 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1290 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1291 let lines: Vec<&str> = data.lines().collect();
1292 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1294 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1295 let lines: Vec<&str> = data.lines().collect();
1296 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1300 fn test_splitator() {
1301 fn t(s: &str, sep: &str, u: &[&str]) {
1302 let v: Vec<&str> = s.split(sep).collect();
1305 t("--1233345--", "12345", &["--1233345--"]);
1306 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1307 t("::hello::there", "::", &["", "hello", "there"]);
1308 t("hello::there::", "::", &["hello", "there", ""]);
1309 t("::hello::there::", "::", &["", "hello", "there", ""]);
1310 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1311 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1312 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1313 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1315 t("zz", "zz", &["",""]);
1316 t("ok", "z", &["ok"]);
1317 t("zzz", "zz", &["","z"]);
1318 t("zzzzz", "zz", &["","","z"]);
1323 fn test_str_default() {
1324 use std::default::Default;
1326 fn t<S: Default + AsRef<str>>() {
1327 let s: S = Default::default();
1328 assert_eq!(s.as_ref(), "");
1337 fn test_str_container() {
1338 fn sum_len(v: &[&str]) -> usize {
1339 v.iter().map(|x| x.len()).sum()
1343 assert_eq!(5, sum_len(&["012", "", "34"]));
1344 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1345 assert_eq!(5, sum_len(&[s]));
1349 fn test_str_from_utf8() {
1351 assert_eq!(from_utf8(xs), Ok("hello"));
1353 let xs = "ศไทย中华Việt Nam".as_bytes();
1354 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1356 let xs = b"hello\xFF";
1357 assert!(from_utf8(xs).is_err());
1361 fn test_pattern_deref_forward() {
1362 let data = "aabcdaa";
1363 assert!(data.contains("bcd"));
1364 assert!(data.contains(&"bcd"));
1365 assert!(data.contains(&"bcd".to_string()));
1369 fn test_empty_match_indices() {
1371 let vec: Vec<_> = data.match_indices("").collect();
1372 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1376 fn test_bool_from_str() {
1377 assert_eq!("true".parse().ok(), Some(true));
1378 assert_eq!("false".parse().ok(), Some(false));
1379 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1383 fn check_contains_all_substrings(s: &str) {
1384 assert!(s.contains(""));
1385 for i in 0..s.len() {
1386 for j in i+1..=s.len() {
1387 assert!(s.contains(&s[i..j]));
1394 fn strslice_issue_16589() {
1395 assert!("bananas".contains("nana"));
1397 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1398 // test all substrings for good measure
1399 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1404 fn strslice_issue_16878() {
1405 assert!(!"1234567ah012345678901ah".contains("hah"));
1406 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1412 fn test_strslice_contains() {
1413 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1414 check_contains_all_substrings(x);
1418 fn test_rsplitn_char_iterator() {
1419 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1421 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1423 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1425 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1427 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1430 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1432 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1434 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1436 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1440 fn test_split_char_iterator() {
1441 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1443 let split: Vec<&str> = data.split(' ').collect();
1444 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1446 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1448 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1450 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1451 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1453 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1455 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1458 let split: Vec<&str> = data.split('ä').collect();
1459 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1461 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1463 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1465 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1466 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1468 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1470 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1474 fn test_rev_split_char_iterator_no_trailing() {
1475 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1477 let mut split: Vec<&str> = data.split('\n').rev().collect();
1479 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1481 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1483 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1487 fn test_utf16_code_units() {
1488 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
1489 [0xE9, 0xD83D, 0xDCA9])
1493 fn starts_with_in_unicode() {
1494 assert!(!"├── Cargo.toml".starts_with("# "));
1498 fn starts_short_long() {
1499 assert!(!"".starts_with("##"));
1500 assert!(!"##".starts_with("####"));
1501 assert!("####".starts_with("##"));
1502 assert!(!"##ä".starts_with("####"));
1503 assert!("####ä".starts_with("##"));
1504 assert!(!"##".starts_with("####ä"));
1505 assert!("##ä##".starts_with("##ä"));
1507 assert!("".starts_with(""));
1508 assert!("ä".starts_with(""));
1509 assert!("#ä".starts_with(""));
1510 assert!("##ä".starts_with(""));
1511 assert!("ä###".starts_with(""));
1512 assert!("#ä##".starts_with(""));
1513 assert!("##ä#".starts_with(""));
1517 fn contains_weird_cases() {
1518 assert!("* \t".contains(' '));
1519 assert!(!"* \t".contains('?'));
1520 assert!(!"* \t".contains('\u{1F4A9}'));
1525 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1527 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1529 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1531 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1533 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
1535 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1537 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1539 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1541 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1543 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
1550 assert_eq!("".to_lowercase(), "");
1551 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1553 // https://github.com/rust-lang/rust/issues/26035
1554 assert_eq!("ΑΣ".to_lowercase(), "ας");
1555 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1556 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1558 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1559 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1560 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1562 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1563 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1565 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1566 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1568 assert_eq!("Α Σ".to_lowercase(), "α σ");
1569 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1570 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1572 assert_eq!("Σ".to_lowercase(), "σ");
1573 assert_eq!("'Σ".to_lowercase(), "'σ");
1574 assert_eq!("''Σ".to_lowercase(), "''σ");
1576 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1577 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1578 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1584 assert_eq!("".to_uppercase(), "");
1585 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1589 fn test_into_string() {
1590 // The only way to acquire a Box<str> in the first place is through a String, so just
1591 // test that we can round-trip between Box<str> and String.
1592 let string = String::from("Some text goes here");
1593 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1597 fn test_box_slice_clone() {
1598 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1599 let data2 = data.clone().into_boxed_str().clone().into_string();
1601 assert_eq!(data, data2);
1605 fn test_cow_from() {
1606 let borrowed = "borrowed";
1607 let owned = String::from("owned");
1608 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1609 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1610 _ => panic!("invalid `Cow::from`"),
1617 assert_eq!("".repeat(3), "");
1618 assert_eq!("abc".repeat(0), "");
1619 assert_eq!("α".repeat(3), "ααα");
1623 use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
1624 use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1626 macro_rules! make_test {
1627 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1628 #[allow(unused_imports)]
1630 use std::str::pattern::SearchStep::{Match, Reject};
1631 use super::{cmp_search_to_vec};
1634 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1638 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1644 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1645 right: Vec<SearchStep>)
1646 where P::Searcher: ReverseSearcher<'a>
1648 let mut searcher = pat.into_searcher(haystack);
1651 match if !rev {searcher.next()} else {searcher.next_back()} {
1652 Match(a, b) => v.push(Match(a, b)),
1653 Reject(a, b) => v.push(Reject(a, b)),
1661 let mut first_index = 0;
1664 for (i, e) in right.iter().enumerate() {
1666 Match(a, b) | Reject(a, b)
1667 if a <= b && a == first_index => {
1677 if let Some(err) = err {
1678 panic!("Input skipped range at {}", err);
1681 if first_index != haystack.len() {
1682 panic!("Did not cover whole input");
1685 assert_eq!(v, right);
1688 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1695 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1703 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1720 make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1725 make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1734 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1737 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1739 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1748 make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1753 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1761 macro_rules! generate_iterator_test {
1765 ($($arg:expr),*) -> [$($t:tt)*];
1768 with $fwd:expr, $bwd:expr;
1774 let res = vec![$($t)*];
1776 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1777 assert_eq!(fwd_vec, res);
1779 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1781 assert_eq!(bwd_vec, res);
1789 ($($arg:expr),*) -> [$($t:tt)*];
1798 let res = vec![$($t)*];
1800 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1801 assert_eq!(fwd_vec, res);
1808 generate_iterator_test! {
1809 double_ended_split {
1810 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1811 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1813 with str::split, str::rsplit;
1816 generate_iterator_test! {
1817 double_ended_split_terminator {
1818 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1820 with str::split_terminator, str::rsplit_terminator;
1823 generate_iterator_test! {
1824 double_ended_matches {
1825 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1827 with str::matches, str::rmatches;
1830 generate_iterator_test! {
1831 double_ended_match_indices {
1832 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1834 with str::match_indices, str::rmatch_indices;
1837 generate_iterator_test! {
1838 not_double_ended_splitn {
1839 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1844 generate_iterator_test! {
1845 not_double_ended_rsplitn {
1846 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1852 fn different_str_pattern_forwarding_lifetimes() {
1853 use std::str::pattern::Pattern;
1855 fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {