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"], "-");
166 fn test_unsafe_slice() {
167 assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)});
168 assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)});
169 assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)});
170 fn a_million_letter_a() -> String {
172 let mut rs = String::new();
174 rs.push_str("aaaaaaaaaa");
179 fn half_a_million_letter_a() -> String {
181 let mut rs = String::new();
183 rs.push_str("aaaaa");
188 let letters = a_million_letter_a();
189 assert_eq!(half_a_million_letter_a(),
190 unsafe { letters.slice_unchecked(0, 500000)});
194 fn test_starts_with() {
195 assert!("".starts_with(""));
196 assert!("abc".starts_with(""));
197 assert!("abc".starts_with("a"));
198 assert!(!"a".starts_with("abc"));
199 assert!(!"".starts_with("abc"));
200 assert!(!"ödd".starts_with("-"));
201 assert!("ödd".starts_with("öd"));
205 fn test_ends_with() {
206 assert!("".ends_with(""));
207 assert!("abc".ends_with(""));
208 assert!("abc".ends_with("c"));
209 assert!(!"a".ends_with("abc"));
210 assert!(!"".ends_with("abc"));
211 assert!(!"ddö".ends_with("-"));
212 assert!("ddö".ends_with("dö"));
217 assert!("".is_empty());
218 assert!(!"a".is_empty());
223 assert_eq!("".replacen('a', "b", 5), "");
224 assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
225 assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
228 assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
229 assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
230 assert_eq!(" test test ".replacen(test, "", 5), " ");
232 assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
238 assert_eq!("".replace(a, "b"), "");
239 assert_eq!("a".replace(a, "b"), "b");
240 assert_eq!("ab".replace(a, "b"), "bb");
242 assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
243 assert_eq!(" test test ".replace(test, ""), " ");
247 fn test_replace_2a() {
248 let data = "ประเทศไทย中华";
249 let repl = "دولة الكويت";
252 let a2 = "دولة الكويتทศไทย中华";
253 assert_eq!(data.replace(a, repl), a2);
257 fn test_replace_2b() {
258 let data = "ประเทศไทย中华";
259 let repl = "دولة الكويت";
262 let b2 = "ปรدولة الكويتทศไทย中华";
263 assert_eq!(data.replace(b, repl), b2);
267 fn test_replace_2c() {
268 let data = "ประเทศไทย中华";
269 let repl = "دولة الكويت";
272 let c2 = "ประเทศไทยدولة الكويت";
273 assert_eq!(data.replace(c, repl), c2);
277 fn test_replace_2d() {
278 let data = "ประเทศไทย中华";
279 let repl = "دولة الكويت";
282 assert_eq!(data.replace(d, repl), data);
286 fn test_replace_pattern() {
287 let data = "abcdαβγδabcdαβγδ";
288 assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
289 assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
290 assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
291 assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
296 assert_eq!("ab", &"abc"[0..2]);
297 assert_eq!("bc", &"abc"[1..3]);
298 assert_eq!("", &"abc"[1..1]);
299 assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]);
301 let data = "ประเทศไทย中华";
302 assert_eq!("ป", &data[0..3]);
303 assert_eq!("ร", &data[3..6]);
304 assert_eq!("", &data[3..3]);
305 assert_eq!("华", &data[30..33]);
307 fn a_million_letter_x() -> String {
309 let mut rs = String::new();
311 rs.push_str("华华华华华华华华华华");
316 fn half_a_million_letter_x() -> String {
318 let mut rs = String::new();
320 rs.push_str("华华华华华");
325 let letters = a_million_letter_x();
326 assert_eq!(half_a_million_letter_x(), &letters[0..3 * 500000]);
331 let ss = "中华Việt Nam";
333 assert_eq!("华", &ss[3..6]);
334 assert_eq!("Việt Nam", &ss[6..16]);
336 assert_eq!("ab", &"abc"[0..2]);
337 assert_eq!("bc", &"abc"[1..3]);
338 assert_eq!("", &"abc"[1..1]);
340 assert_eq!("中", &ss[0..3]);
341 assert_eq!("华V", &ss[3..7]);
342 assert_eq!("", &ss[3..3]);
357 fn test_slice_fail() {
363 fn test_is_char_boundary() {
364 let s = "ศไทย中华Việt Nam β-release 🐱123";
365 assert!(s.is_char_boundary(0));
366 assert!(s.is_char_boundary(s.len()));
367 assert!(!s.is_char_boundary(s.len() + 1));
368 for (i, ch) in s.char_indices() {
369 // ensure character locations are boundaries and continuation bytes are not
370 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
371 for j in 1..ch.len_utf8() {
372 assert!(!s.is_char_boundary(i + j),
373 "{} should not be a char boundary in {:?}", i + j, s);
377 const LOREM_PARAGRAPH: &'static str = "\
378 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
379 ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
380 eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
381 sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
382 tempus vel, gravida nec quam.";
384 // check the panic includes the prefix of the sliced string
386 #[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
387 fn test_slice_fail_truncated_1() {
388 &LOREM_PARAGRAPH[..1024];
390 // check the truncation in the panic message
392 #[should_panic(expected="luctus, im`[...]")]
393 fn test_slice_fail_truncated_2() {
394 &LOREM_PARAGRAPH[..1024];
398 #[should_panic(expected="byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of")]
399 fn test_slice_fail_boundary_1() {
404 #[should_panic(expected="byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of")]
405 fn test_slice_fail_boundary_2() {
410 fn test_slice_from() {
411 assert_eq!(&"abcd"[0..], "abcd");
412 assert_eq!(&"abcd"[2..], "cd");
413 assert_eq!(&"abcd"[4..], "");
417 assert_eq!(&"abcd"[..0], "");
418 assert_eq!(&"abcd"[..2], "ab");
419 assert_eq!(&"abcd"[..4], "abcd");
423 fn test_trim_left_matches() {
424 let v: &[char] = &[];
425 assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** ");
426 let chars: &[char] = &['*', ' '];
427 assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** ");
428 assert_eq!(" *** *** ".trim_left_matches(chars), "");
429 assert_eq!("foo *** ".trim_left_matches(chars), "foo *** ");
431 assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
432 let chars: &[char] = &['1', '2'];
433 assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12");
434 assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
438 fn test_trim_right_matches() {
439 let v: &[char] = &[];
440 assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** ");
441 let chars: &[char] = &['*', ' '];
442 assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo");
443 assert_eq!(" *** *** ".trim_right_matches(chars), "");
444 assert_eq!(" *** foo".trim_right_matches(chars), " *** foo");
446 assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
447 let chars: &[char] = &['1', '2'];
448 assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar");
449 assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
453 fn test_trim_matches() {
454 let v: &[char] = &[];
455 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
456 let chars: &[char] = &['*', ' '];
457 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
458 assert_eq!(" *** *** ".trim_matches(chars), "");
459 assert_eq!("foo".trim_matches(chars), "foo");
461 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
462 let chars: &[char] = &['1', '2'];
463 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
464 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
468 fn test_trim_left() {
469 assert_eq!("".trim_left(), "");
470 assert_eq!("a".trim_left(), "a");
471 assert_eq!(" ".trim_left(), "");
472 assert_eq!(" blah".trim_left(), "blah");
473 assert_eq!(" \u{3000} wut".trim_left(), "wut");
474 assert_eq!("hey ".trim_left(), "hey ");
478 fn test_trim_right() {
479 assert_eq!("".trim_right(), "");
480 assert_eq!("a".trim_right(), "a");
481 assert_eq!(" ".trim_right(), "");
482 assert_eq!("blah ".trim_right(), "blah");
483 assert_eq!("wut \u{3000} ".trim_right(), "wut");
484 assert_eq!(" hey".trim_right(), " hey");
489 assert_eq!("".trim(), "");
490 assert_eq!("a".trim(), "a");
491 assert_eq!(" ".trim(), "");
492 assert_eq!(" blah ".trim(), "blah");
493 assert_eq!("\nwut \u{3000} ".trim(), "wut");
494 assert_eq!(" hey dude ".trim(), "hey dude");
498 fn test_is_whitespace() {
499 assert!("".chars().all(|c| c.is_whitespace()));
500 assert!(" ".chars().all(|c| c.is_whitespace()));
501 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
502 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
503 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
508 // deny overlong encodings
509 assert!(from_utf8(&[0xc0, 0x80]).is_err());
510 assert!(from_utf8(&[0xc0, 0xae]).is_err());
511 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
512 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
513 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
514 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
515 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
518 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
519 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
521 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
522 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
523 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
524 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
525 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
526 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
527 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
528 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
532 fn from_utf8_mostly_ascii() {
533 // deny invalid bytes embedded in long stretches of ascii
535 let mut data = [0; 128];
537 assert!(from_utf8(&data).is_err());
539 assert!(from_utf8(&data).is_err());
547 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
548 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
552 assert_eq!("".as_bytes(), b);
553 assert_eq!("abc".as_bytes(), b"abc");
554 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
559 fn test_as_bytes_fail() {
560 // Don't double free. (I'm not sure if this exercises the
561 // original problem code path anymore.)
562 let s = String::from("");
563 let _bytes = s.as_bytes();
569 let buf = "hello".as_ptr();
571 assert_eq!(*buf.offset(0), b'h');
572 assert_eq!(*buf.offset(1), b'e');
573 assert_eq!(*buf.offset(2), b'l');
574 assert_eq!(*buf.offset(3), b'l');
575 assert_eq!(*buf.offset(4), b'o');
580 fn vec_str_conversions() {
581 let s1: String = String::from("All mimsy were the borogoves");
583 let v: Vec<u8> = s1.as_bytes().to_vec();
584 let s2: String = String::from(from_utf8(&v).unwrap());
590 let a: u8 = s1.as_bytes()[i];
591 let b: u8 = s2.as_bytes()[i];
599 assert!("abcde".contains("bcd"));
600 assert!("abcde".contains("abcd"));
601 assert!("abcde".contains("bcde"));
602 assert!("abcde".contains(""));
603 assert!("".contains(""));
604 assert!(!"abcde".contains("def"));
605 assert!(!"".contains("a"));
607 let data = "ประเทศไทย中华Việt Nam";
608 assert!(data.contains("ประเ"));
609 assert!(data.contains("ะเ"));
610 assert!(data.contains("中华"));
611 assert!(!data.contains("ไท华"));
615 fn test_contains_char() {
616 assert!("abc".contains('b'));
617 assert!("a".contains('a'));
618 assert!(!"abc".contains('d'));
619 assert!(!"".contains('a'));
624 let s = "ศไทย中华Việt Nam";
625 for (index, _) in s.char_indices() {
626 let (a, b) = s.split_at(index);
627 assert_eq!(&s[..a.len()], a);
628 assert_eq!(&s[a.len()..], b);
630 let (a, b) = s.split_at(s.len());
636 fn test_split_at_mut() {
637 use std::ascii::AsciiExt;
638 let mut s = "Hello World".to_string();
640 let (a, b) = s.split_at_mut(5);
641 a.make_ascii_uppercase();
642 b.make_ascii_lowercase();
644 assert_eq!(s, "HELLO world");
649 fn test_split_at_boundscheck() {
650 let s = "ศไทย中华Việt Nam";
655 fn test_escape_unicode() {
656 assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
657 assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
658 assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
659 assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
660 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
661 assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
662 assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
663 assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
664 assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
668 fn test_escape_debug() {
669 assert_eq!("abc".escape_debug(), "abc");
670 assert_eq!("a c".escape_debug(), "a c");
671 assert_eq!("éèê".escape_debug(), "éèê");
672 assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
673 assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
674 assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
675 assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
676 assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
677 assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
678 assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
682 fn test_escape_default() {
683 assert_eq!("abc".escape_default(), "abc");
684 assert_eq!("a c".escape_default(), "a c");
685 assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
686 assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
687 assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
688 assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
689 assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
690 assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
691 assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
692 assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
696 fn test_total_ord() {
697 assert_eq!("1234".cmp("123"), Greater);
698 assert_eq!("123".cmp("1234"), Less);
699 assert_eq!("1234".cmp("1234"), Equal);
700 assert_eq!("12345555".cmp("123456"), Less);
701 assert_eq!("22".cmp("1234"), Greater);
706 let s = "ศไทย中华Việt Nam";
707 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
713 assert_eq!(c, v[pos]);
716 assert_eq!(pos, v.len());
717 assert_eq!(s.chars().count(), v.len());
721 fn test_rev_iterator() {
722 let s = "ศไทย中华Việt Nam";
723 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
726 let it = s.chars().rev();
729 assert_eq!(c, v[pos]);
732 assert_eq!(pos, v.len());
736 fn test_chars_decoding() {
737 let mut bytes = [0; 4];
738 for c in (0..0x110000).filter_map(::std::char::from_u32) {
739 let s = c.encode_utf8(&mut bytes);
740 if Some(c) != s.chars().next() {
741 panic!("character {:x}={} does not decode correctly", c as u32, c);
747 fn test_chars_rev_decoding() {
748 let mut bytes = [0; 4];
749 for c in (0..0x110000).filter_map(::std::char::from_u32) {
750 let s = c.encode_utf8(&mut bytes);
751 if Some(c) != s.chars().rev().next() {
752 panic!("character {:x}={} does not decode correctly", c as u32, c);
758 fn test_iterator_clone() {
759 let s = "ศไทย中华Việt Nam";
760 let mut it = s.chars();
762 assert!(it.clone().zip(it).all(|(x,y)| x == y));
766 fn test_iterator_last() {
767 let s = "ศไทย中华Việt Nam";
768 let mut it = s.chars();
770 assert_eq!(it.last(), Some('m'));
774 fn test_bytesator() {
775 let s = "ศไทย中华Việt Nam";
777 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
778 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
784 assert_eq!(b, v[pos]);
790 fn test_bytes_revator() {
791 let s = "ศไทย中华Việt Nam";
793 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
794 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
797 let mut pos = v.len();
799 for b in s.bytes().rev() {
801 assert_eq!(b, v[pos]);
806 fn test_bytesator_nth() {
807 let s = "ศไทย中华Việt Nam";
809 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
810 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
814 let mut b = s.bytes();
815 assert_eq!(b.nth(2).unwrap(), v[2]);
816 assert_eq!(b.nth(10).unwrap(), v[10]);
817 assert_eq!(b.nth(200), None);
821 fn test_bytesator_count() {
822 let s = "ศไทย中华Việt Nam";
825 assert_eq!(b.count(), 28)
829 fn test_bytesator_last() {
830 let s = "ศไทย中华Việt Nam";
833 assert_eq!(b.last().unwrap(), 109)
837 fn test_char_indicesator() {
838 let s = "ศไทย中华Việt Nam";
839 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
840 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
843 let it = s.char_indices();
846 assert_eq!(c, (p[pos], v[pos]));
849 assert_eq!(pos, v.len());
850 assert_eq!(pos, p.len());
854 fn test_char_indices_revator() {
855 let s = "ศไทย中华Việt Nam";
856 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
857 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
860 let it = s.char_indices().rev();
863 assert_eq!(c, (p[pos], v[pos]));
866 assert_eq!(pos, v.len());
867 assert_eq!(pos, p.len());
871 fn test_char_indices_last() {
872 let s = "ศไทย中华Việt Nam";
873 let mut it = s.char_indices();
875 assert_eq!(it.last(), Some((27, 'm')));
879 fn test_splitn_char_iterator() {
880 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
882 let split: Vec<&str> = data.splitn(4, ' ').collect();
883 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
885 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
886 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
889 let split: Vec<&str> = data.splitn(4, 'ä').collect();
890 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
892 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
893 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
897 fn test_split_char_iterator_no_trailing() {
898 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
900 let split: Vec<&str> = data.split('\n').collect();
901 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
903 let split: Vec<&str> = data.split_terminator('\n').collect();
904 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
909 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
911 let split: Vec<&str> = data.rsplit(' ').collect();
912 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
914 let split: Vec<&str> = data.rsplit("lämb").collect();
915 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
917 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
918 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
923 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
925 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
926 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
928 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
929 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
931 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
932 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
936 fn test_split_whitespace() {
937 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
938 let words: Vec<&str> = data.split_whitespace().collect();
939 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
944 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
945 let lines: Vec<&str> = data.lines().collect();
946 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
948 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
949 let lines: Vec<&str> = data.lines().collect();
950 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
954 fn test_splitator() {
955 fn t(s: &str, sep: &str, u: &[&str]) {
956 let v: Vec<&str> = s.split(sep).collect();
959 t("--1233345--", "12345", &["--1233345--"]);
960 t("abc::hello::there", "::", &["abc", "hello", "there"]);
961 t("::hello::there", "::", &["", "hello", "there"]);
962 t("hello::there::", "::", &["hello", "there", ""]);
963 t("::hello::there::", "::", &["", "hello", "there", ""]);
964 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
965 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
966 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
967 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
969 t("zz", "zz", &["",""]);
970 t("ok", "z", &["ok"]);
971 t("zzz", "zz", &["","z"]);
972 t("zzzzz", "zz", &["","","z"]);
976 fn test_str_default() {
977 use std::default::Default;
979 fn t<S: Default + AsRef<str>>() {
980 let s: S = Default::default();
981 assert_eq!(s.as_ref(), "");
989 fn test_str_container() {
990 fn sum_len(v: &[&str]) -> usize {
991 v.iter().map(|x| x.len()).sum()
995 assert_eq!(5, sum_len(&["012", "", "34"]));
996 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
997 assert_eq!(5, sum_len(&[s]));
1001 fn test_str_from_utf8() {
1003 assert_eq!(from_utf8(xs), Ok("hello"));
1005 let xs = "ศไทย中华Việt Nam".as_bytes();
1006 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1008 let xs = b"hello\xFF";
1009 assert!(from_utf8(xs).is_err());
1013 fn test_pattern_deref_forward() {
1014 let data = "aabcdaa";
1015 assert!(data.contains("bcd"));
1016 assert!(data.contains(&"bcd"));
1017 assert!(data.contains(&"bcd".to_string()));
1021 fn test_empty_match_indices() {
1023 let vec: Vec<_> = data.match_indices("").collect();
1024 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1028 fn test_bool_from_str() {
1029 assert_eq!("true".parse().ok(), Some(true));
1030 assert_eq!("false".parse().ok(), Some(false));
1031 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1034 fn check_contains_all_substrings(s: &str) {
1035 assert!(s.contains(""));
1036 for i in 0..s.len() {
1037 for j in i+1..s.len() + 1 {
1038 assert!(s.contains(&s[i..j]));
1044 fn strslice_issue_16589() {
1045 assert!("bananas".contains("nana"));
1047 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1048 // test all substrings for good measure
1049 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1053 fn strslice_issue_16878() {
1054 assert!(!"1234567ah012345678901ah".contains("hah"));
1055 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1060 fn test_strslice_contains() {
1061 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1062 check_contains_all_substrings(x);
1066 fn test_rsplitn_char_iterator() {
1067 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1069 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1071 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1073 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1075 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1078 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1080 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1082 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1084 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1088 fn test_split_char_iterator() {
1089 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1091 let split: Vec<&str> = data.split(' ').collect();
1092 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1094 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1096 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1098 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1099 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1101 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1103 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1106 let split: Vec<&str> = data.split('ä').collect();
1107 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1109 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1111 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1113 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1114 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1116 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1118 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1122 fn test_rev_split_char_iterator_no_trailing() {
1123 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1125 let mut split: Vec<&str> = data.split('\n').rev().collect();
1127 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1129 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1131 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1135 fn test_utf16_code_units() {
1136 use std_unicode::str::Utf16Encoder;
1137 assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
1138 [0xE9, 0xD83D, 0xDCA9])
1142 fn starts_with_in_unicode() {
1143 assert!(!"├── Cargo.toml".starts_with("# "));
1147 fn starts_short_long() {
1148 assert!(!"".starts_with("##"));
1149 assert!(!"##".starts_with("####"));
1150 assert!("####".starts_with("##"));
1151 assert!(!"##ä".starts_with("####"));
1152 assert!("####ä".starts_with("##"));
1153 assert!(!"##".starts_with("####ä"));
1154 assert!("##ä##".starts_with("##ä"));
1156 assert!("".starts_with(""));
1157 assert!("ä".starts_with(""));
1158 assert!("#ä".starts_with(""));
1159 assert!("##ä".starts_with(""));
1160 assert!("ä###".starts_with(""));
1161 assert!("#ä##".starts_with(""));
1162 assert!("##ä#".starts_with(""));
1166 fn contains_weird_cases() {
1167 assert!("* \t".contains(' '));
1168 assert!(!"* \t".contains('?'));
1169 assert!(!"* \t".contains('\u{1F4A9}'));
1174 assert_eq!(" \t a \t ".trim_left_matches(|c: char| c.is_whitespace()),
1176 assert_eq!(" \t a \t ".trim_right_matches(|c: char| c.is_whitespace()),
1178 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
1180 assert_eq!(" \t \t ".trim_left_matches(|c: char| c.is_whitespace()),
1182 assert_eq!(" \t \t ".trim_right_matches(|c: char| c.is_whitespace()),
1184 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
1190 assert_eq!("".to_lowercase(), "");
1191 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1193 // https://github.com/rust-lang/rust/issues/26035
1194 assert_eq!("ΑΣ".to_lowercase(), "ας");
1195 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1196 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1198 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1199 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1200 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1202 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1203 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1205 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1206 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1208 assert_eq!("Α Σ".to_lowercase(), "α σ");
1209 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1210 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1212 assert_eq!("Σ".to_lowercase(), "σ");
1213 assert_eq!("'Σ".to_lowercase(), "'σ");
1214 assert_eq!("''Σ".to_lowercase(), "''σ");
1216 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1217 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1218 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1223 assert_eq!("".to_uppercase(), "");
1224 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1228 fn test_into_string() {
1229 // The only way to acquire a Box<str> in the first place is through a String, so just
1230 // test that we can round-trip between Box<str> and String.
1231 let string = String::from("Some text goes here");
1232 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1236 fn test_box_slice_clone() {
1237 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1238 let data2 = data.clone().into_boxed_str().clone().into_string();
1240 assert_eq!(data, data2);
1244 fn test_cow_from() {
1245 let borrowed = "borrowed";
1246 let owned = String::from("owned");
1247 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1248 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1249 _ => panic!("invalid `Cow::from`"),
1255 assert_eq!("".repeat(3), "");
1256 assert_eq!("abc".repeat(0), "");
1257 assert_eq!("α".repeat(3), "ααα");
1261 use std::str::pattern::Pattern;
1262 use std::str::pattern::{Searcher, ReverseSearcher};
1263 use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1265 macro_rules! make_test {
1266 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1267 #[allow(unused_imports)]
1269 use std::str::pattern::SearchStep::{Match, Reject};
1270 use super::{cmp_search_to_vec};
1273 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1277 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1283 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1284 right: Vec<SearchStep>)
1285 where P::Searcher: ReverseSearcher<'a>
1287 let mut searcher = pat.into_searcher(haystack);
1290 match if !rev {searcher.next()} else {searcher.next_back()} {
1291 Match(a, b) => v.push(Match(a, b)),
1292 Reject(a, b) => v.push(Reject(a, b)),
1300 let mut first_index = 0;
1303 for (i, e) in right.iter().enumerate() {
1305 Match(a, b) | Reject(a, b)
1306 if a <= b && a == first_index => {
1316 if let Some(err) = err {
1317 panic!("Input skipped range at {}", err);
1320 if first_index != haystack.len() {
1321 panic!("Did not cover whole input");
1324 assert_eq!(v, right);
1327 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1334 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1342 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1359 make_test!(str_searcher_mulibyte_haystack, " ", "├──", [
1364 make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [
1373 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1376 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1378 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1387 make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [
1392 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1400 macro_rules! generate_iterator_test {
1404 ($($arg:expr),*) -> [$($t:tt)*];
1407 with $fwd:expr, $bwd:expr;
1413 let res = vec![$($t)*];
1415 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1416 assert_eq!(fwd_vec, res);
1418 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1420 assert_eq!(bwd_vec, res);
1428 ($($arg:expr),*) -> [$($t:tt)*];
1437 let res = vec![$($t)*];
1439 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1440 assert_eq!(fwd_vec, res);
1447 generate_iterator_test! {
1448 double_ended_split {
1449 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1450 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1452 with str::split, str::rsplit;
1455 generate_iterator_test! {
1456 double_ended_split_terminator {
1457 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1459 with str::split_terminator, str::rsplit_terminator;
1462 generate_iterator_test! {
1463 double_ended_matches {
1464 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1466 with str::matches, str::rmatches;
1469 generate_iterator_test! {
1470 double_ended_match_indices {
1471 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1473 with str::match_indices, str::rmatch_indices;
1476 generate_iterator_test! {
1477 not_double_ended_splitn {
1478 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1483 generate_iterator_test! {
1484 not_double_ended_rsplitn {
1485 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1491 fn different_str_pattern_forwarding_lifetimes() {
1492 use std::str::pattern::Pattern;
1494 fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {