1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 use std::cmp::Ordering::{Equal, Greater, Less};
13 use std::str::from_utf8;
19 assert!("foo" <= "foo");
20 assert!("foo" != "bar");
25 assert_eq!("hello".find('l'), Some(2));
26 assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
27 assert!("hello".find('x').is_none());
28 assert!("hello".find(|c:char| c == 'x').is_none());
29 assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
30 assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
35 assert_eq!("hello".rfind('l'), Some(3));
36 assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
37 assert!("hello".rfind('x').is_none());
38 assert!("hello".rfind(|c:char| c == 'x').is_none());
39 assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
40 assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
46 let s: String = empty.chars().collect();
48 let data = "ประเทศไทย中";
49 let s: String = data.chars().collect();
54 fn test_into_bytes() {
55 let data = String::from("asdf");
56 let buf = data.into_bytes();
57 assert_eq!(buf, b"asdf");
63 assert_eq!("".find(""), Some(0));
64 assert!("banana".find("apple pie").is_none());
67 assert_eq!(data[0..6].find("ab"), Some(0));
68 assert_eq!(data[2..6].find("ab"), Some(3 - 2));
69 assert!(data[2..4].find("ab").is_none());
71 let string = "ประเทศไทย中华Việt Nam";
72 let mut data = String::from(string);
73 data.push_str(string);
74 assert!(data.find("ไท华").is_none());
75 assert_eq!(data[0..43].find(""), Some(0));
76 assert_eq!(data[6..43].find(""), Some(6 - 6));
78 assert_eq!(data[0..43].find("ประ"), Some( 0));
79 assert_eq!(data[0..43].find("ทศไ"), Some(12));
80 assert_eq!(data[0..43].find("ย中"), Some(24));
81 assert_eq!(data[0..43].find("iệt"), Some(34));
82 assert_eq!(data[0..43].find("Nam"), Some(40));
84 assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
85 assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
86 assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
87 assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
88 assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
90 // find every substring -- assert that it finds it, or an earlier occurrence.
91 let string = "Việt Namacbaabcaabaaba";
92 for (i, ci) in string.char_indices() {
93 let ip = i + ci.len_utf8();
94 for j in string[ip..].char_indices()
96 .chain(Some(string.len() - ip))
98 let pat = &string[i..ip + j];
99 assert!(match string.find(pat) {
103 assert!(match string.rfind(pat) {
111 fn s(x: &str) -> String { x.to_string() }
113 macro_rules! test_concat {
114 ($expected: expr, $string: expr) => {
116 let s: String = $string.concat();
117 assert_eq!($expected, s);
123 fn test_concat_for_different_types() {
124 test_concat!("ab", vec![s("a"), s("b")]);
125 test_concat!("ab", vec!["a", "b"]);
129 fn test_concat_for_different_lengths() {
130 let empty: &[&str] = &[];
131 test_concat!("", empty);
132 test_concat!("a", ["a"]);
133 test_concat!("ab", ["a", "b"]);
134 test_concat!("abc", ["", "a", "bc"]);
137 macro_rules! test_join {
138 ($expected: expr, $string: expr, $delim: expr) => {
140 let s = $string.join($delim);
141 assert_eq!($expected, s);
147 fn test_join_for_different_types() {
148 test_join!("a-b", ["a", "b"], "-");
149 let hyphen = "-".to_string();
150 test_join!("a-b", [s("a"), s("b")], &*hyphen);
151 test_join!("a-b", vec!["a", "b"], &*hyphen);
152 test_join!("a-b", &*vec!["a", "b"], "-");
153 test_join!("a-b", vec![s("a"), s("b")], "-");
157 fn test_join_for_different_lengths() {
158 let empty: &[&str] = &[];
159 test_join!("", empty, "-");
160 test_join!("a", ["a"], "-");
161 test_join!("a-b", ["a", "b"], "-");
162 test_join!("-a-bc", ["", "a", "bc"], "-");
165 // join has fast paths for small separators up to 4 bytes
166 // this tests the slow paths.
168 fn test_join_for_different_lengths_with_long_separator() {
169 assert_eq!("~~~~~".len(), 15);
171 let empty: &[&str] = &[];
172 test_join!("", empty, "~~~~~");
173 test_join!("a", ["a"], "~~~~~");
174 test_join!("a~~~~~b", ["a", "b"], "~~~~~");
175 test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
179 fn test_unsafe_slice() {
180 assert_eq!("ab", unsafe {"abc".get_unchecked(0..2)});
181 assert_eq!("bc", unsafe {"abc".get_unchecked(1..3)});
182 assert_eq!("", unsafe {"abc".get_unchecked(1..1)});
183 fn a_million_letter_a() -> String {
185 let mut rs = String::new();
187 rs.push_str("aaaaaaaaaa");
192 fn half_a_million_letter_a() -> String {
194 let mut rs = String::new();
196 rs.push_str("aaaaa");
201 let letters = a_million_letter_a();
202 assert_eq!(half_a_million_letter_a(),
203 unsafe { letters.get_unchecked(0..500000)});
207 fn test_starts_with() {
208 assert!("".starts_with(""));
209 assert!("abc".starts_with(""));
210 assert!("abc".starts_with("a"));
211 assert!(!"a".starts_with("abc"));
212 assert!(!"".starts_with("abc"));
213 assert!(!"ödd".starts_with("-"));
214 assert!("ödd".starts_with("öd"));
218 fn test_ends_with() {
219 assert!("".ends_with(""));
220 assert!("abc".ends_with(""));
221 assert!("abc".ends_with("c"));
222 assert!(!"a".ends_with("abc"));
223 assert!(!"".ends_with("abc"));
224 assert!(!"ddö".ends_with("-"));
225 assert!("ddö".ends_with("dö"));
230 assert!("".is_empty());
231 assert!(!"a".is_empty());
236 assert_eq!("".replacen('a', "b", 5), "");
237 assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
238 assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
241 assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
242 assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
243 assert_eq!(" test test ".replacen(test, "", 5), " ");
245 assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
251 assert_eq!("".replace(a, "b"), "");
252 assert_eq!("a".replace(a, "b"), "b");
253 assert_eq!("ab".replace(a, "b"), "bb");
255 assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
256 assert_eq!(" test test ".replace(test, ""), " ");
260 fn test_replace_2a() {
261 let data = "ประเทศไทย中华";
262 let repl = "دولة الكويت";
265 let a2 = "دولة الكويتทศไทย中华";
266 assert_eq!(data.replace(a, repl), a2);
270 fn test_replace_2b() {
271 let data = "ประเทศไทย中华";
272 let repl = "دولة الكويت";
275 let b2 = "ปรدولة الكويتทศไทย中华";
276 assert_eq!(data.replace(b, repl), b2);
280 fn test_replace_2c() {
281 let data = "ประเทศไทย中华";
282 let repl = "دولة الكويت";
285 let c2 = "ประเทศไทยدولة الكويت";
286 assert_eq!(data.replace(c, repl), c2);
290 fn test_replace_2d() {
291 let data = "ประเทศไทย中华";
292 let repl = "دولة الكويت";
295 assert_eq!(data.replace(d, repl), data);
299 fn test_replace_pattern() {
300 let data = "abcdαβγδabcdαβγδ";
301 assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
302 assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
303 assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
304 assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
307 // The current implementation of SliceIndex fails to handle methods
308 // orthogonally from range types; therefore, it is worth testing
309 // all of the indexing operations on each input.
311 // Test a slicing operation **that should succeed,**
312 // testing it on all of the indexing methods.
314 // This is not suitable for testing failure on invalid inputs.
315 macro_rules! assert_range_eq {
316 ($s:expr, $range:expr, $expected:expr)
318 let mut s: String = $s.to_owned();
319 let mut expected: String = $expected.to_owned();
322 let expected: &str = &expected;
324 assert_eq!(&s[$range], expected, "(in assertion for: index)");
325 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
328 s.get_unchecked($range), expected,
329 "(in assertion for: get_unchecked)",
334 let s: &mut str = &mut s;
335 let expected: &mut str = &mut expected;
338 &mut s[$range], expected,
339 "(in assertion for: index_mut)",
342 s.get_mut($range), Some(&mut expected[..]),
343 "(in assertion for: get_mut)",
347 s.get_unchecked_mut($range), expected,
348 "(in assertion for: get_unchecked_mut)",
355 // Make sure the macro can actually detect bugs,
356 // because if it can't, then what are we even doing here?
358 // (Be aware this only demonstrates the ability to detect bugs
359 // in the FIRST method that panics, as the macro is not designed
360 // to be used in `should_panic`)
362 #[should_panic(expected = "out of bounds")]
363 fn assert_range_eq_can_fail_by_panic() {
364 assert_range_eq!("abc", 0..5, "abc");
367 // (Be aware this only demonstrates the ability to detect bugs
368 // in the FIRST method it calls, as the macro is not designed
369 // to be used in `should_panic`)
371 #[should_panic(expected = "==")]
372 fn assert_range_eq_can_fail_by_inequality() {
373 assert_range_eq!("abc", 0..2, "abc");
376 // Generates test cases for bad index operations.
378 // This generates `should_panic` test cases for Index/IndexMut
379 // and `None` test cases for get/get_mut.
380 macro_rules! panic_cases {
382 in mod $case_name:ident {
387 // a similar input for which DATA[input] succeeds, and the corresponding
388 // output str. This helps validate "critical points" where an input range
389 // straddles the boundary between valid and invalid.
390 // (such as the input `len..len`, which is just barely valid)
392 good: data[$good:expr] == $output:expr;
395 bad: data[$bad:expr];
396 message: $expect_msg:expr; // must be a literal
402 let mut v: String = $data.into();
404 $( assert_range_eq!(v, $good, $output); )*
408 assert_eq!(v.get($bad), None, "(in None assertion for get)");
412 let v: &mut str = &mut v;
413 assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
418 #[should_panic(expected = $expect_msg)]
420 let v: String = $data.into();
426 #[should_panic(expected = $expect_msg)]
427 fn index_mut_fail() {
428 let mut v: String = $data.into();
429 let v: &mut str = &mut v;
430 let _v = &mut v[$bad];
438 assert_range_eq!("abc", .., "abc");
440 assert_range_eq!("abc", 0..2, "ab");
441 assert_range_eq!("abc", 0..=1, "ab");
442 assert_range_eq!("abc", ..2, "ab");
443 assert_range_eq!("abc", ..=1, "ab");
445 assert_range_eq!("abc", 1..3, "bc");
446 assert_range_eq!("abc", 1..=2, "bc");
447 assert_range_eq!("abc", 1..1, "");
448 assert_range_eq!("abc", 1..=0, "");
452 fn simple_unicode() {
454 assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
456 assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
457 assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
458 assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
459 assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
461 assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
462 assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
463 assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
465 let data = "ประเทศไทย中华";
466 assert_range_eq!(data, 0..3, "ป");
467 assert_range_eq!(data, 3..6, "ร");
468 assert_range_eq!(data, 3..3, "");
469 assert_range_eq!(data, 30..33, "华");
481 let ss = "中华Việt Nam";
482 assert_range_eq!(ss, 3..6, "华");
483 assert_range_eq!(ss, 6..16, "Việt Nam");
484 assert_range_eq!(ss, 6..=15, "Việt Nam");
485 assert_range_eq!(ss, 6.., "Việt Nam");
487 assert_range_eq!(ss, 0..3, "中");
488 assert_range_eq!(ss, 3..7, "华V");
489 assert_range_eq!(ss, 3..=6, "华V");
490 assert_range_eq!(ss, 3..3, "");
491 assert_range_eq!(ss, 3..=2, "");
495 #[cfg(not(target_arch = "asmjs"))] // hits an OOM
497 fn a_million_letter_x() -> String {
499 let mut rs = String::new();
501 rs.push_str("华华华华华华华华华华");
506 fn half_a_million_letter_x() -> String {
508 let mut rs = String::new();
510 rs.push_str("华华华华华");
515 let letters = a_million_letter_x();
516 assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
521 fn test_slice_fail() {
526 in mod rangefrom_len {
528 good: data[6..] == "";
530 message: "out of bounds";
535 good: data[..6] == "abcdef";
537 message: "out of bounds";
540 in mod rangetoinclusive_len {
542 good: data[..=5] == "abcdef";
544 message: "out of bounds";
547 in mod range_len_len {
549 good: data[6..6] == "";
551 message: "out of bounds";
554 in mod rangeinclusive_len_len {
556 good: data[6..=5] == "";
558 message: "out of bounds";
563 in mod range_neg_width {
565 good: data[4..4] == "";
567 message: "begin <= end (4 <= 3)";
570 in mod rangeinclusive_neg_width {
572 good: data[4..=3] == "";
574 message: "begin <= end (4 <= 3)";
580 in mod rangeinclusive {
582 // note: using 0 specifically ensures that the result of overflowing is 0..0,
583 // so that `get` doesn't simply return None for the wrong reason.
584 bad: data[0..=usize::max_value()];
585 message: "maximum usize";
588 in mod rangetoinclusive {
590 bad: data[..=usize::max_value()];
591 message: "maximum usize";
597 const DATA: &'static str = "abcαβγ";
599 const BAD_START: usize = 4;
600 const GOOD_START: usize = 3;
601 const BAD_END: usize = 6;
602 const GOOD_END: usize = 7;
603 const BAD_END_INCL: usize = BAD_END - 1;
604 const GOOD_END_INCL: usize = GOOD_END - 1;
606 // it is especially important to test all of the different range types here
607 // because some of the logic may be duplicated as part of micro-optimizations
608 // to dodge unicode boundary checks on half-ranges.
612 bad: data[super::BAD_START..super::GOOD_END];
614 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
619 bad: data[super::GOOD_START..super::BAD_END];
621 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
626 bad: data[super::BAD_START..];
628 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
633 bad: data[..super::BAD_END];
635 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
638 in mod rangeinclusive_1 {
640 bad: data[super::BAD_START..=super::GOOD_END_INCL];
642 "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
645 in mod rangeinclusive_2 {
647 bad: data[super::GOOD_START..=super::BAD_END_INCL];
649 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
652 in mod rangetoinclusive {
654 bad: data[..=super::BAD_END_INCL];
656 "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
661 const LOREM_PARAGRAPH: &'static str = "\
662 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \
663 sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \
664 quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \
665 nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \
666 tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \
669 // check the panic includes the prefix of the sliced string
671 #[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
672 fn test_slice_fail_truncated_1() {
673 &LOREM_PARAGRAPH[..1024];
675 // check the truncation in the panic message
677 #[should_panic(expected="luctus, im`[...]")]
678 fn test_slice_fail_truncated_2() {
679 &LOREM_PARAGRAPH[..1024];
684 fn test_str_slice_rangetoinclusive_ok() {
686 assert_eq!(&s[..=2], "abc");
687 assert_eq!(&s[..=4], "abcα");
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 fn test_str_slicemut_rangetoinclusive_notok() {
708 let mut s = "abcαβγ".to_owned();
709 let s: &mut str = &mut s;
714 fn test_is_char_boundary() {
715 let s = "ศไทย中华Việt Nam β-release 🐱123";
716 assert!(s.is_char_boundary(0));
717 assert!(s.is_char_boundary(s.len()));
718 assert!(!s.is_char_boundary(s.len() + 1));
719 for (i, ch) in s.char_indices() {
720 // ensure character locations are boundaries and continuation bytes are not
721 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
722 for j in 1..ch.len_utf8() {
723 assert!(!s.is_char_boundary(i + j),
724 "{} should not be a char boundary in {:?}", i + j, s);
730 fn test_trim_start_matches() {
731 let v: &[char] = &[];
732 assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
733 let chars: &[char] = &['*', ' '];
734 assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
735 assert_eq!(" *** *** ".trim_start_matches(chars), "");
736 assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
738 assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
739 let chars: &[char] = &['1', '2'];
740 assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
741 assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
745 fn test_trim_end_matches() {
746 let v: &[char] = &[];
747 assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
748 let chars: &[char] = &['*', ' '];
749 assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
750 assert_eq!(" *** *** ".trim_end_matches(chars), "");
751 assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
753 assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
754 let chars: &[char] = &['1', '2'];
755 assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
756 assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
760 fn test_trim_matches() {
761 let v: &[char] = &[];
762 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
763 let chars: &[char] = &['*', ' '];
764 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
765 assert_eq!(" *** *** ".trim_matches(chars), "");
766 assert_eq!("foo".trim_matches(chars), "foo");
768 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
769 let chars: &[char] = &['1', '2'];
770 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
771 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
775 fn test_trim_start() {
776 assert_eq!("".trim_start(), "");
777 assert_eq!("a".trim_start(), "a");
778 assert_eq!(" ".trim_start(), "");
779 assert_eq!(" blah".trim_start(), "blah");
780 assert_eq!(" \u{3000} wut".trim_start(), "wut");
781 assert_eq!("hey ".trim_start(), "hey ");
786 assert_eq!("".trim_end(), "");
787 assert_eq!("a".trim_end(), "a");
788 assert_eq!(" ".trim_end(), "");
789 assert_eq!("blah ".trim_end(), "blah");
790 assert_eq!("wut \u{3000} ".trim_end(), "wut");
791 assert_eq!(" hey".trim_end(), " hey");
796 assert_eq!("".trim(), "");
797 assert_eq!("a".trim(), "a");
798 assert_eq!(" ".trim(), "");
799 assert_eq!(" blah ".trim(), "blah");
800 assert_eq!("\nwut \u{3000} ".trim(), "wut");
801 assert_eq!(" hey dude ".trim(), "hey dude");
805 fn test_is_whitespace() {
806 assert!("".chars().all(|c| c.is_whitespace()));
807 assert!(" ".chars().all(|c| c.is_whitespace()));
808 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
809 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
810 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
815 // deny overlong encodings
816 assert!(from_utf8(&[0xc0, 0x80]).is_err());
817 assert!(from_utf8(&[0xc0, 0xae]).is_err());
818 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
819 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
820 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
821 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
822 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
825 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
826 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
828 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
829 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
830 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
831 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
832 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
833 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
834 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
835 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
839 fn from_utf8_mostly_ascii() {
840 // deny invalid bytes embedded in long stretches of ascii
842 let mut data = [0; 128];
844 assert!(from_utf8(&data).is_err());
846 assert!(from_utf8(&data).is_err());
851 fn from_utf8_error() {
853 ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
854 let error = from_utf8($input).unwrap_err();
855 assert_eq!(error.valid_up_to(), $expected_valid_up_to);
856 assert_eq!(error.error_len(), $expected_error_len);
859 test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
860 test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
861 test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
862 test!(b"A\xC3\xA9 \xC1", 4, Some(1));
863 test!(b"A\xC3\xA9 \xC2", 4, None);
864 test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
865 test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
866 test!(b"A\xC3\xA9 \xE0", 4, None);
867 test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
868 test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
869 test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
870 test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
871 test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
872 test!(b"A\xC3\xA9 \xF1", 4, None);
873 test!(b"A\xC3\xA9 \xF1\x80", 4, None);
874 test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
875 test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
876 test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
877 test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
884 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
885 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
889 assert_eq!("".as_bytes(), b);
890 assert_eq!("abc".as_bytes(), b"abc");
891 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
896 fn test_as_bytes_fail() {
897 // Don't double free. (I'm not sure if this exercises the
898 // original problem code path anymore.)
899 let s = String::from("");
900 let _bytes = s.as_bytes();
906 let buf = "hello".as_ptr();
908 assert_eq!(*buf.offset(0), b'h');
909 assert_eq!(*buf.offset(1), b'e');
910 assert_eq!(*buf.offset(2), b'l');
911 assert_eq!(*buf.offset(3), b'l');
912 assert_eq!(*buf.offset(4), b'o');
917 fn vec_str_conversions() {
918 let s1: String = String::from("All mimsy were the borogoves");
920 let v: Vec<u8> = s1.as_bytes().to_vec();
921 let s2: String = String::from(from_utf8(&v).unwrap());
927 let a: u8 = s1.as_bytes()[i];
928 let b: u8 = s2.as_bytes()[i];
936 assert!("abcde".contains("bcd"));
937 assert!("abcde".contains("abcd"));
938 assert!("abcde".contains("bcde"));
939 assert!("abcde".contains(""));
940 assert!("".contains(""));
941 assert!(!"abcde".contains("def"));
942 assert!(!"".contains("a"));
944 let data = "ประเทศไทย中华Việt Nam";
945 assert!(data.contains("ประเ"));
946 assert!(data.contains("ะเ"));
947 assert!(data.contains("中华"));
948 assert!(!data.contains("ไท华"));
952 fn test_contains_char() {
953 assert!("abc".contains('b'));
954 assert!("a".contains('a'));
955 assert!(!"abc".contains('d'));
956 assert!(!"".contains('a'));
961 let s = "ศไทย中华Việt Nam";
962 for (index, _) in s.char_indices() {
963 let (a, b) = s.split_at(index);
964 assert_eq!(&s[..a.len()], a);
965 assert_eq!(&s[a.len()..], b);
967 let (a, b) = s.split_at(s.len());
973 fn test_split_at_mut() {
974 let mut s = "Hello World".to_string();
976 let (a, b) = s.split_at_mut(5);
977 a.make_ascii_uppercase();
978 b.make_ascii_lowercase();
980 assert_eq!(s, "HELLO world");
985 fn test_split_at_boundscheck() {
986 let s = "ศไทย中华Việt Nam";
991 fn test_escape_unicode() {
992 assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
993 assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
994 assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
995 assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
996 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
997 assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
998 assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
999 assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
1000 assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
1004 fn test_escape_debug() {
1005 // Note that there are subtleties with the number of backslashes
1006 // on the left- and right-hand sides. In particular, Unicode code points
1007 // are usually escaped with two backslashes on the right-hand side, as
1008 // they are escaped. However, when the character is unescaped (e.g., for
1009 // printable characters), only a single backslash appears (as the character
1010 // itself appears in the debug string).
1011 assert_eq!("abc".escape_debug(), "abc");
1012 assert_eq!("a c".escape_debug(), "a c");
1013 assert_eq!("éèê".escape_debug(), "éèê");
1014 assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
1015 assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
1016 assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
1017 assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
1018 assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
1019 assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
1020 assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
1021 assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug(), "\\u{301}a\u{301}bé\\u{e000}");
1025 fn test_escape_default() {
1026 assert_eq!("abc".escape_default(), "abc");
1027 assert_eq!("a c".escape_default(), "a c");
1028 assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
1029 assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
1030 assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
1031 assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
1032 assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
1033 assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
1034 assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
1035 assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
1039 fn test_total_ord() {
1040 assert_eq!("1234".cmp("123"), Greater);
1041 assert_eq!("123".cmp("1234"), Less);
1042 assert_eq!("1234".cmp("1234"), Equal);
1043 assert_eq!("12345555".cmp("123456"), Less);
1044 assert_eq!("22".cmp("1234"), Greater);
1048 fn test_iterator() {
1049 let s = "ศไทย中华Việt Nam";
1050 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1056 assert_eq!(c, v[pos]);
1059 assert_eq!(pos, v.len());
1060 assert_eq!(s.chars().count(), v.len());
1064 fn test_rev_iterator() {
1065 let s = "ศไทย中华Việt Nam";
1066 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1069 let it = s.chars().rev();
1072 assert_eq!(c, v[pos]);
1075 assert_eq!(pos, v.len());
1079 fn test_chars_decoding() {
1080 let mut bytes = [0; 4];
1081 for c in (0..0x110000).filter_map(::std::char::from_u32) {
1082 let s = c.encode_utf8(&mut bytes);
1083 if Some(c) != s.chars().next() {
1084 panic!("character {:x}={} does not decode correctly", c as u32, c);
1090 fn test_chars_rev_decoding() {
1091 let mut bytes = [0; 4];
1092 for c in (0..0x110000).filter_map(::std::char::from_u32) {
1093 let s = c.encode_utf8(&mut bytes);
1094 if Some(c) != s.chars().rev().next() {
1095 panic!("character {:x}={} does not decode correctly", c as u32, c);
1101 fn test_iterator_clone() {
1102 let s = "ศไทย中华Việt Nam";
1103 let mut it = s.chars();
1105 assert!(it.clone().zip(it).all(|(x,y)| x == y));
1109 fn test_iterator_last() {
1110 let s = "ศไทย中华Việt Nam";
1111 let mut it = s.chars();
1113 assert_eq!(it.last(), Some('m'));
1117 fn test_bytesator() {
1118 let s = "ศไทย中华Việt Nam";
1120 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1121 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1126 for b in s.bytes() {
1127 assert_eq!(b, v[pos]);
1133 fn test_bytes_revator() {
1134 let s = "ศไทย中华Việt Nam";
1136 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1137 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1140 let mut pos = v.len();
1142 for b in s.bytes().rev() {
1144 assert_eq!(b, v[pos]);
1149 fn test_bytesator_nth() {
1150 let s = "ศไทย中华Việt Nam";
1152 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1153 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1157 let mut b = s.bytes();
1158 assert_eq!(b.nth(2).unwrap(), v[2]);
1159 assert_eq!(b.nth(10).unwrap(), v[10]);
1160 assert_eq!(b.nth(200), None);
1164 fn test_bytesator_count() {
1165 let s = "ศไทย中华Việt Nam";
1168 assert_eq!(b.count(), 28)
1172 fn test_bytesator_last() {
1173 let s = "ศไทย中华Việt Nam";
1176 assert_eq!(b.last().unwrap(), 109)
1180 fn test_char_indicesator() {
1181 let s = "ศไทย中华Việt Nam";
1182 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1183 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1186 let it = s.char_indices();
1189 assert_eq!(c, (p[pos], v[pos]));
1192 assert_eq!(pos, v.len());
1193 assert_eq!(pos, p.len());
1197 fn test_char_indices_revator() {
1198 let s = "ศไทย中华Việt Nam";
1199 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1200 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1203 let it = s.char_indices().rev();
1206 assert_eq!(c, (p[pos], v[pos]));
1209 assert_eq!(pos, v.len());
1210 assert_eq!(pos, p.len());
1214 fn test_char_indices_last() {
1215 let s = "ศไทย中华Việt Nam";
1216 let mut it = s.char_indices();
1218 assert_eq!(it.last(), Some((27, 'm')));
1222 fn test_splitn_char_iterator() {
1223 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1225 let split: Vec<&str> = data.splitn(4, ' ').collect();
1226 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1228 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1229 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1232 let split: Vec<&str> = data.splitn(4, 'ä').collect();
1233 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1235 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1236 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1240 fn test_split_char_iterator_no_trailing() {
1241 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1243 let split: Vec<&str> = data.split('\n').collect();
1244 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1246 let split: Vec<&str> = data.split_terminator('\n').collect();
1247 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1252 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1254 let split: Vec<&str> = data.rsplit(' ').collect();
1255 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1257 let split: Vec<&str> = data.rsplit("lämb").collect();
1258 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1260 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1261 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1266 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1268 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1269 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1271 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1272 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1274 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1275 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1279 fn test_split_whitespace() {
1280 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1281 let words: Vec<&str> = data.split_whitespace().collect();
1282 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1287 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1288 let lines: Vec<&str> = data.lines().collect();
1289 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1291 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1292 let lines: Vec<&str> = data.lines().collect();
1293 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1297 fn test_splitator() {
1298 fn t(s: &str, sep: &str, u: &[&str]) {
1299 let v: Vec<&str> = s.split(sep).collect();
1302 t("--1233345--", "12345", &["--1233345--"]);
1303 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1304 t("::hello::there", "::", &["", "hello", "there"]);
1305 t("hello::there::", "::", &["hello", "there", ""]);
1306 t("::hello::there::", "::", &["", "hello", "there", ""]);
1307 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1308 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1309 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1310 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1312 t("zz", "zz", &["",""]);
1313 t("ok", "z", &["ok"]);
1314 t("zzz", "zz", &["","z"]);
1315 t("zzzzz", "zz", &["","","z"]);
1319 fn test_str_default() {
1320 use std::default::Default;
1322 fn t<S: Default + AsRef<str>>() {
1323 let s: S = Default::default();
1324 assert_eq!(s.as_ref(), "");
1333 fn test_str_container() {
1334 fn sum_len(v: &[&str]) -> usize {
1335 v.iter().map(|x| x.len()).sum()
1339 assert_eq!(5, sum_len(&["012", "", "34"]));
1340 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1341 assert_eq!(5, sum_len(&[s]));
1345 fn test_str_from_utf8() {
1347 assert_eq!(from_utf8(xs), Ok("hello"));
1349 let xs = "ศไทย中华Việt Nam".as_bytes();
1350 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1352 let xs = b"hello\xFF";
1353 assert!(from_utf8(xs).is_err());
1357 fn test_pattern_deref_forward() {
1358 let data = "aabcdaa";
1359 assert!(data.contains("bcd"));
1360 assert!(data.contains(&"bcd"));
1361 assert!(data.contains(&"bcd".to_string()));
1365 fn test_empty_match_indices() {
1367 let vec: Vec<_> = data.match_indices("").collect();
1368 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1372 fn test_bool_from_str() {
1373 assert_eq!("true".parse().ok(), Some(true));
1374 assert_eq!("false".parse().ok(), Some(false));
1375 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1378 fn check_contains_all_substrings(s: &str) {
1379 assert!(s.contains(""));
1380 for i in 0..s.len() {
1381 for j in i+1..=s.len() {
1382 assert!(s.contains(&s[i..j]));
1388 fn strslice_issue_16589() {
1389 assert!("bananas".contains("nana"));
1391 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1392 // test all substrings for good measure
1393 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1397 fn strslice_issue_16878() {
1398 assert!(!"1234567ah012345678901ah".contains("hah"));
1399 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1404 fn test_strslice_contains() {
1405 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1406 check_contains_all_substrings(x);
1410 fn test_rsplitn_char_iterator() {
1411 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1413 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1415 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1417 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1419 assert_eq!(split, ["\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"]);
1432 fn test_split_char_iterator() {
1433 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1435 let split: Vec<&str> = data.split(' ').collect();
1436 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1438 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1440 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1442 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1443 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1445 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1447 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1450 let split: Vec<&str> = data.split('ä').collect();
1451 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1453 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1455 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1457 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1458 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1460 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1462 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1466 fn test_rev_split_char_iterator_no_trailing() {
1467 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1469 let mut split: Vec<&str> = data.split('\n').rev().collect();
1471 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1473 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1475 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1479 fn test_utf16_code_units() {
1480 assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
1481 [0xE9, 0xD83D, 0xDCA9])
1485 fn starts_with_in_unicode() {
1486 assert!(!"├── Cargo.toml".starts_with("# "));
1490 fn starts_short_long() {
1491 assert!(!"".starts_with("##"));
1492 assert!(!"##".starts_with("####"));
1493 assert!("####".starts_with("##"));
1494 assert!(!"##ä".starts_with("####"));
1495 assert!("####ä".starts_with("##"));
1496 assert!(!"##".starts_with("####ä"));
1497 assert!("##ä##".starts_with("##ä"));
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(""));
1509 fn contains_weird_cases() {
1510 assert!("* \t".contains(' '));
1511 assert!(!"* \t".contains('?'));
1512 assert!(!"* \t".contains('\u{1F4A9}'));
1517 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1519 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1521 assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()),
1523 assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()),
1525 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
1527 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1529 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1531 assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()),
1533 assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()),
1535 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
1541 assert_eq!("".to_lowercase(), "");
1542 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1544 // https://github.com/rust-lang/rust/issues/26035
1545 assert_eq!("ΑΣ".to_lowercase(), "ας");
1546 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1547 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1549 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1550 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1551 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1553 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1554 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1556 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1557 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1559 assert_eq!("Α Σ".to_lowercase(), "α σ");
1560 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1561 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1563 assert_eq!("Σ".to_lowercase(), "σ");
1564 assert_eq!("'Σ".to_lowercase(), "'σ");
1565 assert_eq!("''Σ".to_lowercase(), "''σ");
1567 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1568 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1569 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1574 assert_eq!("".to_uppercase(), "");
1575 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1579 fn test_into_string() {
1580 // The only way to acquire a Box<str> in the first place is through a String, so just
1581 // test that we can round-trip between Box<str> and String.
1582 let string = String::from("Some text goes here");
1583 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1587 fn test_box_slice_clone() {
1588 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1589 let data2 = data.clone().into_boxed_str().clone().into_string();
1591 assert_eq!(data, data2);
1595 fn test_cow_from() {
1596 let borrowed = "borrowed";
1597 let owned = String::from("owned");
1598 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1599 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1600 _ => panic!("invalid `Cow::from`"),
1606 assert_eq!("".repeat(3), "");
1607 assert_eq!("abc".repeat(0), "");
1608 assert_eq!("α".repeat(3), "ααα");
1612 use std::str::pattern::Pattern;
1613 use std::str::pattern::{Searcher, ReverseSearcher};
1614 use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1616 macro_rules! make_test {
1617 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1618 #[allow(unused_imports)]
1620 use std::str::pattern::SearchStep::{Match, Reject};
1621 use super::{cmp_search_to_vec};
1624 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1628 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1634 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1635 right: Vec<SearchStep>)
1636 where P::Searcher: ReverseSearcher<'a>
1638 let mut searcher = pat.into_searcher(haystack);
1641 match if !rev {searcher.next()} else {searcher.next_back()} {
1642 Match(a, b) => v.push(Match(a, b)),
1643 Reject(a, b) => v.push(Reject(a, b)),
1651 let mut first_index = 0;
1654 for (i, e) in right.iter().enumerate() {
1656 Match(a, b) | Reject(a, b)
1657 if a <= b && a == first_index => {
1667 if let Some(err) = err {
1668 panic!("Input skipped range at {}", err);
1671 if first_index != haystack.len() {
1672 panic!("Did not cover whole input");
1675 assert_eq!(v, right);
1678 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1685 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1693 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1710 make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1715 make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1724 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1727 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1729 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1738 make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1743 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1751 macro_rules! generate_iterator_test {
1755 ($($arg:expr),*) -> [$($t:tt)*];
1758 with $fwd:expr, $bwd:expr;
1764 let res = vec![$($t)*];
1766 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1767 assert_eq!(fwd_vec, res);
1769 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1771 assert_eq!(bwd_vec, res);
1779 ($($arg:expr),*) -> [$($t:tt)*];
1788 let res = vec![$($t)*];
1790 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1791 assert_eq!(fwd_vec, res);
1798 generate_iterator_test! {
1799 double_ended_split {
1800 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1801 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1803 with str::split, str::rsplit;
1806 generate_iterator_test! {
1807 double_ended_split_terminator {
1808 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1810 with str::split_terminator, str::rsplit_terminator;
1813 generate_iterator_test! {
1814 double_ended_matches {
1815 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1817 with str::matches, str::rmatches;
1820 generate_iterator_test! {
1821 double_ended_match_indices {
1822 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1824 with str::match_indices, str::rmatch_indices;
1827 generate_iterator_test! {
1828 not_double_ended_splitn {
1829 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1834 generate_iterator_test! {
1835 not_double_ended_rsplitn {
1836 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1842 fn different_str_pattern_forwarding_lifetimes() {
1843 use std::str::pattern::Pattern;
1845 fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {