2 use std::cmp::Ordering::{Equal, Greater, Less};
3 use std::str::from_utf8;
9 assert!("foo" <= "foo");
10 assert_ne!("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 fn assert_range_eq_can_fail_by_panic() {
355 assert_range_eq!("abc", 0..5, "abc");
358 // (Be aware this only demonstrates the ability to detect bugs
359 // in the FIRST method it calls, as the macro is not designed
360 // to be used in `should_panic`)
362 #[should_panic(expected = "==")]
363 fn assert_range_eq_can_fail_by_inequality() {
364 assert_range_eq!("abc", 0..2, "abc");
367 // Generates test cases for bad index operations.
369 // This generates `should_panic` test cases for Index/IndexMut
370 // and `None` test cases for get/get_mut.
371 macro_rules! panic_cases {
373 in mod $case_name:ident {
378 // a similar input for which DATA[input] succeeds, and the corresponding
379 // output str. This helps validate "critical points" where an input range
380 // straddles the boundary between valid and invalid.
381 // (such as the input `len..len`, which is just barely valid)
383 good: data[$good:expr] == $output:expr;
386 bad: data[$bad:expr];
387 message: $expect_msg:expr; // must be a literal
393 let mut v: String = $data.into();
395 $( assert_range_eq!(v, $good, $output); )*
399 assert_eq!(v.get($bad), None, "(in None assertion for get)");
403 let v: &mut str = &mut v;
404 assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
409 #[should_panic(expected = $expect_msg)]
411 let v: String = $data.into();
417 #[should_panic(expected = $expect_msg)]
418 fn index_mut_fail() {
419 let mut v: String = $data.into();
420 let v: &mut str = &mut v;
421 let _v = &mut v[$bad];
429 assert_range_eq!("abc", .., "abc");
431 assert_range_eq!("abc", 0..2, "ab");
432 assert_range_eq!("abc", 0..=1, "ab");
433 assert_range_eq!("abc", ..2, "ab");
434 assert_range_eq!("abc", ..=1, "ab");
436 assert_range_eq!("abc", 1..3, "bc");
437 assert_range_eq!("abc", 1..=2, "bc");
438 assert_range_eq!("abc", 1..1, "");
439 assert_range_eq!("abc", 1..=0, "");
443 fn simple_unicode() {
445 assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
447 assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
448 assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
449 assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
450 assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
452 assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
453 assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
454 assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
456 let data = "ประเทศไทย中华";
457 assert_range_eq!(data, 0..3, "ป");
458 assert_range_eq!(data, 3..6, "ร");
459 assert_range_eq!(data, 3..3, "");
460 assert_range_eq!(data, 30..33, "华");
472 let ss = "中华Việt Nam";
473 assert_range_eq!(ss, 3..6, "华");
474 assert_range_eq!(ss, 6..16, "Việt Nam");
475 assert_range_eq!(ss, 6..=15, "Việt Nam");
476 assert_range_eq!(ss, 6.., "Việt Nam");
478 assert_range_eq!(ss, 0..3, "中");
479 assert_range_eq!(ss, 3..7, "华V");
480 assert_range_eq!(ss, 3..=6, "华V");
481 assert_range_eq!(ss, 3..3, "");
482 assert_range_eq!(ss, 3..=2, "");
486 #[cfg(not(target_arch = "asmjs"))] // hits an OOM
487 #[cfg(not(miri))] // Miri is too slow
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().to_string(), "\\u{61}\\u{62}\\u{63}");
985 assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
986 assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
987 assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
988 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
989 assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
990 assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
991 assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
992 assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\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().to_string(), "abc");
1004 assert_eq!("a c".escape_debug().to_string(), "a c");
1005 assert_eq!("éèê".escape_debug().to_string(), "éèê");
1006 assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1007 assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1008 assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1009 assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1010 assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1011 assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1012 assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1013 assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1014 "\\u{301}a\u{301}bé\\u{e000}");
1018 fn test_escape_default() {
1019 assert_eq!("abc".escape_default().to_string(), "abc");
1020 assert_eq!("a c".escape_default().to_string(), "a c");
1021 assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1022 assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1023 assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1024 assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1025 assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1026 assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1027 assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1028 assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1032 fn test_total_ord() {
1033 assert_eq!("1234".cmp("123"), Greater);
1034 assert_eq!("123".cmp("1234"), Less);
1035 assert_eq!("1234".cmp("1234"), Equal);
1036 assert_eq!("12345555".cmp("123456"), Less);
1037 assert_eq!("22".cmp("1234"), Greater);
1041 fn test_iterator() {
1042 let s = "ศไทย中华Việt Nam";
1043 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1049 assert_eq!(c, v[pos]);
1052 assert_eq!(pos, v.len());
1053 assert_eq!(s.chars().count(), v.len());
1057 fn test_rev_iterator() {
1058 let s = "ศไทย中华Việt Nam";
1059 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1062 let it = s.chars().rev();
1065 assert_eq!(c, v[pos]);
1068 assert_eq!(pos, v.len());
1072 #[cfg(not(miri))] // Miri is too slow
1073 fn test_chars_decoding() {
1074 let mut bytes = [0; 4];
1075 for c in (0..0x110000).filter_map(std::char::from_u32) {
1076 let s = c.encode_utf8(&mut bytes);
1077 if Some(c) != s.chars().next() {
1078 panic!("character {:x}={} does not decode correctly", c as u32, c);
1084 #[cfg(not(miri))] // Miri is too slow
1085 fn test_chars_rev_decoding() {
1086 let mut bytes = [0; 4];
1087 for c in (0..0x110000).filter_map(std::char::from_u32) {
1088 let s = c.encode_utf8(&mut bytes);
1089 if Some(c) != s.chars().rev().next() {
1090 panic!("character {:x}={} does not decode correctly", c as u32, c);
1096 fn test_iterator_clone() {
1097 let s = "ศไทย中华Việt Nam";
1098 let mut it = s.chars();
1100 assert!(it.clone().zip(it).all(|(x,y)| x == y));
1104 fn test_iterator_last() {
1105 let s = "ศไทย中华Việt Nam";
1106 let mut it = s.chars();
1108 assert_eq!(it.last(), Some('m'));
1112 fn test_chars_debug() {
1113 let s = "ศไทย中华Việt Nam";
1117 r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"#
1122 fn test_bytesator() {
1123 let s = "ศไทย中华Việt Nam";
1125 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1126 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1131 for b in s.bytes() {
1132 assert_eq!(b, v[pos]);
1138 fn test_bytes_revator() {
1139 let s = "ศไทย中华Việt Nam";
1141 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1142 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1145 let mut pos = v.len();
1147 for b in s.bytes().rev() {
1149 assert_eq!(b, v[pos]);
1154 fn test_bytesator_nth() {
1155 let s = "ศไทย中华Việt Nam";
1157 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1158 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1162 let mut b = s.bytes();
1163 assert_eq!(b.nth(2).unwrap(), v[2]);
1164 assert_eq!(b.nth(10).unwrap(), v[10]);
1165 assert_eq!(b.nth(200), None);
1169 fn test_bytesator_count() {
1170 let s = "ศไทย中华Việt Nam";
1173 assert_eq!(b.count(), 28)
1177 fn test_bytesator_last() {
1178 let s = "ศไทย中华Việt Nam";
1181 assert_eq!(b.last().unwrap(), 109)
1185 fn test_char_indicesator() {
1186 let s = "ศไทย中华Việt Nam";
1187 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1188 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1191 let it = s.char_indices();
1194 assert_eq!(c, (p[pos], v[pos]));
1197 assert_eq!(pos, v.len());
1198 assert_eq!(pos, p.len());
1202 fn test_char_indices_revator() {
1203 let s = "ศไทย中华Việt Nam";
1204 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1205 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1208 let it = s.char_indices().rev();
1211 assert_eq!(c, (p[pos], v[pos]));
1214 assert_eq!(pos, v.len());
1215 assert_eq!(pos, p.len());
1219 fn test_char_indices_last() {
1220 let s = "ศไทย中华Việt Nam";
1221 let mut it = s.char_indices();
1223 assert_eq!(it.last(), Some((27, 'm')));
1227 fn test_splitn_char_iterator() {
1228 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1230 let split: Vec<&str> = data.splitn(4, ' ').collect();
1231 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1233 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1234 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1237 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1238 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1240 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1241 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1245 fn test_split_char_iterator_no_trailing() {
1246 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1248 let split: Vec<&str> = data.split('\n').collect();
1249 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1251 let split: Vec<&str> = data.split_terminator('\n').collect();
1252 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1257 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1259 let split: Vec<&str> = data.rsplit(' ').collect();
1260 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1262 let split: Vec<&str> = data.rsplit("lämb").collect();
1263 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1265 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1266 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1271 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1273 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1274 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1276 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1277 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1279 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1280 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1284 fn test_split_whitespace() {
1285 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1286 let words: Vec<&str> = data.split_whitespace().collect();
1287 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1292 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1293 let lines: Vec<&str> = data.lines().collect();
1294 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1296 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1297 let lines: Vec<&str> = data.lines().collect();
1298 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1302 fn test_splitator() {
1303 fn t(s: &str, sep: &str, u: &[&str]) {
1304 let v: Vec<&str> = s.split(sep).collect();
1307 t("--1233345--", "12345", &["--1233345--"]);
1308 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1309 t("::hello::there", "::", &["", "hello", "there"]);
1310 t("hello::there::", "::", &["hello", "there", ""]);
1311 t("::hello::there::", "::", &["", "hello", "there", ""]);
1312 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1313 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1314 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1315 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1317 t("zz", "zz", &["",""]);
1318 t("ok", "z", &["ok"]);
1319 t("zzz", "zz", &["","z"]);
1320 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);
1383 #[cfg(not(miri))] // Miri is too slow
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]));
1394 #[cfg(not(miri))] // Miri is too slow
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");
1404 fn strslice_issue_16878() {
1405 assert!(!"1234567ah012345678901ah".contains("hah"));
1406 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1411 #[cfg(not(miri))] // Miri is too slow
1412 fn test_strslice_contains() {
1413 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1414 check_contains_all_substrings(x);
1418 fn test_rsplitn_char_iterator() {
1419 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1421 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1423 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1425 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1427 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1430 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1432 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1434 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1436 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1440 fn test_split_char_iterator() {
1441 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1443 let split: Vec<&str> = data.split(' ').collect();
1444 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1446 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1448 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1450 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1451 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1453 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1455 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1458 let split: Vec<&str> = data.split('ä').collect();
1459 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1461 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1463 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1465 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1466 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1468 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1470 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1474 fn test_rev_split_char_iterator_no_trailing() {
1475 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1477 let mut split: Vec<&str> = data.split('\n').rev().collect();
1479 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1481 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1483 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1487 fn test_utf16_code_units() {
1488 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
1489 [0xE9, 0xD83D, 0xDCA9])
1493 fn starts_with_in_unicode() {
1494 assert!(!"├── Cargo.toml".starts_with("# "));
1498 fn starts_short_long() {
1499 assert!(!"".starts_with("##"));
1500 assert!(!"##".starts_with("####"));
1501 assert!("####".starts_with("##"));
1502 assert!(!"##ä".starts_with("####"));
1503 assert!("####ä".starts_with("##"));
1504 assert!(!"##".starts_with("####ä"));
1505 assert!("##ä##".starts_with("##ä"));
1507 assert!("".starts_with(""));
1508 assert!("ä".starts_with(""));
1509 assert!("#ä".starts_with(""));
1510 assert!("##ä".starts_with(""));
1511 assert!("ä###".starts_with(""));
1512 assert!("#ä##".starts_with(""));
1513 assert!("##ä#".starts_with(""));
1517 fn contains_weird_cases() {
1518 assert!("* \t".contains(' '));
1519 assert!(!"* \t".contains('?'));
1520 assert!(!"* \t".contains('\u{1F4A9}'));
1525 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1527 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1529 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1531 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1533 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
1535 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1537 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1539 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1541 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1543 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
1549 assert_eq!("".to_lowercase(), "");
1550 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1552 // https://github.com/rust-lang/rust/issues/26035
1553 assert_eq!("ΑΣ".to_lowercase(), "ας");
1554 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1555 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1557 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1558 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1559 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1561 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1562 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1564 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1565 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1567 assert_eq!("Α Σ".to_lowercase(), "α σ");
1568 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1569 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1571 assert_eq!("Σ".to_lowercase(), "σ");
1572 assert_eq!("'Σ".to_lowercase(), "'σ");
1573 assert_eq!("''Σ".to_lowercase(), "''σ");
1575 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1576 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1577 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1582 assert_eq!("".to_uppercase(), "");
1583 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1587 fn test_into_string() {
1588 // The only way to acquire a Box<str> in the first place is through a String, so just
1589 // test that we can round-trip between Box<str> and String.
1590 let string = String::from("Some text goes here");
1591 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1595 fn test_box_slice_clone() {
1596 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1597 let data2 = data.clone().into_boxed_str().clone().into_string();
1599 assert_eq!(data, data2);
1603 fn test_cow_from() {
1604 let borrowed = "borrowed";
1605 let owned = String::from("owned");
1606 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1607 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1608 _ => panic!("invalid `Cow::from`"),
1614 assert_eq!("".repeat(3), "");
1615 assert_eq!("abc".repeat(0), "");
1616 assert_eq!("α".repeat(3), "ααα");
1620 use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
1621 use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1623 macro_rules! make_test {
1624 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1625 #[allow(unused_imports)]
1627 use std::str::pattern::SearchStep::{Match, Reject};
1628 use super::{cmp_search_to_vec};
1631 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1635 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1641 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1642 right: Vec<SearchStep>)
1643 where P::Searcher: ReverseSearcher<'a>
1645 let mut searcher = pat.into_searcher(haystack);
1648 match if !rev {searcher.next()} else {searcher.next_back()} {
1649 Match(a, b) => v.push(Match(a, b)),
1650 Reject(a, b) => v.push(Reject(a, b)),
1658 let mut first_index = 0;
1661 for (i, e) in right.iter().enumerate() {
1663 Match(a, b) | Reject(a, b)
1664 if a <= b && a == first_index => {
1674 if let Some(err) = err {
1675 panic!("Input skipped range at {}", err);
1678 if first_index != haystack.len() {
1679 panic!("Did not cover whole input");
1682 assert_eq!(v, right);
1685 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1692 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1700 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1717 make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1722 make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1731 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1734 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1736 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1745 make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1750 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1758 macro_rules! generate_iterator_test {
1762 ($($arg:expr),*) -> [$($t:tt)*];
1765 with $fwd:expr, $bwd:expr;
1771 let res = vec![$($t)*];
1773 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1774 assert_eq!(fwd_vec, res);
1776 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1778 assert_eq!(bwd_vec, res);
1786 ($($arg:expr),*) -> [$($t:tt)*];
1795 let res = vec![$($t)*];
1797 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1798 assert_eq!(fwd_vec, res);
1805 generate_iterator_test! {
1806 double_ended_split {
1807 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1808 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1810 with str::split, str::rsplit;
1813 generate_iterator_test! {
1814 double_ended_split_terminator {
1815 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1817 with str::split_terminator, str::rsplit_terminator;
1820 generate_iterator_test! {
1821 double_ended_matches {
1822 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1824 with str::matches, str::rmatches;
1827 generate_iterator_test! {
1828 double_ended_match_indices {
1829 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1831 with str::match_indices, str::rmatch_indices;
1834 generate_iterator_test! {
1835 not_double_ended_splitn {
1836 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1841 generate_iterator_test! {
1842 not_double_ended_rsplitn {
1843 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1849 fn different_str_pattern_forwarding_lifetimes() {
1850 use std::str::pattern::Pattern;
1852 fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {