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_bytesator() {
1113 let s = "ศไทย中华Việt Nam";
1115 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1116 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1121 for b in s.bytes() {
1122 assert_eq!(b, v[pos]);
1128 fn test_bytes_revator() {
1129 let s = "ศไทย中华Việt Nam";
1131 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1132 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1135 let mut pos = v.len();
1137 for b in s.bytes().rev() {
1139 assert_eq!(b, v[pos]);
1144 fn test_bytesator_nth() {
1145 let s = "ศไทย中华Việt Nam";
1147 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1148 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1152 let mut b = s.bytes();
1153 assert_eq!(b.nth(2).unwrap(), v[2]);
1154 assert_eq!(b.nth(10).unwrap(), v[10]);
1155 assert_eq!(b.nth(200), None);
1159 fn test_bytesator_count() {
1160 let s = "ศไทย中华Việt Nam";
1163 assert_eq!(b.count(), 28)
1167 fn test_bytesator_last() {
1168 let s = "ศไทย中华Việt Nam";
1171 assert_eq!(b.last().unwrap(), 109)
1175 fn test_char_indicesator() {
1176 let s = "ศไทย中华Việt Nam";
1177 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1178 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1181 let it = s.char_indices();
1184 assert_eq!(c, (p[pos], v[pos]));
1187 assert_eq!(pos, v.len());
1188 assert_eq!(pos, p.len());
1192 fn test_char_indices_revator() {
1193 let s = "ศไทย中华Việt Nam";
1194 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1195 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1198 let it = s.char_indices().rev();
1201 assert_eq!(c, (p[pos], v[pos]));
1204 assert_eq!(pos, v.len());
1205 assert_eq!(pos, p.len());
1209 fn test_char_indices_last() {
1210 let s = "ศไทย中华Việt Nam";
1211 let mut it = s.char_indices();
1213 assert_eq!(it.last(), Some((27, 'm')));
1217 fn test_splitn_char_iterator() {
1218 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1220 let split: Vec<&str> = data.splitn(4, ' ').collect();
1221 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1223 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1224 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1227 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1228 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1230 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1231 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1235 fn test_split_char_iterator_no_trailing() {
1236 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1238 let split: Vec<&str> = data.split('\n').collect();
1239 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1241 let split: Vec<&str> = data.split_terminator('\n').collect();
1242 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1247 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1249 let split: Vec<&str> = data.rsplit(' ').collect();
1250 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1252 let split: Vec<&str> = data.rsplit("lämb").collect();
1253 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1255 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1256 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1261 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1263 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1264 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1266 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1267 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1269 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1270 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1274 fn test_split_whitespace() {
1275 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1276 let words: Vec<&str> = data.split_whitespace().collect();
1277 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1282 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1283 let lines: Vec<&str> = data.lines().collect();
1284 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1286 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1287 let lines: Vec<&str> = data.lines().collect();
1288 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1292 fn test_splitator() {
1293 fn t(s: &str, sep: &str, u: &[&str]) {
1294 let v: Vec<&str> = s.split(sep).collect();
1297 t("--1233345--", "12345", &["--1233345--"]);
1298 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1299 t("::hello::there", "::", &["", "hello", "there"]);
1300 t("hello::there::", "::", &["hello", "there", ""]);
1301 t("::hello::there::", "::", &["", "hello", "there", ""]);
1302 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1303 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1304 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1305 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1307 t("zz", "zz", &["",""]);
1308 t("ok", "z", &["ok"]);
1309 t("zzz", "zz", &["","z"]);
1310 t("zzzzz", "zz", &["","","z"]);
1314 fn test_str_default() {
1315 use std::default::Default;
1317 fn t<S: Default + AsRef<str>>() {
1318 let s: S = Default::default();
1319 assert_eq!(s.as_ref(), "");
1328 fn test_str_container() {
1329 fn sum_len(v: &[&str]) -> usize {
1330 v.iter().map(|x| x.len()).sum()
1334 assert_eq!(5, sum_len(&["012", "", "34"]));
1335 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1336 assert_eq!(5, sum_len(&[s]));
1340 fn test_str_from_utf8() {
1342 assert_eq!(from_utf8(xs), Ok("hello"));
1344 let xs = "ศไทย中华Việt Nam".as_bytes();
1345 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1347 let xs = b"hello\xFF";
1348 assert!(from_utf8(xs).is_err());
1352 fn test_pattern_deref_forward() {
1353 let data = "aabcdaa";
1354 assert!(data.contains("bcd"));
1355 assert!(data.contains(&"bcd"));
1356 assert!(data.contains(&"bcd".to_string()));
1360 fn test_empty_match_indices() {
1362 let vec: Vec<_> = data.match_indices("").collect();
1363 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1367 fn test_bool_from_str() {
1368 assert_eq!("true".parse().ok(), Some(true));
1369 assert_eq!("false".parse().ok(), Some(false));
1370 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1373 #[cfg(not(miri))] // Miri is too slow
1374 fn check_contains_all_substrings(s: &str) {
1375 assert!(s.contains(""));
1376 for i in 0..s.len() {
1377 for j in i+1..=s.len() {
1378 assert!(s.contains(&s[i..j]));
1384 #[cfg(not(miri))] // Miri is too slow
1385 fn strslice_issue_16589() {
1386 assert!("bananas".contains("nana"));
1388 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1389 // test all substrings for good measure
1390 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1394 fn strslice_issue_16878() {
1395 assert!(!"1234567ah012345678901ah".contains("hah"));
1396 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1401 #[cfg(not(miri))] // Miri is too slow
1402 fn test_strslice_contains() {
1403 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1404 check_contains_all_substrings(x);
1408 fn test_rsplitn_char_iterator() {
1409 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1411 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1413 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1415 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1417 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1420 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1422 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1424 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1426 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1430 fn test_split_char_iterator() {
1431 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1433 let split: Vec<&str> = data.split(' ').collect();
1434 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1436 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1438 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1440 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1441 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1443 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1445 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1448 let split: Vec<&str> = data.split('ä').collect();
1449 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1451 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1453 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1455 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1456 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1458 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1460 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1464 fn test_rev_split_char_iterator_no_trailing() {
1465 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1467 let mut split: Vec<&str> = data.split('\n').rev().collect();
1469 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1471 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1473 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1477 fn test_utf16_code_units() {
1478 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
1479 [0xE9, 0xD83D, 0xDCA9])
1483 fn starts_with_in_unicode() {
1484 assert!(!"├── Cargo.toml".starts_with("# "));
1488 fn starts_short_long() {
1489 assert!(!"".starts_with("##"));
1490 assert!(!"##".starts_with("####"));
1491 assert!("####".starts_with("##"));
1492 assert!(!"##ä".starts_with("####"));
1493 assert!("####ä".starts_with("##"));
1494 assert!(!"##".starts_with("####ä"));
1495 assert!("##ä##".starts_with("##ä"));
1497 assert!("".starts_with(""));
1498 assert!("ä".starts_with(""));
1499 assert!("#ä".starts_with(""));
1500 assert!("##ä".starts_with(""));
1501 assert!("ä###".starts_with(""));
1502 assert!("#ä##".starts_with(""));
1503 assert!("##ä#".starts_with(""));
1507 fn contains_weird_cases() {
1508 assert!("* \t".contains(' '));
1509 assert!(!"* \t".contains('?'));
1510 assert!(!"* \t".contains('\u{1F4A9}'));
1515 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1517 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1519 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1521 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1523 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
1525 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1527 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1529 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1531 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1533 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
1539 assert_eq!("".to_lowercase(), "");
1540 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1542 // https://github.com/rust-lang/rust/issues/26035
1543 assert_eq!("ΑΣ".to_lowercase(), "ας");
1544 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1545 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1547 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1548 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1549 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1551 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1552 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(), "'σ");
1563 assert_eq!("''Σ".to_lowercase(), "''σ");
1565 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1566 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1567 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1572 assert_eq!("".to_uppercase(), "");
1573 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1577 fn test_into_string() {
1578 // The only way to acquire a Box<str> in the first place is through a String, so just
1579 // test that we can round-trip between Box<str> and String.
1580 let string = String::from("Some text goes here");
1581 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1585 fn test_box_slice_clone() {
1586 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1587 let data2 = data.clone().into_boxed_str().clone().into_string();
1589 assert_eq!(data, data2);
1593 fn test_cow_from() {
1594 let borrowed = "borrowed";
1595 let owned = String::from("owned");
1596 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1597 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1598 _ => panic!("invalid `Cow::from`"),
1604 assert_eq!("".repeat(3), "");
1605 assert_eq!("abc".repeat(0), "");
1606 assert_eq!("α".repeat(3), "ααα");
1610 use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
1611 use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1613 macro_rules! make_test {
1614 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1615 #[allow(unused_imports)]
1617 use std::str::pattern::SearchStep::{Match, Reject};
1618 use super::{cmp_search_to_vec};
1621 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1625 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1631 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1632 right: Vec<SearchStep>)
1633 where P::Searcher: ReverseSearcher<'a>
1635 let mut searcher = pat.into_searcher(haystack);
1638 match if !rev {searcher.next()} else {searcher.next_back()} {
1639 Match(a, b) => v.push(Match(a, b)),
1640 Reject(a, b) => v.push(Reject(a, b)),
1648 let mut first_index = 0;
1651 for (i, e) in right.iter().enumerate() {
1653 Match(a, b) | Reject(a, b)
1654 if a <= b && a == first_index => {
1664 if let Some(err) = err {
1665 panic!("Input skipped range at {}", err);
1668 if first_index != haystack.len() {
1669 panic!("Did not cover whole input");
1672 assert_eq!(v, right);
1675 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1682 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1690 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1707 make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1712 make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1721 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1724 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1726 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1735 make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1740 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1748 macro_rules! generate_iterator_test {
1752 ($($arg:expr),*) -> [$($t:tt)*];
1755 with $fwd:expr, $bwd:expr;
1761 let res = vec![$($t)*];
1763 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1764 assert_eq!(fwd_vec, res);
1766 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1768 assert_eq!(bwd_vec, res);
1776 ($($arg:expr),*) -> [$($t:tt)*];
1785 let res = vec![$($t)*];
1787 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1788 assert_eq!(fwd_vec, res);
1795 generate_iterator_test! {
1796 double_ended_split {
1797 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1798 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1800 with str::split, str::rsplit;
1803 generate_iterator_test! {
1804 double_ended_split_terminator {
1805 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1807 with str::split_terminator, str::rsplit_terminator;
1810 generate_iterator_test! {
1811 double_ended_matches {
1812 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1814 with str::matches, str::rmatches;
1817 generate_iterator_test! {
1818 double_ended_match_indices {
1819 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1821 with str::match_indices, str::rmatch_indices;
1824 generate_iterator_test! {
1825 not_double_ended_splitn {
1826 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1831 generate_iterator_test! {
1832 not_double_ended_rsplitn {
1833 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1839 fn different_str_pattern_forwarding_lifetimes() {
1840 use std::str::pattern::Pattern;
1842 fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {