3 cmp::Ordering::{Equal, Greater, Less},
11 assert!("foo" <= "foo");
12 assert!("foo" != "bar");
17 assert_eq!("hello".find('l'), Some(2));
18 assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
19 assert!("hello".find('x').is_none());
20 assert!("hello".find(|c:char| c == 'x').is_none());
21 assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
22 assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
27 assert_eq!("hello".rfind('l'), Some(3));
28 assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
29 assert!("hello".rfind('x').is_none());
30 assert!("hello".rfind(|c:char| c == 'x').is_none());
31 assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
32 assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
38 let s: String = empty.chars().collect();
40 let data = "ประเทศไทย中";
41 let s: String = data.chars().collect();
46 fn test_into_bytes() {
47 let data = String::from("asdf");
48 let buf = data.into_bytes();
49 assert_eq!(buf, b"asdf");
55 assert_eq!("".find(""), Some(0));
56 assert!("banana".find("apple pie").is_none());
59 assert_eq!(data[0..6].find("ab"), Some(0));
60 assert_eq!(data[2..6].find("ab"), Some(3 - 2));
61 assert!(data[2..4].find("ab").is_none());
63 let string = "ประเทศไทย中华Việt Nam";
64 let mut data = String::from(string);
65 data.push_str(string);
66 assert!(data.find("ไท华").is_none());
67 assert_eq!(data[0..43].find(""), Some(0));
68 assert_eq!(data[6..43].find(""), Some(6 - 6));
70 assert_eq!(data[0..43].find("ประ"), Some( 0));
71 assert_eq!(data[0..43].find("ทศไ"), Some(12));
72 assert_eq!(data[0..43].find("ย中"), Some(24));
73 assert_eq!(data[0..43].find("iệt"), Some(34));
74 assert_eq!(data[0..43].find("Nam"), Some(40));
76 assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
77 assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
78 assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
79 assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
80 assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
82 // find every substring -- assert that it finds it, or an earlier occurrence.
83 let string = "Việt Namacbaabcaabaaba";
84 for (i, ci) in string.char_indices() {
85 let ip = i + ci.len_utf8();
86 for j in string[ip..].char_indices()
88 .chain(Some(string.len() - ip))
90 let pat = &string[i..ip + j];
91 assert!(match string.find(pat) {
95 assert!(match string.rfind(pat) {
103 fn s(x: &str) -> String { x.to_string() }
105 macro_rules! test_concat {
106 ($expected: expr, $string: expr) => {
108 let s: String = $string.concat();
109 assert_eq!($expected, s);
115 fn test_concat_for_different_types() {
116 test_concat!("ab", vec![s("a"), s("b")]);
117 test_concat!("ab", vec!["a", "b"]);
121 fn test_concat_for_different_lengths() {
122 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] = &[];
151 test_join!("", empty, "-");
152 test_join!("a", ["a"], "-");
153 test_join!("a-b", ["a", "b"], "-");
154 test_join!("-a-bc", ["", "a", "bc"], "-");
157 // join has fast paths for small separators up to 4 bytes
158 // this tests the slow paths.
160 fn test_join_for_different_lengths_with_long_separator() {
161 assert_eq!("~~~~~".len(), 15);
163 let empty: &[&str] = &[];
164 test_join!("", empty, "~~~~~");
165 test_join!("a", ["a"], "~~~~~");
166 test_join!("a~~~~~b", ["a", "b"], "~~~~~");
167 test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
171 fn test_unsafe_slice() {
172 assert_eq!("ab", unsafe {"abc".get_unchecked(0..2)});
173 assert_eq!("bc", unsafe {"abc".get_unchecked(1..3)});
174 assert_eq!("", unsafe {"abc".get_unchecked(1..1)});
175 fn a_million_letter_a() -> String {
177 let mut rs = String::new();
179 rs.push_str("aaaaaaaaaa");
184 fn half_a_million_letter_a() -> String {
186 let mut rs = String::new();
188 rs.push_str("aaaaa");
193 let letters = a_million_letter_a();
194 assert_eq!(half_a_million_letter_a(),
195 unsafe { letters.get_unchecked(0..500000)});
199 fn test_starts_with() {
200 assert!("".starts_with(""));
201 assert!("abc".starts_with(""));
202 assert!("abc".starts_with("a"));
203 assert!(!"a".starts_with("abc"));
204 assert!(!"".starts_with("abc"));
205 assert!(!"ödd".starts_with("-"));
206 assert!("ödd".starts_with("öd"));
210 fn test_ends_with() {
211 assert!("".ends_with(""));
212 assert!("abc".ends_with(""));
213 assert!("abc".ends_with("c"));
214 assert!(!"a".ends_with("abc"));
215 assert!(!"".ends_with("abc"));
216 assert!(!"ddö".ends_with("-"));
217 assert!("ddö".ends_with("dö"));
222 assert!("".is_empty());
223 assert!(!"a".is_empty());
228 assert_eq!("".replacen('a', "b", 5), "");
229 assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
230 assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
233 assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
234 assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
235 assert_eq!(" test test ".replacen(test, "", 5), " ");
237 assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
243 assert_eq!("".replace(a, "b"), "");
244 assert_eq!("a".replace(a, "b"), "b");
245 assert_eq!("ab".replace(a, "b"), "bb");
247 assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
248 assert_eq!(" test test ".replace(test, ""), " ");
252 fn test_replace_2a() {
253 let data = "ประเทศไทย中华";
254 let repl = "دولة الكويت";
257 let a2 = "دولة الكويتทศไทย中华";
258 assert_eq!(data.replace(a, repl), a2);
262 fn test_replace_2b() {
263 let data = "ประเทศไทย中华";
264 let repl = "دولة الكويت";
267 let b2 = "ปรدولة الكويتทศไทย中华";
268 assert_eq!(data.replace(b, repl), b2);
272 fn test_replace_2c() {
273 let data = "ประเทศไทย中华";
274 let repl = "دولة الكويت";
277 let c2 = "ประเทศไทยدولة الكويت";
278 assert_eq!(data.replace(c, repl), c2);
282 fn test_replace_2d() {
283 let data = "ประเทศไทย中华";
284 let repl = "دولة الكويت";
287 assert_eq!(data.replace(d, repl), data);
291 fn test_replace_pattern() {
292 let data = "abcdαβγδabcdαβγδ";
293 assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
294 assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
295 assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
296 assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
299 // The current implementation of SliceIndex fails to handle methods
300 // orthogonally from range types; therefore, it is worth testing
301 // all of the indexing operations on each input.
303 // Test a slicing operation **that should succeed,**
304 // testing it on all of the indexing methods.
306 // This is not suitable for testing failure on invalid inputs.
307 macro_rules! assert_range_eq {
308 ($s:expr, $range:expr, $expected:expr)
310 let mut s: String = $s.to_owned();
311 let mut expected: String = $expected.to_owned();
314 let expected: &str = &expected;
316 assert_eq!(&s[$range], expected, "(in assertion for: index)");
317 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
320 s.get_unchecked($range), expected,
321 "(in assertion for: get_unchecked)",
326 let s: &mut str = &mut s;
327 let expected: &mut str = &mut expected;
330 &mut s[$range], expected,
331 "(in assertion for: index_mut)",
334 s.get_mut($range), Some(&mut expected[..]),
335 "(in assertion for: get_mut)",
339 s.get_unchecked_mut($range), expected,
340 "(in assertion for: get_unchecked_mut)",
347 // Make sure the macro can actually detect bugs,
348 // because if it can't, then what are we even doing here?
350 // (Be aware this only demonstrates the ability to detect bugs
351 // in the FIRST method that panics, as the macro is not designed
352 // to be used in `should_panic`)
354 #[should_panic(expected = "out of bounds")]
355 fn assert_range_eq_can_fail_by_panic() {
356 assert_range_eq!("abc", 0..5, "abc");
359 // (Be aware this only demonstrates the ability to detect bugs
360 // in the FIRST method it calls, as the macro is not designed
361 // to be used in `should_panic`)
363 #[should_panic(expected = "==")]
364 fn assert_range_eq_can_fail_by_inequality() {
365 assert_range_eq!("abc", 0..2, "abc");
368 // Generates test cases for bad index operations.
370 // This generates `should_panic` test cases for Index/IndexMut
371 // and `None` test cases for get/get_mut.
372 macro_rules! panic_cases {
374 in mod $case_name:ident {
379 // a similar input for which DATA[input] succeeds, and the corresponding
380 // output str. This helps validate "critical points" where an input range
381 // straddles the boundary between valid and invalid.
382 // (such as the input `len..len`, which is just barely valid)
384 good: data[$good:expr] == $output:expr;
387 bad: data[$bad:expr];
388 message: $expect_msg:expr; // must be a literal
394 let mut v: String = $data.into();
396 $( assert_range_eq!(v, $good, $output); )*
400 assert_eq!(v.get($bad), None, "(in None assertion for get)");
404 let v: &mut str = &mut v;
405 assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
410 #[should_panic(expected = $expect_msg)]
412 let v: String = $data.into();
418 #[should_panic(expected = $expect_msg)]
419 fn index_mut_fail() {
420 let mut v: String = $data.into();
421 let v: &mut str = &mut v;
422 let _v = &mut v[$bad];
430 assert_range_eq!("abc", .., "abc");
432 assert_range_eq!("abc", 0..2, "ab");
433 assert_range_eq!("abc", 0..=1, "ab");
434 assert_range_eq!("abc", ..2, "ab");
435 assert_range_eq!("abc", ..=1, "ab");
437 assert_range_eq!("abc", 1..3, "bc");
438 assert_range_eq!("abc", 1..=2, "bc");
439 assert_range_eq!("abc", 1..1, "");
440 assert_range_eq!("abc", 1..=0, "");
444 fn simple_unicode() {
446 assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
448 assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
449 assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
450 assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
451 assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
453 assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
454 assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
455 assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
457 let data = "ประเทศไทย中华";
458 assert_range_eq!(data, 0..3, "ป");
459 assert_range_eq!(data, 3..6, "ร");
460 assert_range_eq!(data, 3..3, "");
461 assert_range_eq!(data, 30..33, "华");
473 let ss = "中华Việt Nam";
474 assert_range_eq!(ss, 3..6, "华");
475 assert_range_eq!(ss, 6..16, "Việt Nam");
476 assert_range_eq!(ss, 6..=15, "Việt Nam");
477 assert_range_eq!(ss, 6.., "Việt Nam");
479 assert_range_eq!(ss, 0..3, "中");
480 assert_range_eq!(ss, 3..7, "华V");
481 assert_range_eq!(ss, 3..=6, "华V");
482 assert_range_eq!(ss, 3..3, "");
483 assert_range_eq!(ss, 3..=2, "");
487 #[cfg(not(target_arch = "asmjs"))] // hits an OOM
489 fn a_million_letter_x() -> String {
491 let mut rs = String::new();
493 rs.push_str("华华华华华华华华华华");
498 fn half_a_million_letter_x() -> String {
500 let mut rs = String::new();
502 rs.push_str("华华华华华");
507 let letters = a_million_letter_x();
508 assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
513 fn test_slice_fail() {
518 in mod rangefrom_len {
520 good: data[6..] == "";
522 message: "out of bounds";
527 good: data[..6] == "abcdef";
529 message: "out of bounds";
532 in mod rangetoinclusive_len {
534 good: data[..=5] == "abcdef";
536 message: "out of bounds";
539 in mod range_len_len {
541 good: data[6..6] == "";
543 message: "out of bounds";
546 in mod rangeinclusive_len_len {
548 good: data[6..=5] == "";
550 message: "out of bounds";
555 in mod range_neg_width {
557 good: data[4..4] == "";
559 message: "begin <= end (4 <= 3)";
562 in mod rangeinclusive_neg_width {
564 good: data[4..=3] == "";
566 message: "begin <= end (4 <= 3)";
572 in mod rangeinclusive {
574 // note: using 0 specifically ensures that the result of overflowing is 0..0,
575 // so that `get` doesn't simply return None for the wrong reason.
576 bad: data[0..=usize::max_value()];
577 message: "maximum usize";
580 in mod rangetoinclusive {
582 bad: data[..=usize::max_value()];
583 message: "maximum usize";
589 const DATA: &str = "abcαβγ";
591 const BAD_START: usize = 4;
592 const GOOD_START: usize = 3;
593 const BAD_END: usize = 6;
594 const GOOD_END: usize = 7;
595 const BAD_END_INCL: usize = BAD_END - 1;
596 const GOOD_END_INCL: usize = GOOD_END - 1;
598 // it is especially important to test all of the different range types here
599 // because some of the logic may be duplicated as part of micro-optimizations
600 // to dodge unicode boundary checks on half-ranges.
604 bad: data[super::BAD_START..super::GOOD_END];
606 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
611 bad: data[super::GOOD_START..super::BAD_END];
613 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
618 bad: data[super::BAD_START..];
620 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
625 bad: data[..super::BAD_END];
627 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
630 in mod rangeinclusive_1 {
632 bad: data[super::BAD_START..=super::GOOD_END_INCL];
634 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
637 in mod rangeinclusive_2 {
639 bad: data[super::GOOD_START..=super::BAD_END_INCL];
641 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
644 in mod rangetoinclusive {
646 bad: data[..=super::BAD_END_INCL];
648 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
653 const LOREM_PARAGRAPH: &str = "\
654 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \
655 sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \
656 quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \
657 nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \
658 tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \
661 // check the panic includes the prefix of the sliced string
663 #[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
664 fn test_slice_fail_truncated_1() {
665 &LOREM_PARAGRAPH[..1024];
667 // check the truncation in the panic message
669 #[should_panic(expected="luctus, im`[...]")]
670 fn test_slice_fail_truncated_2() {
671 &LOREM_PARAGRAPH[..1024];
676 fn test_str_slice_rangetoinclusive_ok() {
678 assert_eq!(&s[..=2], "abc");
679 assert_eq!(&s[..=4], "abcα");
684 fn test_str_slice_rangetoinclusive_notok() {
690 fn test_str_slicemut_rangetoinclusive_ok() {
691 let mut s = "abcαβγ".to_owned();
692 let s: &mut str = &mut s;
693 assert_eq!(&mut s[..=2], "abc");
694 assert_eq!(&mut s[..=4], "abcα");
699 fn test_str_slicemut_rangetoinclusive_notok() {
700 let mut s = "abcαβγ".to_owned();
701 let s: &mut str = &mut s;
706 fn test_is_char_boundary() {
707 let s = "ศไทย中华Việt Nam β-release 🐱123";
708 assert!(s.is_char_boundary(0));
709 assert!(s.is_char_boundary(s.len()));
710 assert!(!s.is_char_boundary(s.len() + 1));
711 for (i, ch) in s.char_indices() {
712 // ensure character locations are boundaries and continuation bytes are not
713 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
714 for j in 1..ch.len_utf8() {
715 assert!(!s.is_char_boundary(i + j),
716 "{} should not be a char boundary in {:?}", i + j, s);
722 fn test_trim_start_matches() {
723 let v: &[char] = &[];
724 assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
725 let chars: &[char] = &['*', ' '];
726 assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
727 assert_eq!(" *** *** ".trim_start_matches(chars), "");
728 assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
730 assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
731 let chars: &[char] = &['1', '2'];
732 assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
733 assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
737 fn test_trim_end_matches() {
738 let v: &[char] = &[];
739 assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
740 let chars: &[char] = &['*', ' '];
741 assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
742 assert_eq!(" *** *** ".trim_end_matches(chars), "");
743 assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
745 assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
746 let chars: &[char] = &['1', '2'];
747 assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
748 assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
752 fn test_trim_matches() {
753 let v: &[char] = &[];
754 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
755 let chars: &[char] = &['*', ' '];
756 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
757 assert_eq!(" *** *** ".trim_matches(chars), "");
758 assert_eq!("foo".trim_matches(chars), "foo");
760 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
761 let chars: &[char] = &['1', '2'];
762 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
763 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
767 fn test_trim_start() {
768 assert_eq!("".trim_start(), "");
769 assert_eq!("a".trim_start(), "a");
770 assert_eq!(" ".trim_start(), "");
771 assert_eq!(" blah".trim_start(), "blah");
772 assert_eq!(" \u{3000} wut".trim_start(), "wut");
773 assert_eq!("hey ".trim_start(), "hey ");
778 assert_eq!("".trim_end(), "");
779 assert_eq!("a".trim_end(), "a");
780 assert_eq!(" ".trim_end(), "");
781 assert_eq!("blah ".trim_end(), "blah");
782 assert_eq!("wut \u{3000} ".trim_end(), "wut");
783 assert_eq!(" hey".trim_end(), " hey");
788 assert_eq!("".trim(), "");
789 assert_eq!("a".trim(), "a");
790 assert_eq!(" ".trim(), "");
791 assert_eq!(" blah ".trim(), "blah");
792 assert_eq!("\nwut \u{3000} ".trim(), "wut");
793 assert_eq!(" hey dude ".trim(), "hey dude");
797 fn test_is_whitespace() {
798 assert!("".chars().all(|c| c.is_whitespace()));
799 assert!(" ".chars().all(|c| c.is_whitespace()));
800 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
801 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
802 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
807 // deny overlong encodings
808 assert!(from_utf8(&[0xc0, 0x80]).is_err());
809 assert!(from_utf8(&[0xc0, 0xae]).is_err());
810 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
811 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
812 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
813 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
814 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
817 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
818 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
820 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
821 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
822 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
823 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
824 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
825 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
826 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
827 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
831 fn from_utf8_mostly_ascii() {
832 // deny invalid bytes embedded in long stretches of ascii
834 let mut data = [0; 128];
836 assert!(from_utf8(&data).is_err());
838 assert!(from_utf8(&data).is_err());
843 fn from_utf8_error() {
845 ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
846 let error = from_utf8($input).unwrap_err();
847 assert_eq!(error.valid_up_to(), $expected_valid_up_to);
848 assert_eq!(error.error_len(), $expected_error_len);
851 test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
852 test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
853 test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
854 test!(b"A\xC3\xA9 \xC1", 4, Some(1));
855 test!(b"A\xC3\xA9 \xC2", 4, None);
856 test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
857 test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
858 test!(b"A\xC3\xA9 \xE0", 4, None);
859 test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
860 test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
861 test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
862 test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
863 test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
864 test!(b"A\xC3\xA9 \xF1", 4, None);
865 test!(b"A\xC3\xA9 \xF1\x80", 4, None);
866 test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
867 test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
868 test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
869 test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
876 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
877 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
881 assert_eq!("".as_bytes(), b);
882 assert_eq!("abc".as_bytes(), b"abc");
883 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
888 fn test_as_bytes_fail() {
889 // Don't double free. (I'm not sure if this exercises the
890 // original problem code path anymore.)
891 let s = String::from("");
892 let _bytes = s.as_bytes();
898 let buf = "hello".as_ptr();
900 assert_eq!(*buf.offset(0), b'h');
901 assert_eq!(*buf.offset(1), b'e');
902 assert_eq!(*buf.offset(2), b'l');
903 assert_eq!(*buf.offset(3), b'l');
904 assert_eq!(*buf.offset(4), b'o');
909 fn vec_str_conversions() {
910 let s1: String = String::from("All mimsy were the borogoves");
912 let v: Vec<u8> = s1.as_bytes().to_vec();
913 let s2: String = String::from(from_utf8(&v).unwrap());
919 let a: u8 = s1.as_bytes()[i];
920 let b: u8 = s2.as_bytes()[i];
928 assert!("abcde".contains("bcd"));
929 assert!("abcde".contains("abcd"));
930 assert!("abcde".contains("bcde"));
931 assert!("abcde".contains(""));
932 assert!("".contains(""));
933 assert!(!"abcde".contains("def"));
934 assert!(!"".contains("a"));
936 let data = "ประเทศไทย中华Việt Nam";
937 assert!(data.contains("ประเ"));
938 assert!(data.contains("ะเ"));
939 assert!(data.contains("中华"));
940 assert!(!data.contains("ไท华"));
944 fn test_contains_char() {
945 assert!("abc".contains('b'));
946 assert!("a".contains('a'));
947 assert!(!"abc".contains('d'));
948 assert!(!"".contains('a'));
953 let s = "ศไทย中华Việt Nam";
954 for (index, _) in s.char_indices() {
955 let (a, b) = s.split_at(index);
956 assert_eq!(&s[..a.len()], a);
957 assert_eq!(&s[a.len()..], b);
959 let (a, b) = s.split_at(s.len());
965 fn test_split_at_mut() {
966 let mut s = "Hello World".to_string();
968 let (a, b) = s.split_at_mut(5);
969 a.make_ascii_uppercase();
970 b.make_ascii_lowercase();
972 assert_eq!(s, "HELLO world");
977 fn test_split_at_boundscheck() {
978 let s = "ศไทย中华Việt Nam";
983 fn test_escape_unicode() {
984 assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
985 assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
986 assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
987 assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
988 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
989 assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
990 assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
991 assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
992 assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
996 fn test_escape_debug() {
997 // Note that there are subtleties with the number of backslashes
998 // on the left- and right-hand sides. In particular, Unicode code points
999 // are usually escaped with two backslashes on the right-hand side, as
1000 // they are escaped. However, when the character is unescaped (e.g., for
1001 // printable characters), only a single backslash appears (as the character
1002 // itself appears in the debug string).
1003 assert_eq!("abc".escape_debug(), "abc");
1004 assert_eq!("a c".escape_debug(), "a c");
1005 assert_eq!("éèê".escape_debug(), "éèê");
1006 assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
1007 assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
1008 assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
1009 assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
1010 assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
1011 assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
1012 assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
1013 assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug(), "\\u{301}a\u{301}bé\\u{e000}");
1017 fn test_escape_default() {
1018 assert_eq!("abc".escape_default(), "abc");
1019 assert_eq!("a c".escape_default(), "a c");
1020 assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
1021 assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
1022 assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
1023 assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
1024 assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
1025 assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
1026 assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
1027 assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
1031 fn test_total_ord() {
1032 assert_eq!("1234".cmp("123"), Greater);
1033 assert_eq!("123".cmp("1234"), Less);
1034 assert_eq!("1234".cmp("1234"), Equal);
1035 assert_eq!("12345555".cmp("123456"), Less);
1036 assert_eq!("22".cmp("1234"), Greater);
1040 fn test_iterator() {
1041 let s = "ศไทย中华Việt Nam";
1042 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1048 assert_eq!(c, v[pos]);
1051 assert_eq!(pos, v.len());
1052 assert_eq!(s.chars().count(), v.len());
1056 fn test_rev_iterator() {
1057 let s = "ศไทย中华Việt Nam";
1058 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1061 let it = s.chars().rev();
1064 assert_eq!(c, v[pos]);
1067 assert_eq!(pos, v.len());
1071 fn test_chars_decoding() {
1072 let mut bytes = [0; 4];
1073 for c in (0..0x110000).filter_map(std::char::from_u32) {
1074 let s = c.encode_utf8(&mut bytes);
1075 if Some(c) != s.chars().next() {
1076 panic!("character {:x}={} does not decode correctly", c as u32, c);
1082 fn test_chars_rev_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().rev().next() {
1087 panic!("character {:x}={} does not decode correctly", c as u32, c);
1093 fn test_iterator_clone() {
1094 let s = "ศไทย中华Việt Nam";
1095 let mut it = s.chars();
1097 assert!(it.clone().zip(it).all(|(x,y)| x == y));
1101 fn test_iterator_last() {
1102 let s = "ศไทย中华Việt Nam";
1103 let mut it = s.chars();
1105 assert_eq!(it.last(), Some('m'));
1109 fn test_bytesator() {
1110 let s = "ศไทย中华Việt Nam";
1112 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1113 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1118 for b in s.bytes() {
1119 assert_eq!(b, v[pos]);
1125 fn test_bytes_revator() {
1126 let s = "ศไทย中华Việt Nam";
1128 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1129 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1132 let mut pos = v.len();
1134 for b in s.bytes().rev() {
1136 assert_eq!(b, v[pos]);
1141 fn test_bytesator_nth() {
1142 let s = "ศไทย中华Việt Nam";
1144 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1145 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1149 let mut b = s.bytes();
1150 assert_eq!(b.nth(2).unwrap(), v[2]);
1151 assert_eq!(b.nth(10).unwrap(), v[10]);
1152 assert_eq!(b.nth(200), None);
1156 fn test_bytesator_count() {
1157 let s = "ศไทย中华Việt Nam";
1160 assert_eq!(b.count(), 28)
1164 fn test_bytesator_last() {
1165 let s = "ศไทย中华Việt Nam";
1168 assert_eq!(b.last().unwrap(), 109)
1172 fn test_char_indicesator() {
1173 let s = "ศไทย中华Việt Nam";
1174 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1175 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1178 let it = s.char_indices();
1181 assert_eq!(c, (p[pos], v[pos]));
1184 assert_eq!(pos, v.len());
1185 assert_eq!(pos, p.len());
1189 fn test_char_indices_revator() {
1190 let s = "ศไทย中华Việt Nam";
1191 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1192 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1195 let it = s.char_indices().rev();
1198 assert_eq!(c, (p[pos], v[pos]));
1201 assert_eq!(pos, v.len());
1202 assert_eq!(pos, p.len());
1206 fn test_char_indices_last() {
1207 let s = "ศไทย中华Việt Nam";
1208 let mut it = s.char_indices();
1210 assert_eq!(it.last(), Some((27, 'm')));
1214 fn test_splitn_char_iterator() {
1215 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1217 let split: Vec<&str> = data.splitn(4, ' ').collect();
1218 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1220 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1221 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1224 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1225 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1227 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1228 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1232 fn test_split_char_iterator_no_trailing() {
1233 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1235 let split: Vec<&str> = data.split('\n').collect();
1236 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1238 let split: Vec<&str> = data.split_terminator('\n').collect();
1239 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1244 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1246 let split: Vec<&str> = data.rsplit(' ').collect();
1247 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1249 let split: Vec<&str> = data.rsplit("lämb").collect();
1250 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1252 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1253 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1258 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1260 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1261 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1263 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1264 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1266 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1267 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1271 fn test_split_whitespace() {
1272 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1273 let words: Vec<&str> = data.split_whitespace().collect();
1274 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1279 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1280 let lines: Vec<&str> = data.lines().collect();
1281 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1283 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1284 let lines: Vec<&str> = data.lines().collect();
1285 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1289 fn test_splitator() {
1290 fn t(s: &str, sep: &str, u: &[&str]) {
1291 let v: Vec<&str> = s.split(sep).collect();
1294 t("--1233345--", "12345", &["--1233345--"]);
1295 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1296 t("::hello::there", "::", &["", "hello", "there"]);
1297 t("hello::there::", "::", &["hello", "there", ""]);
1298 t("::hello::there::", "::", &["", "hello", "there", ""]);
1299 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1300 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1301 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1302 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1304 t("zz", "zz", &["",""]);
1305 t("ok", "z", &["ok"]);
1306 t("zzz", "zz", &["","z"]);
1307 t("zzzzz", "zz", &["","","z"]);
1311 fn test_str_default() {
1312 use std::default::Default;
1314 fn t<S: Default + AsRef<str>>() {
1315 let s: S = Default::default();
1316 assert_eq!(s.as_ref(), "");
1325 fn test_str_container() {
1326 fn sum_len(v: &[&str]) -> usize {
1327 v.iter().map(|x| x.len()).sum()
1331 assert_eq!(5, sum_len(&["012", "", "34"]));
1332 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1333 assert_eq!(5, sum_len(&[s]));
1337 fn test_str_from_utf8() {
1339 assert_eq!(from_utf8(xs), Ok("hello"));
1341 let xs = "ศไทย中华Việt Nam".as_bytes();
1342 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1344 let xs = b"hello\xFF";
1345 assert!(from_utf8(xs).is_err());
1349 fn test_pattern_deref_forward() {
1350 let data = "aabcdaa";
1351 assert!(data.contains("bcd"));
1352 assert!(data.contains(&"bcd"));
1353 assert!(data.contains(&"bcd".to_string()));
1357 fn test_empty_match_indices() {
1359 let vec: Vec<_> = data.match_indices("").collect();
1360 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1364 fn test_bool_from_str() {
1365 assert_eq!("true".parse().ok(), Some(true));
1366 assert_eq!("false".parse().ok(), Some(false));
1367 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1370 fn check_contains_all_substrings(s: &str) {
1371 assert!(s.contains(""));
1372 for i in 0..s.len() {
1373 for j in i+1..=s.len() {
1374 assert!(s.contains(&s[i..j]));
1380 fn strslice_issue_16589() {
1381 assert!("bananas".contains("nana"));
1383 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1384 // test all substrings for good measure
1385 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1389 fn strslice_issue_16878() {
1390 assert!(!"1234567ah012345678901ah".contains("hah"));
1391 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1396 fn test_strslice_contains() {
1397 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1398 check_contains_all_substrings(x);
1402 fn test_rsplitn_char_iterator() {
1403 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1405 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1407 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1409 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1411 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1414 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1416 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1418 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1420 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1424 fn test_split_char_iterator() {
1425 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1427 let split: Vec<&str> = data.split(' ').collect();
1428 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1430 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1432 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1434 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1435 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1437 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1439 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1442 let split: Vec<&str> = data.split('ä').collect();
1443 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1445 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1447 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1449 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1450 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1452 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1454 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1458 fn test_rev_split_char_iterator_no_trailing() {
1459 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1461 let mut split: Vec<&str> = data.split('\n').rev().collect();
1463 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1465 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1467 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1471 fn test_utf16_code_units() {
1472 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
1473 [0xE9, 0xD83D, 0xDCA9])
1477 fn starts_with_in_unicode() {
1478 assert!(!"├── Cargo.toml".starts_with("# "));
1482 fn starts_short_long() {
1483 assert!(!"".starts_with("##"));
1484 assert!(!"##".starts_with("####"));
1485 assert!("####".starts_with("##"));
1486 assert!(!"##ä".starts_with("####"));
1487 assert!("####ä".starts_with("##"));
1488 assert!(!"##".starts_with("####ä"));
1489 assert!("##ä##".starts_with("##ä"));
1491 assert!("".starts_with(""));
1492 assert!("ä".starts_with(""));
1493 assert!("#ä".starts_with(""));
1494 assert!("##ä".starts_with(""));
1495 assert!("ä###".starts_with(""));
1496 assert!("#ä##".starts_with(""));
1497 assert!("##ä#".starts_with(""));
1501 fn contains_weird_cases() {
1502 assert!("* \t".contains(' '));
1503 assert!(!"* \t".contains('?'));
1504 assert!(!"* \t".contains('\u{1F4A9}'));
1509 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1511 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1513 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1515 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1517 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
1519 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1521 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1523 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1525 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1527 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
1533 assert_eq!("".to_lowercase(), "");
1534 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1536 // https://github.com/rust-lang/rust/issues/26035
1537 assert_eq!("ΑΣ".to_lowercase(), "ας");
1538 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1539 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1541 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1542 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1543 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1545 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1546 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1548 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1549 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1551 assert_eq!("Α Σ".to_lowercase(), "α σ");
1552 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1553 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
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(), "ασ''α");
1566 assert_eq!("".to_uppercase(), "");
1567 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1571 fn test_into_string() {
1572 // The only way to acquire a Box<str> in the first place is through a String, so just
1573 // test that we can round-trip between Box<str> and String.
1574 let string = String::from("Some text goes here");
1575 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1579 fn test_box_slice_clone() {
1580 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1581 let data2 = data.clone().into_boxed_str().clone().into_string();
1583 assert_eq!(data, data2);
1587 fn test_cow_from() {
1588 let borrowed = "borrowed";
1589 let owned = String::from("owned");
1590 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1591 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1592 _ => panic!("invalid `Cow::from`"),
1598 assert_eq!("".repeat(3), "");
1599 assert_eq!("abc".repeat(0), "");
1600 assert_eq!("α".repeat(3), "ααα");
1604 use std::str::pattern::{
1605 Pattern, Searcher, ReverseSearcher,
1606 SearchStep::{self, Match, Reject, Done},
1609 macro_rules! make_test {
1610 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1611 #[allow(unused_imports)]
1613 use std::str::pattern::SearchStep::{Match, Reject};
1614 use super::{cmp_search_to_vec};
1617 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1621 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1627 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1628 right: Vec<SearchStep>)
1629 where P::Searcher: ReverseSearcher<'a>
1631 let mut searcher = pat.into_searcher(haystack);
1634 match if !rev {searcher.next()} else {searcher.next_back()} {
1635 Match(a, b) => v.push(Match(a, b)),
1636 Reject(a, b) => v.push(Reject(a, b)),
1644 let mut first_index = 0;
1647 for (i, e) in right.iter().enumerate() {
1649 Match(a, b) | Reject(a, b)
1650 if a <= b && a == first_index => {
1660 if let Some(err) = err {
1661 panic!("Input skipped range at {}", err);
1664 if first_index != haystack.len() {
1665 panic!("Did not cover whole input");
1668 assert_eq!(v, right);
1671 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1678 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1686 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1703 make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1708 make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1717 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1720 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1722 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1731 make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1736 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1744 macro_rules! generate_iterator_test {
1748 ($($arg:expr),*) -> [$($t:tt)*];
1751 with $fwd:expr, $bwd:expr;
1757 let res = vec![$($t)*];
1759 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1760 assert_eq!(fwd_vec, res);
1762 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1764 assert_eq!(bwd_vec, res);
1772 ($($arg:expr),*) -> [$($t:tt)*];
1781 let res = vec![$($t)*];
1783 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1784 assert_eq!(fwd_vec, res);
1791 generate_iterator_test! {
1792 double_ended_split {
1793 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1794 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1796 with str::split, str::rsplit;
1799 generate_iterator_test! {
1800 double_ended_split_terminator {
1801 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1803 with str::split_terminator, str::rsplit_terminator;
1806 generate_iterator_test! {
1807 double_ended_matches {
1808 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1810 with str::matches, str::rmatches;
1813 generate_iterator_test! {
1814 double_ended_match_indices {
1815 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1817 with str::match_indices, str::rmatch_indices;
1820 generate_iterator_test! {
1821 not_double_ended_splitn {
1822 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1827 generate_iterator_test! {
1828 not_double_ended_rsplitn {
1829 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1835 fn different_str_pattern_forwarding_lifetimes() {
1836 use std::str::pattern::Pattern;
1838 fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {