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));
36 let s: String = empty.chars().collect();
38 let data = "ประเทศไทย中";
39 let s: String = data.chars().collect();
44 fn test_into_bytes() {
45 let data = String::from("asdf");
46 let buf = data.into_bytes();
47 assert_eq!(buf, b"asdf");
53 assert_eq!("".find(""), Some(0));
54 assert!("banana".find("apple pie").is_none());
57 assert_eq!(data[0..6].find("ab"), Some(0));
58 assert_eq!(data[2..6].find("ab"), Some(3 - 2));
59 assert!(data[2..4].find("ab").is_none());
61 let string = "ประเทศไทย中华Việt Nam";
62 let mut data = String::from(string);
63 data.push_str(string);
64 assert!(data.find("ไท华").is_none());
65 assert_eq!(data[0..43].find(""), Some(0));
66 assert_eq!(data[6..43].find(""), Some(6 - 6));
68 assert_eq!(data[0..43].find("ประ"), Some( 0));
69 assert_eq!(data[0..43].find("ทศไ"), Some(12));
70 assert_eq!(data[0..43].find("ย中"), Some(24));
71 assert_eq!(data[0..43].find("iệt"), Some(34));
72 assert_eq!(data[0..43].find("Nam"), Some(40));
74 assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
75 assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
76 assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
77 assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
78 assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
80 // find every substring -- assert that it finds it, or an earlier occurrence.
81 let string = "Việt Namacbaabcaabaaba";
82 for (i, ci) in string.char_indices() {
83 let ip = i + ci.len_utf8();
84 for j in string[ip..].char_indices()
86 .chain(Some(string.len() - ip))
88 let pat = &string[i..ip + j];
89 assert!(match string.find(pat) {
93 assert!(match string.rfind(pat) {
101 fn s(x: &str) -> String { x.to_string() }
103 macro_rules! test_concat {
104 ($expected: expr, $string: expr) => {
106 let s: String = $string.concat();
107 assert_eq!($expected, s);
113 fn test_concat_for_different_types() {
114 test_concat!("ab", vec![s("a"), s("b")]);
115 test_concat!("ab", vec!["a", "b"]);
119 fn test_concat_for_different_lengths() {
120 let empty: &[&str] = &[];
121 test_concat!("", empty);
122 test_concat!("a", ["a"]);
123 test_concat!("ab", ["a", "b"]);
124 test_concat!("abc", ["", "a", "bc"]);
127 macro_rules! test_join {
128 ($expected: expr, $string: expr, $delim: expr) => {
130 let s = $string.join($delim);
131 assert_eq!($expected, s);
137 fn test_join_for_different_types() {
138 test_join!("a-b", ["a", "b"], "-");
139 let hyphen = "-".to_string();
140 test_join!("a-b", [s("a"), s("b")], &*hyphen);
141 test_join!("a-b", vec!["a", "b"], &*hyphen);
142 test_join!("a-b", &*vec!["a", "b"], "-");
143 test_join!("a-b", vec![s("a"), s("b")], "-");
147 fn test_join_for_different_lengths() {
148 let empty: &[&str] = &[];
149 test_join!("", empty, "-");
150 test_join!("a", ["a"], "-");
151 test_join!("a-b", ["a", "b"], "-");
152 test_join!("-a-bc", ["", "a", "bc"], "-");
155 // join has fast paths for small separators up to 4 bytes
156 // this tests the slow paths.
158 fn test_join_for_different_lengths_with_long_separator() {
159 assert_eq!("~~~~~".len(), 15);
161 let empty: &[&str] = &[];
162 test_join!("", empty, "~~~~~");
163 test_join!("a", ["a"], "~~~~~");
164 test_join!("a~~~~~b", ["a", "b"], "~~~~~");
165 test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
169 #[cfg(not(miri))] // Miri is too slow
170 fn test_unsafe_slice() {
171 assert_eq!("ab", unsafe {"abc".get_unchecked(0..2)});
172 assert_eq!("bc", unsafe {"abc".get_unchecked(1..3)});
173 assert_eq!("", unsafe {"abc".get_unchecked(1..1)});
174 fn a_million_letter_a() -> String {
176 let mut rs = String::new();
178 rs.push_str("aaaaaaaaaa");
183 fn half_a_million_letter_a() -> String {
185 let mut rs = String::new();
187 rs.push_str("aaaaa");
192 let letters = a_million_letter_a();
193 assert_eq!(half_a_million_letter_a(),
194 unsafe { letters.get_unchecked(0..500000)});
198 fn test_starts_with() {
199 assert!("".starts_with(""));
200 assert!("abc".starts_with(""));
201 assert!("abc".starts_with("a"));
202 assert!(!"a".starts_with("abc"));
203 assert!(!"".starts_with("abc"));
204 assert!(!"ödd".starts_with("-"));
205 assert!("ödd".starts_with("öd"));
209 fn test_ends_with() {
210 assert!("".ends_with(""));
211 assert!("abc".ends_with(""));
212 assert!("abc".ends_with("c"));
213 assert!(!"a".ends_with("abc"));
214 assert!(!"".ends_with("abc"));
215 assert!(!"ddö".ends_with("-"));
216 assert!("ddö".ends_with("dö"));
221 assert!("".is_empty());
222 assert!(!"a".is_empty());
227 assert_eq!("".replacen('a', "b", 5), "");
228 assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
229 assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
232 assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
233 assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
234 assert_eq!(" test test ".replacen(test, "", 5), " ");
236 assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
242 assert_eq!("".replace(a, "b"), "");
243 assert_eq!("a".replace(a, "b"), "b");
244 assert_eq!("ab".replace(a, "b"), "bb");
246 assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
247 assert_eq!(" test test ".replace(test, ""), " ");
251 fn test_replace_2a() {
252 let data = "ประเทศไทย中华";
253 let repl = "دولة الكويت";
256 let a2 = "دولة الكويتทศไทย中华";
257 assert_eq!(data.replace(a, repl), a2);
261 fn test_replace_2b() {
262 let data = "ประเทศไทย中华";
263 let repl = "دولة الكويت";
266 let b2 = "ปรدولة الكويتทศไทย中华";
267 assert_eq!(data.replace(b, repl), b2);
271 fn test_replace_2c() {
272 let data = "ประเทศไทย中华";
273 let repl = "دولة الكويت";
276 let c2 = "ประเทศไทยدولة الكويت";
277 assert_eq!(data.replace(c, repl), c2);
281 fn test_replace_2d() {
282 let data = "ประเทศไทย中华";
283 let repl = "دولة الكويت";
286 assert_eq!(data.replace(d, repl), data);
290 fn test_replace_pattern() {
291 let data = "abcdαβγδabcdαβγδ";
292 assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
293 assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
294 assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
295 assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
298 // The current implementation of SliceIndex fails to handle methods
299 // orthogonally from range types; therefore, it is worth testing
300 // all of the indexing operations on each input.
302 // Test a slicing operation **that should succeed,**
303 // testing it on all of the indexing methods.
305 // This is not suitable for testing failure on invalid inputs.
306 macro_rules! assert_range_eq {
307 ($s:expr, $range:expr, $expected:expr)
309 let mut s: String = $s.to_owned();
310 let mut expected: String = $expected.to_owned();
313 let expected: &str = &expected;
315 assert_eq!(&s[$range], expected, "(in assertion for: index)");
316 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
319 s.get_unchecked($range), expected,
320 "(in assertion for: get_unchecked)",
325 let s: &mut str = &mut s;
326 let expected: &mut str = &mut expected;
329 &mut s[$range], expected,
330 "(in assertion for: index_mut)",
333 s.get_mut($range), Some(&mut expected[..]),
334 "(in assertion for: get_mut)",
338 s.get_unchecked_mut($range), expected,
339 "(in assertion for: get_unchecked_mut)",
346 // Make sure the macro can actually detect bugs,
347 // because if it can't, then what are we even doing here?
349 // (Be aware this only demonstrates the ability to detect bugs
350 // in the FIRST method that panics, as the macro is not designed
351 // to be used in `should_panic`)
353 #[should_panic(expected = "out of bounds")]
354 #[cfg(not(miri))] // Miri does not support panics
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 #[cfg(not(miri))] // Miri does not support panics
365 fn assert_range_eq_can_fail_by_inequality() {
366 assert_range_eq!("abc", 0..2, "abc");
369 // Generates test cases for bad index operations.
371 // This generates `should_panic` test cases for Index/IndexMut
372 // and `None` test cases for get/get_mut.
373 macro_rules! panic_cases {
375 in mod $case_name:ident {
380 // a similar input for which DATA[input] succeeds, and the corresponding
381 // output str. This helps validate "critical points" where an input range
382 // straddles the boundary between valid and invalid.
383 // (such as the input `len..len`, which is just barely valid)
385 good: data[$good:expr] == $output:expr;
388 bad: data[$bad:expr];
389 message: $expect_msg:expr; // must be a literal
395 let mut v: String = $data.into();
397 $( assert_range_eq!(v, $good, $output); )*
401 assert_eq!(v.get($bad), None, "(in None assertion for get)");
405 let v: &mut str = &mut v;
406 assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
411 #[should_panic(expected = $expect_msg)]
412 #[cfg(not(miri))] // Miri does not support panics
414 let v: String = $data.into();
420 #[should_panic(expected = $expect_msg)]
421 #[cfg(not(miri))] // Miri does not support panics
422 fn index_mut_fail() {
423 let mut v: String = $data.into();
424 let v: &mut str = &mut v;
425 let _v = &mut v[$bad];
433 assert_range_eq!("abc", .., "abc");
435 assert_range_eq!("abc", 0..2, "ab");
436 assert_range_eq!("abc", 0..=1, "ab");
437 assert_range_eq!("abc", ..2, "ab");
438 assert_range_eq!("abc", ..=1, "ab");
440 assert_range_eq!("abc", 1..3, "bc");
441 assert_range_eq!("abc", 1..=2, "bc");
442 assert_range_eq!("abc", 1..1, "");
443 assert_range_eq!("abc", 1..=0, "");
447 fn simple_unicode() {
449 assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
451 assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
452 assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
453 assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
454 assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
456 assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
457 assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
458 assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
460 let data = "ประเทศไทย中华";
461 assert_range_eq!(data, 0..3, "ป");
462 assert_range_eq!(data, 3..6, "ร");
463 assert_range_eq!(data, 3..3, "");
464 assert_range_eq!(data, 30..33, "华");
476 let ss = "中华Việt Nam";
477 assert_range_eq!(ss, 3..6, "华");
478 assert_range_eq!(ss, 6..16, "Việt Nam");
479 assert_range_eq!(ss, 6..=15, "Việt Nam");
480 assert_range_eq!(ss, 6.., "Việt Nam");
482 assert_range_eq!(ss, 0..3, "中");
483 assert_range_eq!(ss, 3..7, "华V");
484 assert_range_eq!(ss, 3..=6, "华V");
485 assert_range_eq!(ss, 3..3, "");
486 assert_range_eq!(ss, 3..=2, "");
490 #[cfg(not(target_arch = "asmjs"))] // hits an OOM
491 #[cfg(not(miri))] // Miri is too slow
493 fn a_million_letter_x() -> String {
495 let mut rs = String::new();
497 rs.push_str("华华华华华华华华华华");
502 fn half_a_million_letter_x() -> String {
504 let mut rs = String::new();
506 rs.push_str("华华华华华");
511 let letters = a_million_letter_x();
512 assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
517 #[cfg(not(miri))] // Miri does not support panics
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 #[cfg(not(miri))] // Miri does not support panics
670 fn test_slice_fail_truncated_1() {
671 &LOREM_PARAGRAPH[..1024];
673 // check the truncation in the panic message
675 #[should_panic(expected="luctus, im`[...]")]
676 #[cfg(not(miri))] // Miri does not support panics
677 fn test_slice_fail_truncated_2() {
678 &LOREM_PARAGRAPH[..1024];
683 fn test_str_slice_rangetoinclusive_ok() {
685 assert_eq!(&s[..=2], "abc");
686 assert_eq!(&s[..=4], "abcα");
691 #[cfg(not(miri))] // Miri does not support panics
692 fn test_str_slice_rangetoinclusive_notok() {
698 fn test_str_slicemut_rangetoinclusive_ok() {
699 let mut s = "abcαβγ".to_owned();
700 let s: &mut str = &mut s;
701 assert_eq!(&mut s[..=2], "abc");
702 assert_eq!(&mut s[..=4], "abcα");
707 #[cfg(not(miri))] // Miri does not support panics
708 fn test_str_slicemut_rangetoinclusive_notok() {
709 let mut s = "abcαβγ".to_owned();
710 let s: &mut str = &mut s;
715 fn test_is_char_boundary() {
716 let s = "ศไทย中华Việt Nam β-release 🐱123";
717 assert!(s.is_char_boundary(0));
718 assert!(s.is_char_boundary(s.len()));
719 assert!(!s.is_char_boundary(s.len() + 1));
720 for (i, ch) in s.char_indices() {
721 // ensure character locations are boundaries and continuation bytes are not
722 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
723 for j in 1..ch.len_utf8() {
724 assert!(!s.is_char_boundary(i + j),
725 "{} should not be a char boundary in {:?}", i + j, s);
731 fn test_trim_start_matches() {
732 let v: &[char] = &[];
733 assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
734 let chars: &[char] = &['*', ' '];
735 assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
736 assert_eq!(" *** *** ".trim_start_matches(chars), "");
737 assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
739 assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
740 let chars: &[char] = &['1', '2'];
741 assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
742 assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
746 fn test_trim_end_matches() {
747 let v: &[char] = &[];
748 assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
749 let chars: &[char] = &['*', ' '];
750 assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
751 assert_eq!(" *** *** ".trim_end_matches(chars), "");
752 assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
754 assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
755 let chars: &[char] = &['1', '2'];
756 assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
757 assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
761 fn test_trim_matches() {
762 let v: &[char] = &[];
763 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
764 let chars: &[char] = &['*', ' '];
765 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
766 assert_eq!(" *** *** ".trim_matches(chars), "");
767 assert_eq!("foo".trim_matches(chars), "foo");
769 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
770 let chars: &[char] = &['1', '2'];
771 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
772 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
776 fn test_trim_start() {
777 assert_eq!("".trim_start(), "");
778 assert_eq!("a".trim_start(), "a");
779 assert_eq!(" ".trim_start(), "");
780 assert_eq!(" blah".trim_start(), "blah");
781 assert_eq!(" \u{3000} wut".trim_start(), "wut");
782 assert_eq!("hey ".trim_start(), "hey ");
787 assert_eq!("".trim_end(), "");
788 assert_eq!("a".trim_end(), "a");
789 assert_eq!(" ".trim_end(), "");
790 assert_eq!("blah ".trim_end(), "blah");
791 assert_eq!("wut \u{3000} ".trim_end(), "wut");
792 assert_eq!(" hey".trim_end(), " hey");
797 assert_eq!("".trim(), "");
798 assert_eq!("a".trim(), "a");
799 assert_eq!(" ".trim(), "");
800 assert_eq!(" blah ".trim(), "blah");
801 assert_eq!("\nwut \u{3000} ".trim(), "wut");
802 assert_eq!(" hey dude ".trim(), "hey dude");
806 fn test_is_whitespace() {
807 assert!("".chars().all(|c| c.is_whitespace()));
808 assert!(" ".chars().all(|c| c.is_whitespace()));
809 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
810 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
811 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
816 // deny overlong encodings
817 assert!(from_utf8(&[0xc0, 0x80]).is_err());
818 assert!(from_utf8(&[0xc0, 0xae]).is_err());
819 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
820 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
821 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
822 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
823 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
826 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
827 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
829 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
830 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
831 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
832 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
833 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
834 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
835 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
836 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
840 fn from_utf8_mostly_ascii() {
841 // deny invalid bytes embedded in long stretches of ascii
843 let mut data = [0; 128];
845 assert!(from_utf8(&data).is_err());
847 assert!(from_utf8(&data).is_err());
852 fn from_utf8_error() {
854 ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
855 let error = from_utf8($input).unwrap_err();
856 assert_eq!(error.valid_up_to(), $expected_valid_up_to);
857 assert_eq!(error.error_len(), $expected_error_len);
860 test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
861 test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
862 test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
863 test!(b"A\xC3\xA9 \xC1", 4, Some(1));
864 test!(b"A\xC3\xA9 \xC2", 4, None);
865 test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
866 test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
867 test!(b"A\xC3\xA9 \xE0", 4, None);
868 test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
869 test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
870 test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
871 test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
872 test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
873 test!(b"A\xC3\xA9 \xF1", 4, None);
874 test!(b"A\xC3\xA9 \xF1\x80", 4, None);
875 test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
876 test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
877 test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
878 test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
885 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
886 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
890 assert_eq!("".as_bytes(), b);
891 assert_eq!("abc".as_bytes(), b"abc");
892 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
897 #[cfg(not(miri))] // Miri does not support panics
898 fn test_as_bytes_fail() {
899 // Don't double free. (I'm not sure if this exercises the
900 // original problem code path anymore.)
901 let s = String::from("");
902 let _bytes = s.as_bytes();
908 let buf = "hello".as_ptr();
910 assert_eq!(*buf.offset(0), b'h');
911 assert_eq!(*buf.offset(1), b'e');
912 assert_eq!(*buf.offset(2), b'l');
913 assert_eq!(*buf.offset(3), b'l');
914 assert_eq!(*buf.offset(4), b'o');
919 fn vec_str_conversions() {
920 let s1: String = String::from("All mimsy were the borogoves");
922 let v: Vec<u8> = s1.as_bytes().to_vec();
923 let s2: String = String::from(from_utf8(&v).unwrap());
929 let a: u8 = s1.as_bytes()[i];
930 let b: u8 = s2.as_bytes()[i];
938 assert!("abcde".contains("bcd"));
939 assert!("abcde".contains("abcd"));
940 assert!("abcde".contains("bcde"));
941 assert!("abcde".contains(""));
942 assert!("".contains(""));
943 assert!(!"abcde".contains("def"));
944 assert!(!"".contains("a"));
946 let data = "ประเทศไทย中华Việt Nam";
947 assert!(data.contains("ประเ"));
948 assert!(data.contains("ะเ"));
949 assert!(data.contains("中华"));
950 assert!(!data.contains("ไท华"));
954 fn test_contains_char() {
955 assert!("abc".contains('b'));
956 assert!("a".contains('a'));
957 assert!(!"abc".contains('d'));
958 assert!(!"".contains('a'));
963 let s = "ศไทย中华Việt Nam";
964 for (index, _) in s.char_indices() {
965 let (a, b) = s.split_at(index);
966 assert_eq!(&s[..a.len()], a);
967 assert_eq!(&s[a.len()..], b);
969 let (a, b) = s.split_at(s.len());
975 fn test_split_at_mut() {
976 let mut s = "Hello World".to_string();
978 let (a, b) = s.split_at_mut(5);
979 a.make_ascii_uppercase();
980 b.make_ascii_lowercase();
982 assert_eq!(s, "HELLO world");
987 #[cfg(not(miri))] // Miri does not support panics
988 fn test_split_at_boundscheck() {
989 let s = "ศไทย中华Việt Nam";
994 fn test_escape_unicode() {
995 assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}");
996 assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
997 assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
998 assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
999 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
1000 assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
1001 assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
1002 assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
1003 assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}");
1007 fn test_escape_debug() {
1008 // Note that there are subtleties with the number of backslashes
1009 // on the left- and right-hand sides. In particular, Unicode code points
1010 // are usually escaped with two backslashes on the right-hand side, as
1011 // they are escaped. However, when the character is unescaped (e.g., for
1012 // printable characters), only a single backslash appears (as the character
1013 // itself appears in the debug string).
1014 assert_eq!("abc".escape_debug().to_string(), "abc");
1015 assert_eq!("a c".escape_debug().to_string(), "a c");
1016 assert_eq!("éèê".escape_debug().to_string(), "éèê");
1017 assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1018 assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1019 assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1020 assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1021 assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1022 assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1023 assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1024 assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1025 "\\u{301}a\u{301}bé\\u{e000}");
1029 fn test_escape_default() {
1030 assert_eq!("abc".escape_default().to_string(), "abc");
1031 assert_eq!("a c".escape_default().to_string(), "a c");
1032 assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1033 assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1034 assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1035 assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1036 assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1037 assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1038 assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1039 assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1043 fn test_total_ord() {
1044 assert_eq!("1234".cmp("123"), Greater);
1045 assert_eq!("123".cmp("1234"), Less);
1046 assert_eq!("1234".cmp("1234"), Equal);
1047 assert_eq!("12345555".cmp("123456"), Less);
1048 assert_eq!("22".cmp("1234"), Greater);
1052 fn test_iterator() {
1053 let s = "ศไทย中华Việt Nam";
1054 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1060 assert_eq!(c, v[pos]);
1063 assert_eq!(pos, v.len());
1064 assert_eq!(s.chars().count(), v.len());
1068 fn test_rev_iterator() {
1069 let s = "ศไทย中华Việt Nam";
1070 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1073 let it = s.chars().rev();
1076 assert_eq!(c, v[pos]);
1079 assert_eq!(pos, v.len());
1083 #[cfg(not(miri))] // Miri is too slow
1084 fn test_chars_decoding() {
1085 let mut bytes = [0; 4];
1086 for c in (0..0x110000).filter_map(std::char::from_u32) {
1087 let s = c.encode_utf8(&mut bytes);
1088 if Some(c) != s.chars().next() {
1089 panic!("character {:x}={} does not decode correctly", c as u32, c);
1095 #[cfg(not(miri))] // Miri is too slow
1096 fn test_chars_rev_decoding() {
1097 let mut bytes = [0; 4];
1098 for c in (0..0x110000).filter_map(std::char::from_u32) {
1099 let s = c.encode_utf8(&mut bytes);
1100 if Some(c) != s.chars().rev().next() {
1101 panic!("character {:x}={} does not decode correctly", c as u32, c);
1107 fn test_iterator_clone() {
1108 let s = "ศไทย中华Việt Nam";
1109 let mut it = s.chars();
1111 assert!(it.clone().zip(it).all(|(x,y)| x == y));
1115 fn test_iterator_last() {
1116 let s = "ศไทย中华Việt Nam";
1117 let mut it = s.chars();
1119 assert_eq!(it.last(), Some('m'));
1123 fn test_bytesator() {
1124 let s = "ศไทย中华Việt Nam";
1126 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1127 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1132 for b in s.bytes() {
1133 assert_eq!(b, v[pos]);
1139 fn test_bytes_revator() {
1140 let s = "ศไทย中华Việt Nam";
1142 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1143 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1146 let mut pos = v.len();
1148 for b in s.bytes().rev() {
1150 assert_eq!(b, v[pos]);
1155 fn test_bytesator_nth() {
1156 let s = "ศไทย中华Việt Nam";
1158 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1159 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1163 let mut b = s.bytes();
1164 assert_eq!(b.nth(2).unwrap(), v[2]);
1165 assert_eq!(b.nth(10).unwrap(), v[10]);
1166 assert_eq!(b.nth(200), None);
1170 fn test_bytesator_count() {
1171 let s = "ศไทย中华Việt Nam";
1174 assert_eq!(b.count(), 28)
1178 fn test_bytesator_last() {
1179 let s = "ศไทย中华Việt Nam";
1182 assert_eq!(b.last().unwrap(), 109)
1186 fn test_char_indicesator() {
1187 let s = "ศไทย中华Việt Nam";
1188 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1189 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1192 let it = s.char_indices();
1195 assert_eq!(c, (p[pos], v[pos]));
1198 assert_eq!(pos, v.len());
1199 assert_eq!(pos, p.len());
1203 fn test_char_indices_revator() {
1204 let s = "ศไทย中华Việt Nam";
1205 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1206 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1209 let it = s.char_indices().rev();
1212 assert_eq!(c, (p[pos], v[pos]));
1215 assert_eq!(pos, v.len());
1216 assert_eq!(pos, p.len());
1220 fn test_char_indices_last() {
1221 let s = "ศไทย中华Việt Nam";
1222 let mut it = s.char_indices();
1224 assert_eq!(it.last(), Some((27, 'm')));
1228 fn test_splitn_char_iterator() {
1229 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1231 let split: Vec<&str> = data.splitn(4, ' ').collect();
1232 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1234 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1235 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1238 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1239 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1241 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1242 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1246 fn test_split_char_iterator_no_trailing() {
1247 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1249 let split: Vec<&str> = data.split('\n').collect();
1250 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1252 let split: Vec<&str> = data.split_terminator('\n').collect();
1253 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1258 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1260 let split: Vec<&str> = data.rsplit(' ').collect();
1261 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1263 let split: Vec<&str> = data.rsplit("lämb").collect();
1264 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1266 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1267 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1272 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1274 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1275 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1277 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1278 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1280 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1281 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1285 fn test_split_whitespace() {
1286 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1287 let words: Vec<&str> = data.split_whitespace().collect();
1288 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1293 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1294 let lines: Vec<&str> = data.lines().collect();
1295 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1297 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1298 let lines: Vec<&str> = data.lines().collect();
1299 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1303 fn test_splitator() {
1304 fn t(s: &str, sep: &str, u: &[&str]) {
1305 let v: Vec<&str> = s.split(sep).collect();
1308 t("--1233345--", "12345", &["--1233345--"]);
1309 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1310 t("::hello::there", "::", &["", "hello", "there"]);
1311 t("hello::there::", "::", &["hello", "there", ""]);
1312 t("::hello::there::", "::", &["", "hello", "there", ""]);
1313 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1314 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1315 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1316 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1318 t("zz", "zz", &["",""]);
1319 t("ok", "z", &["ok"]);
1320 t("zzz", "zz", &["","z"]);
1321 t("zzzzz", "zz", &["","","z"]);
1325 fn test_str_default() {
1326 use std::default::Default;
1328 fn t<S: Default + AsRef<str>>() {
1329 let s: S = Default::default();
1330 assert_eq!(s.as_ref(), "");
1339 fn test_str_container() {
1340 fn sum_len(v: &[&str]) -> usize {
1341 v.iter().map(|x| x.len()).sum()
1345 assert_eq!(5, sum_len(&["012", "", "34"]));
1346 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1347 assert_eq!(5, sum_len(&[s]));
1351 fn test_str_from_utf8() {
1353 assert_eq!(from_utf8(xs), Ok("hello"));
1355 let xs = "ศไทย中华Việt Nam".as_bytes();
1356 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1358 let xs = b"hello\xFF";
1359 assert!(from_utf8(xs).is_err());
1363 fn test_pattern_deref_forward() {
1364 let data = "aabcdaa";
1365 assert!(data.contains("bcd"));
1366 assert!(data.contains(&"bcd"));
1367 assert!(data.contains(&"bcd".to_string()));
1371 fn test_empty_match_indices() {
1373 let vec: Vec<_> = data.match_indices("").collect();
1374 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1378 fn test_bool_from_str() {
1379 assert_eq!("true".parse().ok(), Some(true));
1380 assert_eq!("false".parse().ok(), Some(false));
1381 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1384 #[cfg(not(miri))] // Miri is too slow
1385 fn check_contains_all_substrings(s: &str) {
1386 assert!(s.contains(""));
1387 for i in 0..s.len() {
1388 for j in i+1..=s.len() {
1389 assert!(s.contains(&s[i..j]));
1395 #[cfg(not(miri))] // Miri is too slow
1396 fn strslice_issue_16589() {
1397 assert!("bananas".contains("nana"));
1399 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1400 // test all substrings for good measure
1401 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1405 fn strslice_issue_16878() {
1406 assert!(!"1234567ah012345678901ah".contains("hah"));
1407 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1412 #[cfg(not(miri))] // Miri is too slow
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()),
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(), "ασ''α");
1583 assert_eq!("".to_uppercase(), "");
1584 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1588 fn test_into_string() {
1589 // The only way to acquire a Box<str> in the first place is through a String, so just
1590 // test that we can round-trip between Box<str> and String.
1591 let string = String::from("Some text goes here");
1592 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1596 fn test_box_slice_clone() {
1597 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1598 let data2 = data.clone().into_boxed_str().clone().into_string();
1600 assert_eq!(data, data2);
1604 fn test_cow_from() {
1605 let borrowed = "borrowed";
1606 let owned = String::from("owned");
1607 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1608 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1609 _ => panic!("invalid `Cow::from`"),
1615 assert_eq!("".repeat(3), "");
1616 assert_eq!("abc".repeat(0), "");
1617 assert_eq!("α".repeat(3), "ααα");
1621 use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
1622 use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1624 macro_rules! make_test {
1625 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1626 #[allow(unused_imports)]
1628 use std::str::pattern::SearchStep::{Match, Reject};
1629 use super::{cmp_search_to_vec};
1632 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1636 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1642 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1643 right: Vec<SearchStep>)
1644 where P::Searcher: ReverseSearcher<'a>
1646 let mut searcher = pat.into_searcher(haystack);
1649 match if !rev {searcher.next()} else {searcher.next_back()} {
1650 Match(a, b) => v.push(Match(a, b)),
1651 Reject(a, b) => v.push(Reject(a, b)),
1659 let mut first_index = 0;
1662 for (i, e) in right.iter().enumerate() {
1664 Match(a, b) | Reject(a, b)
1665 if a <= b && a == first_index => {
1675 if let Some(err) = err {
1676 panic!("Input skipped range at {}", err);
1679 if first_index != haystack.len() {
1680 panic!("Did not cover whole input");
1683 assert_eq!(v, right);
1686 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1693 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1701 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1718 make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1723 make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1732 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1735 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1737 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1746 make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1751 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1759 macro_rules! generate_iterator_test {
1763 ($($arg:expr),*) -> [$($t:tt)*];
1766 with $fwd:expr, $bwd:expr;
1772 let res = vec![$($t)*];
1774 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1775 assert_eq!(fwd_vec, res);
1777 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1779 assert_eq!(bwd_vec, res);
1787 ($($arg:expr),*) -> [$($t:tt)*];
1796 let res = vec![$($t)*];
1798 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1799 assert_eq!(fwd_vec, res);
1806 generate_iterator_test! {
1807 double_ended_split {
1808 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1809 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1811 with str::split, str::rsplit;
1814 generate_iterator_test! {
1815 double_ended_split_terminator {
1816 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1818 with str::split_terminator, str::rsplit_terminator;
1821 generate_iterator_test! {
1822 double_ended_matches {
1823 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1825 with str::matches, str::rmatches;
1828 generate_iterator_test! {
1829 double_ended_match_indices {
1830 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1832 with str::match_indices, str::rmatch_indices;
1835 generate_iterator_test! {
1836 not_double_ended_splitn {
1837 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1842 generate_iterator_test! {
1843 not_double_ended_rsplitn {
1844 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1850 fn different_str_pattern_forwarding_lifetimes() {
1851 use std::str::pattern::Pattern;
1853 fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {