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().to_string(), "\\u{61}\\u{62}\\u{63}");
994 assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
995 assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
996 assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
997 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
998 assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
999 assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
1000 assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
1001 assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\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().to_string(), "abc");
1013 assert_eq!("a c".escape_debug().to_string(), "a c");
1014 assert_eq!("éèê".escape_debug().to_string(), "éèê");
1015 assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1016 assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1017 assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1018 assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1019 assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1020 assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1021 assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1022 assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1023 "\\u{301}a\u{301}bé\\u{e000}");
1027 fn test_escape_default() {
1028 assert_eq!("abc".escape_default().to_string(), "abc");
1029 assert_eq!("a c".escape_default().to_string(), "a c");
1030 assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1031 assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1032 assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1033 assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1034 assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1035 assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1036 assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1037 assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1041 fn test_total_ord() {
1042 assert_eq!("1234".cmp("123"), Greater);
1043 assert_eq!("123".cmp("1234"), Less);
1044 assert_eq!("1234".cmp("1234"), Equal);
1045 assert_eq!("12345555".cmp("123456"), Less);
1046 assert_eq!("22".cmp("1234"), Greater);
1050 fn test_iterator() {
1051 let s = "ศไทย中华Việt Nam";
1052 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1058 assert_eq!(c, v[pos]);
1061 assert_eq!(pos, v.len());
1062 assert_eq!(s.chars().count(), v.len());
1066 fn test_rev_iterator() {
1067 let s = "ศไทย中华Việt Nam";
1068 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1071 let it = s.chars().rev();
1074 assert_eq!(c, v[pos]);
1077 assert_eq!(pos, v.len());
1082 fn test_chars_decoding() {
1083 let mut bytes = [0; 4];
1084 for c in (0..0x110000).filter_map(std::char::from_u32) {
1085 let s = c.encode_utf8(&mut bytes);
1086 if Some(c) != s.chars().next() {
1087 panic!("character {:x}={} does not decode correctly", c as u32, c);
1094 fn test_chars_rev_decoding() {
1095 let mut bytes = [0; 4];
1096 for c in (0..0x110000).filter_map(std::char::from_u32) {
1097 let s = c.encode_utf8(&mut bytes);
1098 if Some(c) != s.chars().rev().next() {
1099 panic!("character {:x}={} does not decode correctly", c as u32, c);
1105 fn test_iterator_clone() {
1106 let s = "ศไทย中华Việt Nam";
1107 let mut it = s.chars();
1109 assert!(it.clone().zip(it).all(|(x,y)| x == y));
1113 fn test_iterator_last() {
1114 let s = "ศไทย中华Việt Nam";
1115 let mut it = s.chars();
1117 assert_eq!(it.last(), Some('m'));
1121 fn test_bytesator() {
1122 let s = "ศไทย中华Việt Nam";
1124 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1125 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1130 for b in s.bytes() {
1131 assert_eq!(b, v[pos]);
1137 fn test_bytes_revator() {
1138 let s = "ศไทย中华Việt Nam";
1140 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1141 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1144 let mut pos = v.len();
1146 for b in s.bytes().rev() {
1148 assert_eq!(b, v[pos]);
1153 fn test_bytesator_nth() {
1154 let s = "ศไทย中华Việt Nam";
1156 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1157 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1161 let mut b = s.bytes();
1162 assert_eq!(b.nth(2).unwrap(), v[2]);
1163 assert_eq!(b.nth(10).unwrap(), v[10]);
1164 assert_eq!(b.nth(200), None);
1168 fn test_bytesator_count() {
1169 let s = "ศไทย中华Việt Nam";
1172 assert_eq!(b.count(), 28)
1176 fn test_bytesator_last() {
1177 let s = "ศไทย中华Việt Nam";
1180 assert_eq!(b.last().unwrap(), 109)
1184 fn test_char_indicesator() {
1185 let s = "ศไทย中华Việt Nam";
1186 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1187 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1190 let it = s.char_indices();
1193 assert_eq!(c, (p[pos], v[pos]));
1196 assert_eq!(pos, v.len());
1197 assert_eq!(pos, p.len());
1201 fn test_char_indices_revator() {
1202 let s = "ศไทย中华Việt Nam";
1203 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1204 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1207 let it = s.char_indices().rev();
1210 assert_eq!(c, (p[pos], v[pos]));
1213 assert_eq!(pos, v.len());
1214 assert_eq!(pos, p.len());
1218 fn test_char_indices_last() {
1219 let s = "ศไทย中华Việt Nam";
1220 let mut it = s.char_indices();
1222 assert_eq!(it.last(), Some((27, 'm')));
1226 fn test_splitn_char_iterator() {
1227 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1229 let split: Vec<&str> = data.splitn(4, ' ').collect();
1230 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1232 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1233 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1236 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1237 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1239 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1240 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1244 fn test_split_char_iterator_no_trailing() {
1245 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1247 let split: Vec<&str> = data.split('\n').collect();
1248 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1250 let split: Vec<&str> = data.split_terminator('\n').collect();
1251 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1256 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1258 let split: Vec<&str> = data.rsplit(' ').collect();
1259 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1261 let split: Vec<&str> = data.rsplit("lämb").collect();
1262 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1264 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1265 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1270 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1272 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1273 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1275 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1276 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1278 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1279 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1283 fn test_split_whitespace() {
1284 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1285 let words: Vec<&str> = data.split_whitespace().collect();
1286 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1291 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1292 let lines: Vec<&str> = data.lines().collect();
1293 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1295 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1296 let lines: Vec<&str> = data.lines().collect();
1297 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1301 fn test_splitator() {
1302 fn t(s: &str, sep: &str, u: &[&str]) {
1303 let v: Vec<&str> = s.split(sep).collect();
1306 t("--1233345--", "12345", &["--1233345--"]);
1307 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1308 t("::hello::there", "::", &["", "hello", "there"]);
1309 t("hello::there::", "::", &["hello", "there", ""]);
1310 t("::hello::there::", "::", &["", "hello", "there", ""]);
1311 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1312 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1313 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1314 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1316 t("zz", "zz", &["",""]);
1317 t("ok", "z", &["ok"]);
1318 t("zzz", "zz", &["","z"]);
1319 t("zzzzz", "zz", &["","","z"]);
1324 fn test_str_default() {
1325 use std::default::Default;
1327 fn t<S: Default + AsRef<str>>() {
1328 let s: S = Default::default();
1329 assert_eq!(s.as_ref(), "");
1338 fn test_str_container() {
1339 fn sum_len(v: &[&str]) -> usize {
1340 v.iter().map(|x| x.len()).sum()
1344 assert_eq!(5, sum_len(&["012", "", "34"]));
1345 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1346 assert_eq!(5, sum_len(&[s]));
1350 fn test_str_from_utf8() {
1352 assert_eq!(from_utf8(xs), Ok("hello"));
1354 let xs = "ศไทย中华Việt Nam".as_bytes();
1355 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1357 let xs = b"hello\xFF";
1358 assert!(from_utf8(xs).is_err());
1362 fn test_pattern_deref_forward() {
1363 let data = "aabcdaa";
1364 assert!(data.contains("bcd"));
1365 assert!(data.contains(&"bcd"));
1366 assert!(data.contains(&"bcd".to_string()));
1370 fn test_empty_match_indices() {
1372 let vec: Vec<_> = data.match_indices("").collect();
1373 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1377 fn test_bool_from_str() {
1378 assert_eq!("true".parse().ok(), Some(true));
1379 assert_eq!("false".parse().ok(), Some(false));
1380 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1384 fn check_contains_all_substrings(s: &str) {
1385 assert!(s.contains(""));
1386 for i in 0..s.len() {
1387 for j in i+1..=s.len() {
1388 assert!(s.contains(&s[i..j]));
1395 fn strslice_issue_16589() {
1396 assert!("bananas".contains("nana"));
1398 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1399 // test all substrings for good measure
1400 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1405 fn strslice_issue_16878() {
1406 assert!(!"1234567ah012345678901ah".contains("hah"));
1407 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1413 fn test_strslice_contains() {
1414 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1415 check_contains_all_substrings(x);
1419 fn test_rsplitn_char_iterator() {
1420 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1422 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1424 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1426 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1428 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1431 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1433 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1435 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1437 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1441 fn test_split_char_iterator() {
1442 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1444 let split: Vec<&str> = data.split(' ').collect();
1445 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1447 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1449 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1451 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1452 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1454 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1456 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1459 let split: Vec<&str> = data.split('ä').collect();
1460 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1462 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1464 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1466 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1467 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1469 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1471 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1475 fn test_rev_split_char_iterator_no_trailing() {
1476 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1478 let mut split: Vec<&str> = data.split('\n').rev().collect();
1480 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1482 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1484 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1488 fn test_utf16_code_units() {
1489 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
1490 [0xE9, 0xD83D, 0xDCA9])
1494 fn starts_with_in_unicode() {
1495 assert!(!"├── Cargo.toml".starts_with("# "));
1499 fn starts_short_long() {
1500 assert!(!"".starts_with("##"));
1501 assert!(!"##".starts_with("####"));
1502 assert!("####".starts_with("##"));
1503 assert!(!"##ä".starts_with("####"));
1504 assert!("####ä".starts_with("##"));
1505 assert!(!"##".starts_with("####ä"));
1506 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(""));
1514 assert!("##ä#".starts_with(""));
1518 fn contains_weird_cases() {
1519 assert!("* \t".contains(' '));
1520 assert!(!"* \t".contains('?'));
1521 assert!(!"* \t".contains('\u{1F4A9}'));
1526 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1528 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1530 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1532 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1534 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
1536 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1538 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1540 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1542 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1544 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
1551 assert_eq!("".to_lowercase(), "");
1552 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1554 // https://github.com/rust-lang/rust/issues/26035
1555 assert_eq!("ΑΣ".to_lowercase(), "ας");
1556 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1557 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1559 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1560 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1561 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1563 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1564 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1566 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1567 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1569 assert_eq!("Α Σ".to_lowercase(), "α σ");
1570 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1571 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1573 assert_eq!("Σ".to_lowercase(), "σ");
1574 assert_eq!("'Σ".to_lowercase(), "'σ");
1575 assert_eq!("''Σ".to_lowercase(), "''σ");
1577 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1578 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1579 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1585 assert_eq!("".to_uppercase(), "");
1586 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1590 fn test_into_string() {
1591 // The only way to acquire a Box<str> in the first place is through a String, so just
1592 // test that we can round-trip between Box<str> and String.
1593 let string = String::from("Some text goes here");
1594 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1598 fn test_box_slice_clone() {
1599 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1600 let data2 = data.clone().into_boxed_str().clone().into_string();
1602 assert_eq!(data, data2);
1606 fn test_cow_from() {
1607 let borrowed = "borrowed";
1608 let owned = String::from("owned");
1609 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1610 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1611 _ => panic!("invalid `Cow::from`"),
1618 assert_eq!("".repeat(3), "");
1619 assert_eq!("abc".repeat(0), "");
1620 assert_eq!("α".repeat(3), "ααα");
1624 use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
1625 use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1627 macro_rules! make_test {
1628 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1629 #[allow(unused_imports)]
1631 use std::str::pattern::SearchStep::{Match, Reject};
1632 use super::{cmp_search_to_vec};
1635 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1639 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1645 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1646 right: Vec<SearchStep>)
1647 where P::Searcher: ReverseSearcher<'a>
1649 let mut searcher = pat.into_searcher(haystack);
1652 match if !rev {searcher.next()} else {searcher.next_back()} {
1653 Match(a, b) => v.push(Match(a, b)),
1654 Reject(a, b) => v.push(Reject(a, b)),
1662 let mut first_index = 0;
1665 for (i, e) in right.iter().enumerate() {
1667 Match(a, b) | Reject(a, b)
1668 if a <= b && a == first_index => {
1678 if let Some(err) = err {
1679 panic!("Input skipped range at {}", err);
1682 if first_index != haystack.len() {
1683 panic!("Did not cover whole input");
1686 assert_eq!(v, right);
1689 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1696 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1704 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1721 make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1726 make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1735 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1738 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1740 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1749 make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1754 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1762 macro_rules! generate_iterator_test {
1766 ($($arg:expr),*) -> [$($t:tt)*];
1769 with $fwd:expr, $bwd:expr;
1775 let res = vec![$($t)*];
1777 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1778 assert_eq!(fwd_vec, res);
1780 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1782 assert_eq!(bwd_vec, res);
1790 ($($arg:expr),*) -> [$($t:tt)*];
1799 let res = vec![$($t)*];
1801 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1802 assert_eq!(fwd_vec, res);
1809 generate_iterator_test! {
1810 double_ended_split {
1811 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1812 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1814 with str::split, str::rsplit;
1817 generate_iterator_test! {
1818 double_ended_split_terminator {
1819 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1821 with str::split_terminator, str::rsplit_terminator;
1824 generate_iterator_test! {
1825 double_ended_matches {
1826 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1828 with str::matches, str::rmatches;
1831 generate_iterator_test! {
1832 double_ended_match_indices {
1833 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1835 with str::match_indices, str::rmatch_indices;
1838 generate_iterator_test! {
1839 not_double_ended_splitn {
1840 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1845 generate_iterator_test! {
1846 not_double_ended_rsplitn {
1847 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1853 fn different_str_pattern_forwarding_lifetimes() {
1854 use std::str::pattern::Pattern;
1856 fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {