]> git.lizzy.rs Git - rust.git/blob - src/liballoc/tests/str.rs
b3178064505e8683f0bbeacd77b01b3c36ccca89
[rust.git] / src / liballoc / tests / str.rs
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.
4 //
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.
10
11 use std::borrow::Cow;
12 use std::cmp::Ordering::{Equal, Greater, Less};
13 use std::str::from_utf8;
14
15 #[test]
16 fn test_le() {
17     assert!("" <= "");
18     assert!("" <= "foo");
19     assert!("foo" <= "foo");
20     assert!("foo" != "bar");
21 }
22
23 #[test]
24 fn test_find() {
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));
31 }
32
33 #[test]
34 fn test_rfind() {
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));
41 }
42
43 #[test]
44 fn test_collect() {
45     let empty = "";
46     let s: String = empty.chars().collect();
47     assert_eq!(empty, s);
48     let data = "ประเทศไทย中";
49     let s: String = data.chars().collect();
50     assert_eq!(data, s);
51 }
52
53 #[test]
54 fn test_into_bytes() {
55     let data = String::from("asdf");
56     let buf = data.into_bytes();
57     assert_eq!(buf, b"asdf");
58 }
59
60 #[test]
61 fn test_find_str() {
62     // byte positions
63     assert_eq!("".find(""), Some(0));
64     assert!("banana".find("apple pie").is_none());
65
66     let data = "abcabc";
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());
70
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));
77
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));
83
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));
89
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()
95                              .map(|(i, _)| i)
96                              .chain(Some(string.len() - ip))
97         {
98             let pat = &string[i..ip + j];
99             assert!(match string.find(pat) {
100                 None => false,
101                 Some(x) => x <= i,
102             });
103             assert!(match string.rfind(pat) {
104                 None => false,
105                 Some(x) => x >= i,
106             });
107         }
108     }
109 }
110
111 fn s(x: &str) -> String { x.to_string() }
112
113 macro_rules! test_concat {
114     ($expected: expr, $string: expr) => {
115         {
116             let s: String = $string.concat();
117             assert_eq!($expected, s);
118         }
119     }
120 }
121
122 #[test]
123 fn test_concat_for_different_types() {
124     test_concat!("ab", vec![s("a"), s("b")]);
125     test_concat!("ab", vec!["a", "b"]);
126 }
127
128 #[test]
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"]);
135 }
136
137 macro_rules! test_join {
138     ($expected: expr, $string: expr, $delim: expr) => {
139         {
140             let s = $string.join($delim);
141             assert_eq!($expected, s);
142         }
143     }
144 }
145
146 #[test]
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")], "-");
154 }
155
156 #[test]
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"], "-");
163 }
164
165 #[test]
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 {
171         let mut i = 0;
172         let mut rs = String::new();
173         while i < 100000 {
174             rs.push_str("aaaaaaaaaa");
175             i += 1;
176         }
177         rs
178     }
179     fn half_a_million_letter_a() -> String {
180         let mut i = 0;
181         let mut rs = String::new();
182         while i < 100000 {
183             rs.push_str("aaaaa");
184             i += 1;
185         }
186         rs
187     }
188     let letters = a_million_letter_a();
189     assert_eq!(half_a_million_letter_a(),
190         unsafe { letters.slice_unchecked(0, 500000)});
191 }
192
193 #[test]
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"));
202 }
203
204 #[test]
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ö"));
213 }
214
215 #[test]
216 fn test_is_empty() {
217     assert!("".is_empty());
218     assert!(!"a".is_empty());
219 }
220
221 #[test]
222 fn test_replacen() {
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");
226
227     let test = "test";
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), "   ");
231
232     assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
233 }
234
235 #[test]
236 fn test_replace() {
237     let a = "a";
238     assert_eq!("".replace(a, "b"), "");
239     assert_eq!("a".replace(a, "b"), "b");
240     assert_eq!("ab".replace(a, "b"), "bb");
241     let test = "test";
242     assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
243     assert_eq!(" test test ".replace(test, ""), "   ");
244 }
245
246 #[test]
247 fn test_replace_2a() {
248     let data = "ประเทศไทย中华";
249     let repl = "دولة الكويت";
250
251     let a = "ประเ";
252     let a2 = "دولة الكويتทศไทย中华";
253     assert_eq!(data.replace(a, repl), a2);
254 }
255
256 #[test]
257 fn test_replace_2b() {
258     let data = "ประเทศไทย中华";
259     let repl = "دولة الكويت";
260
261     let b = "ะเ";
262     let b2 = "ปรدولة الكويتทศไทย中华";
263     assert_eq!(data.replace(b, repl), b2);
264 }
265
266 #[test]
267 fn test_replace_2c() {
268     let data = "ประเทศไทย中华";
269     let repl = "دولة الكويت";
270
271     let c = "中华";
272     let c2 = "ประเทศไทยدولة الكويت";
273     assert_eq!(data.replace(c, repl), c2);
274 }
275
276 #[test]
277 fn test_replace_2d() {
278     let data = "ประเทศไทย中华";
279     let repl = "دولة الكويت";
280
281     let d = "ไท华";
282     assert_eq!(data.replace(d, repl), data);
283 }
284
285 #[test]
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αβ😺😺😺δ");
292 }
293
294 #[test]
295 fn test_slice() {
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]);
300
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]);
306
307     fn a_million_letter_x() -> String {
308         let mut i = 0;
309         let mut rs = String::new();
310         while i < 100000 {
311             rs.push_str("华华华华华华华华华华");
312             i += 1;
313         }
314         rs
315     }
316     fn half_a_million_letter_x() -> String {
317         let mut i = 0;
318         let mut rs = String::new();
319         while i < 100000 {
320             rs.push_str("华华华华华");
321             i += 1;
322         }
323         rs
324     }
325     let letters = a_million_letter_x();
326     assert_eq!(half_a_million_letter_x(), &letters[0..3 * 500000]);
327 }
328
329 #[test]
330 fn test_slice_2() {
331     let ss = "中华Việt Nam";
332
333     assert_eq!("华", &ss[3..6]);
334     assert_eq!("Việt Nam", &ss[6..16]);
335
336     assert_eq!("ab", &"abc"[0..2]);
337     assert_eq!("bc", &"abc"[1..3]);
338     assert_eq!("", &"abc"[1..1]);
339
340     assert_eq!("中", &ss[0..3]);
341     assert_eq!("华V", &ss[3..7]);
342     assert_eq!("", &ss[3..3]);
343     /*0: 中
344       3: 华
345       6: V
346       7: i
347       8: ệ
348      11: t
349      12:
350      13: N
351      14: a
352      15: m */
353 }
354
355 #[test]
356 #[should_panic]
357 fn test_slice_fail() {
358     &"中华Việt Nam"[0..2];
359 }
360
361 #[test]
362 #[should_panic]
363 fn test_str_slice_rangetoinclusive_max_panics() {
364     &"hello"[..=usize::max_value()];
365 }
366
367 #[test]
368 #[should_panic]
369 fn test_str_slice_rangeinclusive_max_panics() {
370     &"hello"[1..=usize::max_value()];
371 }
372
373 #[test]
374 #[should_panic]
375 fn test_str_slicemut_rangetoinclusive_max_panics() {
376     let mut s = "hello".to_owned();
377     let s: &mut str = &mut s;
378     &mut s[..=usize::max_value()];
379 }
380
381 #[test]
382 #[should_panic]
383 fn test_str_slicemut_rangeinclusive_max_panics() {
384     let mut s = "hello".to_owned();
385     let s: &mut str = &mut s;
386     &mut s[1..=usize::max_value()];
387 }
388
389 #[test]
390 fn test_str_get_maxinclusive() {
391     let mut s = "hello".to_owned();
392     {
393         let s: &str = &s;
394         assert_eq!(s.get(..=usize::max_value()), None);
395         assert_eq!(s.get(1..=usize::max_value()), None);
396     }
397     {
398         let s: &mut str = &mut s;
399         assert_eq!(s.get(..=usize::max_value()), None);
400         assert_eq!(s.get(1..=usize::max_value()), None);
401     }
402 }
403
404 #[test]
405 fn test_is_char_boundary() {
406     let s = "ศไทย中华Việt Nam β-release 🐱123";
407     assert!(s.is_char_boundary(0));
408     assert!(s.is_char_boundary(s.len()));
409     assert!(!s.is_char_boundary(s.len() + 1));
410     for (i, ch) in s.char_indices() {
411         // ensure character locations are boundaries and continuation bytes are not
412         assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
413         for j in 1..ch.len_utf8() {
414             assert!(!s.is_char_boundary(i + j),
415                     "{} should not be a char boundary in {:?}", i + j, s);
416         }
417     }
418 }
419 const LOREM_PARAGRAPH: &'static str = "\
420 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
421 ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
422 eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
423 sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
424 tempus vel, gravida nec quam.";
425
426 // check the panic includes the prefix of the sliced string
427 #[test]
428 #[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
429 fn test_slice_fail_truncated_1() {
430     &LOREM_PARAGRAPH[..1024];
431 }
432 // check the truncation in the panic message
433 #[test]
434 #[should_panic(expected="luctus, im`[...]")]
435 fn test_slice_fail_truncated_2() {
436     &LOREM_PARAGRAPH[..1024];
437 }
438
439 #[test]
440 #[should_panic(expected="byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of")]
441 fn test_slice_fail_boundary_1() {
442     &"abcαβγ"[4..];
443 }
444
445 #[test]
446 #[should_panic(expected="byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of")]
447 fn test_slice_fail_boundary_2() {
448     &"abcαβγ"[2..6];
449 }
450
451 #[test]
452 fn test_slice_from() {
453     assert_eq!(&"abcd"[0..], "abcd");
454     assert_eq!(&"abcd"[2..], "cd");
455     assert_eq!(&"abcd"[4..], "");
456 }
457 #[test]
458 fn test_slice_to() {
459     assert_eq!(&"abcd"[..0], "");
460     assert_eq!(&"abcd"[..2], "ab");
461     assert_eq!(&"abcd"[..4], "abcd");
462 }
463
464 #[test]
465 fn test_trim_left_matches() {
466     let v: &[char] = &[];
467     assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** ");
468     let chars: &[char] = &['*', ' '];
469     assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** ");
470     assert_eq!(" ***  *** ".trim_left_matches(chars), "");
471     assert_eq!("foo *** ".trim_left_matches(chars), "foo *** ");
472
473     assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
474     let chars: &[char] = &['1', '2'];
475     assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12");
476     assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
477 }
478
479 #[test]
480 fn test_trim_right_matches() {
481     let v: &[char] = &[];
482     assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** ");
483     let chars: &[char] = &['*', ' '];
484     assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo");
485     assert_eq!(" ***  *** ".trim_right_matches(chars), "");
486     assert_eq!(" *** foo".trim_right_matches(chars), " *** foo");
487
488     assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
489     let chars: &[char] = &['1', '2'];
490     assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar");
491     assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
492 }
493
494 #[test]
495 fn test_trim_matches() {
496     let v: &[char] = &[];
497     assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
498     let chars: &[char] = &['*', ' '];
499     assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
500     assert_eq!(" ***  *** ".trim_matches(chars), "");
501     assert_eq!("foo".trim_matches(chars), "foo");
502
503     assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
504     let chars: &[char] = &['1', '2'];
505     assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
506     assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
507 }
508
509 #[test]
510 fn test_trim_left() {
511     assert_eq!("".trim_left(), "");
512     assert_eq!("a".trim_left(), "a");
513     assert_eq!("    ".trim_left(), "");
514     assert_eq!("     blah".trim_left(), "blah");
515     assert_eq!("   \u{3000}  wut".trim_left(), "wut");
516     assert_eq!("hey ".trim_left(), "hey ");
517 }
518
519 #[test]
520 fn test_trim_right() {
521     assert_eq!("".trim_right(), "");
522     assert_eq!("a".trim_right(), "a");
523     assert_eq!("    ".trim_right(), "");
524     assert_eq!("blah     ".trim_right(), "blah");
525     assert_eq!("wut   \u{3000}  ".trim_right(), "wut");
526     assert_eq!(" hey".trim_right(), " hey");
527 }
528
529 #[test]
530 fn test_trim() {
531     assert_eq!("".trim(), "");
532     assert_eq!("a".trim(), "a");
533     assert_eq!("    ".trim(), "");
534     assert_eq!("    blah     ".trim(), "blah");
535     assert_eq!("\nwut   \u{3000}  ".trim(), "wut");
536     assert_eq!(" hey dude ".trim(), "hey dude");
537 }
538
539 #[test]
540 fn test_is_whitespace() {
541     assert!("".chars().all(|c| c.is_whitespace()));
542     assert!(" ".chars().all(|c| c.is_whitespace()));
543     assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
544     assert!("  \n\t   ".chars().all(|c| c.is_whitespace()));
545     assert!(!"   _   ".chars().all(|c| c.is_whitespace()));
546 }
547
548 #[test]
549 fn test_is_utf8() {
550     // deny overlong encodings
551     assert!(from_utf8(&[0xc0, 0x80]).is_err());
552     assert!(from_utf8(&[0xc0, 0xae]).is_err());
553     assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
554     assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
555     assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
556     assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
557     assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
558
559     // deny surrogates
560     assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
561     assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
562
563     assert!(from_utf8(&[0xC2, 0x80]).is_ok());
564     assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
565     assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
566     assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
567     assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
568     assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
569     assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
570     assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
571 }
572
573 #[test]
574 fn from_utf8_mostly_ascii() {
575     // deny invalid bytes embedded in long stretches of ascii
576     for i in 32..64 {
577         let mut data = [0; 128];
578         data[i] = 0xC0;
579         assert!(from_utf8(&data).is_err());
580         data[i] = 0xC2;
581         assert!(from_utf8(&data).is_err());
582     }
583 }
584
585 #[test]
586 fn from_utf8_error() {
587     macro_rules! test {
588         ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
589             let error = from_utf8($input).unwrap_err();
590             assert_eq!(error.valid_up_to(), $expected_valid_up_to);
591             assert_eq!(error.error_len(), $expected_error_len);
592         }
593     }
594     test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
595     test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
596     test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
597     test!(b"A\xC3\xA9 \xC1", 4, Some(1));
598     test!(b"A\xC3\xA9 \xC2", 4, None);
599     test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
600     test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
601     test!(b"A\xC3\xA9 \xE0", 4, None);
602     test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
603     test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
604     test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
605     test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
606     test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
607     test!(b"A\xC3\xA9 \xF1", 4, None);
608     test!(b"A\xC3\xA9 \xF1\x80", 4, None);
609     test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
610     test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
611     test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
612     test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
613 }
614
615 #[test]
616 fn test_as_bytes() {
617     // no null
618     let v = [
619         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
620         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
621         109
622     ];
623     let b: &[u8] = &[];
624     assert_eq!("".as_bytes(), b);
625     assert_eq!("abc".as_bytes(), b"abc");
626     assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
627 }
628
629 #[test]
630 #[should_panic]
631 fn test_as_bytes_fail() {
632     // Don't double free. (I'm not sure if this exercises the
633     // original problem code path anymore.)
634     let s = String::from("");
635     let _bytes = s.as_bytes();
636     panic!();
637 }
638
639 #[test]
640 fn test_as_ptr() {
641     let buf = "hello".as_ptr();
642     unsafe {
643         assert_eq!(*buf.offset(0), b'h');
644         assert_eq!(*buf.offset(1), b'e');
645         assert_eq!(*buf.offset(2), b'l');
646         assert_eq!(*buf.offset(3), b'l');
647         assert_eq!(*buf.offset(4), b'o');
648     }
649 }
650
651 #[test]
652 fn vec_str_conversions() {
653     let s1: String = String::from("All mimsy were the borogoves");
654
655     let v: Vec<u8> = s1.as_bytes().to_vec();
656     let s2: String = String::from(from_utf8(&v).unwrap());
657     let mut i = 0;
658     let n1 = s1.len();
659     let n2 = v.len();
660     assert_eq!(n1, n2);
661     while i < n1 {
662         let a: u8 = s1.as_bytes()[i];
663         let b: u8 = s2.as_bytes()[i];
664         assert_eq!(a, b);
665         i += 1;
666     }
667 }
668
669 #[test]
670 fn test_contains() {
671     assert!("abcde".contains("bcd"));
672     assert!("abcde".contains("abcd"));
673     assert!("abcde".contains("bcde"));
674     assert!("abcde".contains(""));
675     assert!("".contains(""));
676     assert!(!"abcde".contains("def"));
677     assert!(!"".contains("a"));
678
679     let data = "ประเทศไทย中华Việt Nam";
680     assert!(data.contains("ประเ"));
681     assert!(data.contains("ะเ"));
682     assert!(data.contains("中华"));
683     assert!(!data.contains("ไท华"));
684 }
685
686 #[test]
687 fn test_contains_char() {
688     assert!("abc".contains('b'));
689     assert!("a".contains('a'));
690     assert!(!"abc".contains('d'));
691     assert!(!"".contains('a'));
692 }
693
694 #[test]
695 fn test_split_at() {
696     let s = "ศไทย中华Việt Nam";
697     for (index, _) in s.char_indices() {
698         let (a, b) = s.split_at(index);
699         assert_eq!(&s[..a.len()], a);
700         assert_eq!(&s[a.len()..], b);
701     }
702     let (a, b) = s.split_at(s.len());
703     assert_eq!(a, s);
704     assert_eq!(b, "");
705 }
706
707 #[test]
708 fn test_split_at_mut() {
709     use std::ascii::AsciiExt;
710     let mut s = "Hello World".to_string();
711     {
712         let (a, b) = s.split_at_mut(5);
713         a.make_ascii_uppercase();
714         b.make_ascii_lowercase();
715     }
716     assert_eq!(s, "HELLO world");
717 }
718
719 #[test]
720 #[should_panic]
721 fn test_split_at_boundscheck() {
722     let s = "ศไทย中华Việt Nam";
723     s.split_at(1);
724 }
725
726 #[test]
727 fn test_escape_unicode() {
728     assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
729     assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
730     assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
731     assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
732     assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
733     assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
734     assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
735     assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
736     assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
737 }
738
739 #[test]
740 fn test_escape_debug() {
741     assert_eq!("abc".escape_debug(), "abc");
742     assert_eq!("a c".escape_debug(), "a c");
743     assert_eq!("éèê".escape_debug(), "éèê");
744     assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
745     assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
746     assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
747     assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
748     assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
749     assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
750     assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
751 }
752
753 #[test]
754 fn test_escape_default() {
755     assert_eq!("abc".escape_default(), "abc");
756     assert_eq!("a c".escape_default(), "a c");
757     assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
758     assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
759     assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
760     assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
761     assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
762     assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
763     assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
764     assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
765 }
766
767 #[test]
768 fn test_total_ord() {
769     assert_eq!("1234".cmp("123"), Greater);
770     assert_eq!("123".cmp("1234"), Less);
771     assert_eq!("1234".cmp("1234"), Equal);
772     assert_eq!("12345555".cmp("123456"), Less);
773     assert_eq!("22".cmp("1234"), Greater);
774 }
775
776 #[test]
777 fn test_iterator() {
778     let s = "ศไทย中华Việt Nam";
779     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
780
781     let mut pos = 0;
782     let it = s.chars();
783
784     for c in it {
785         assert_eq!(c, v[pos]);
786         pos += 1;
787     }
788     assert_eq!(pos, v.len());
789     assert_eq!(s.chars().count(), v.len());
790 }
791
792 #[test]
793 fn test_rev_iterator() {
794     let s = "ศไทย中华Việt Nam";
795     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
796
797     let mut pos = 0;
798     let it = s.chars().rev();
799
800     for c in it {
801         assert_eq!(c, v[pos]);
802         pos += 1;
803     }
804     assert_eq!(pos, v.len());
805 }
806
807 #[test]
808 fn test_chars_decoding() {
809     let mut bytes = [0; 4];
810     for c in (0..0x110000).filter_map(::std::char::from_u32) {
811         let s = c.encode_utf8(&mut bytes);
812         if Some(c) != s.chars().next() {
813             panic!("character {:x}={} does not decode correctly", c as u32, c);
814         }
815     }
816 }
817
818 #[test]
819 fn test_chars_rev_decoding() {
820     let mut bytes = [0; 4];
821     for c in (0..0x110000).filter_map(::std::char::from_u32) {
822         let s = c.encode_utf8(&mut bytes);
823         if Some(c) != s.chars().rev().next() {
824             panic!("character {:x}={} does not decode correctly", c as u32, c);
825         }
826     }
827 }
828
829 #[test]
830 fn test_iterator_clone() {
831     let s = "ศไทย中华Việt Nam";
832     let mut it = s.chars();
833     it.next();
834     assert!(it.clone().zip(it).all(|(x,y)| x == y));
835 }
836
837 #[test]
838 fn test_iterator_last() {
839     let s = "ศไทย中华Việt Nam";
840     let mut it = s.chars();
841     it.next();
842     assert_eq!(it.last(), Some('m'));
843 }
844
845 #[test]
846 fn test_bytesator() {
847     let s = "ศไทย中华Việt Nam";
848     let v = [
849         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
850         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
851         109
852     ];
853     let mut pos = 0;
854
855     for b in s.bytes() {
856         assert_eq!(b, v[pos]);
857         pos += 1;
858     }
859 }
860
861 #[test]
862 fn test_bytes_revator() {
863     let s = "ศไทย中华Việt Nam";
864     let v = [
865         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
866         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
867         109
868     ];
869     let mut pos = v.len();
870
871     for b in s.bytes().rev() {
872         pos -= 1;
873         assert_eq!(b, v[pos]);
874     }
875 }
876
877 #[test]
878 fn test_bytesator_nth() {
879     let s = "ศไทย中华Việt Nam";
880     let v = [
881         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
882         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
883         109
884     ];
885
886     let mut b = s.bytes();
887     assert_eq!(b.nth(2).unwrap(), v[2]);
888     assert_eq!(b.nth(10).unwrap(), v[10]);
889     assert_eq!(b.nth(200), None);
890 }
891
892 #[test]
893 fn test_bytesator_count() {
894     let s = "ศไทย中华Việt Nam";
895
896     let b = s.bytes();
897     assert_eq!(b.count(), 28)
898 }
899
900 #[test]
901 fn test_bytesator_last() {
902     let s = "ศไทย中华Việt Nam";
903
904     let b = s.bytes();
905     assert_eq!(b.last().unwrap(), 109)
906 }
907
908 #[test]
909 fn test_char_indicesator() {
910     let s = "ศไทย中华Việt Nam";
911     let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
912     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
913
914     let mut pos = 0;
915     let it = s.char_indices();
916
917     for c in it {
918         assert_eq!(c, (p[pos], v[pos]));
919         pos += 1;
920     }
921     assert_eq!(pos, v.len());
922     assert_eq!(pos, p.len());
923 }
924
925 #[test]
926 fn test_char_indices_revator() {
927     let s = "ศไทย中华Việt Nam";
928     let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
929     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
930
931     let mut pos = 0;
932     let it = s.char_indices().rev();
933
934     for c in it {
935         assert_eq!(c, (p[pos], v[pos]));
936         pos += 1;
937     }
938     assert_eq!(pos, v.len());
939     assert_eq!(pos, p.len());
940 }
941
942 #[test]
943 fn test_char_indices_last() {
944     let s = "ศไทย中华Việt Nam";
945     let mut it = s.char_indices();
946     it.next();
947     assert_eq!(it.last(), Some((27, 'm')));
948 }
949
950 #[test]
951 fn test_splitn_char_iterator() {
952     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
953
954     let split: Vec<&str> = data.splitn(4, ' ').collect();
955     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
956
957     let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
958     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
959
960     // Unicode
961     let split: Vec<&str> = data.splitn(4, 'ä').collect();
962     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
963
964     let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
965     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
966 }
967
968 #[test]
969 fn test_split_char_iterator_no_trailing() {
970     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
971
972     let split: Vec<&str> = data.split('\n').collect();
973     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
974
975     let split: Vec<&str> = data.split_terminator('\n').collect();
976     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
977 }
978
979 #[test]
980 fn test_rsplit() {
981     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
982
983     let split: Vec<&str> = data.rsplit(' ').collect();
984     assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
985
986     let split: Vec<&str> = data.rsplit("lämb").collect();
987     assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
988
989     let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
990     assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
991 }
992
993 #[test]
994 fn test_rsplitn() {
995     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
996
997     let split: Vec<&str> = data.rsplitn(2, ' ').collect();
998     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
999
1000     let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1001     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1002
1003     let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1004     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1005 }
1006
1007 #[test]
1008 fn test_split_whitespace() {
1009     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
1010     let words: Vec<&str> = data.split_whitespace().collect();
1011     assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1012 }
1013
1014 #[test]
1015 fn test_lines() {
1016     let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1017     let lines: Vec<&str> = data.lines().collect();
1018     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1019
1020     let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1021     let lines: Vec<&str> = data.lines().collect();
1022     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1023 }
1024
1025 #[test]
1026 fn test_splitator() {
1027     fn t(s: &str, sep: &str, u: &[&str]) {
1028         let v: Vec<&str> = s.split(sep).collect();
1029         assert_eq!(v, u);
1030     }
1031     t("--1233345--", "12345", &["--1233345--"]);
1032     t("abc::hello::there", "::", &["abc", "hello", "there"]);
1033     t("::hello::there", "::", &["", "hello", "there"]);
1034     t("hello::there::", "::", &["hello", "there", ""]);
1035     t("::hello::there::", "::", &["", "hello", "there", ""]);
1036     t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1037     t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1038     t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1039     t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1040     t("", ".", &[""]);
1041     t("zz", "zz", &["",""]);
1042     t("ok", "z", &["ok"]);
1043     t("zzz", "zz", &["","z"]);
1044     t("zzzzz", "zz", &["","","z"]);
1045 }
1046
1047 #[test]
1048 fn test_str_default() {
1049     use std::default::Default;
1050
1051     fn t<S: Default + AsRef<str>>() {
1052         let s: S = Default::default();
1053         assert_eq!(s.as_ref(), "");
1054     }
1055
1056     t::<&str>();
1057     t::<String>();
1058 }
1059
1060 #[test]
1061 fn test_str_container() {
1062     fn sum_len(v: &[&str]) -> usize {
1063         v.iter().map(|x| x.len()).sum()
1064     }
1065
1066     let s = "01234";
1067     assert_eq!(5, sum_len(&["012", "", "34"]));
1068     assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1069     assert_eq!(5, sum_len(&[s]));
1070 }
1071
1072 #[test]
1073 fn test_str_from_utf8() {
1074     let xs = b"hello";
1075     assert_eq!(from_utf8(xs), Ok("hello"));
1076
1077     let xs = "ศไทย中华Việt Nam".as_bytes();
1078     assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1079
1080     let xs = b"hello\xFF";
1081     assert!(from_utf8(xs).is_err());
1082 }
1083
1084 #[test]
1085 fn test_pattern_deref_forward() {
1086     let data = "aabcdaa";
1087     assert!(data.contains("bcd"));
1088     assert!(data.contains(&"bcd"));
1089     assert!(data.contains(&"bcd".to_string()));
1090 }
1091
1092 #[test]
1093 fn test_empty_match_indices() {
1094     let data = "aä中!";
1095     let vec: Vec<_> = data.match_indices("").collect();
1096     assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1097 }
1098
1099 #[test]
1100 fn test_bool_from_str() {
1101     assert_eq!("true".parse().ok(), Some(true));
1102     assert_eq!("false".parse().ok(), Some(false));
1103     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1104 }
1105
1106 fn check_contains_all_substrings(s: &str) {
1107     assert!(s.contains(""));
1108     for i in 0..s.len() {
1109         for j in i+1..s.len() + 1 {
1110             assert!(s.contains(&s[i..j]));
1111         }
1112     }
1113 }
1114
1115 #[test]
1116 fn strslice_issue_16589() {
1117     assert!("bananas".contains("nana"));
1118
1119     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1120     // test all substrings for good measure
1121     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1122 }
1123
1124 #[test]
1125 fn strslice_issue_16878() {
1126     assert!(!"1234567ah012345678901ah".contains("hah"));
1127     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1128 }
1129
1130
1131 #[test]
1132 fn test_strslice_contains() {
1133     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1134     check_contains_all_substrings(x);
1135 }
1136
1137 #[test]
1138 fn test_rsplitn_char_iterator() {
1139     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1140
1141     let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1142     split.reverse();
1143     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1144
1145     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1146     split.reverse();
1147     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1148
1149     // Unicode
1150     let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1151     split.reverse();
1152     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1153
1154     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1155     split.reverse();
1156     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1157 }
1158
1159 #[test]
1160 fn test_split_char_iterator() {
1161     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1162
1163     let split: Vec<&str> = data.split(' ').collect();
1164     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1165
1166     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1167     rsplit.reverse();
1168     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1169
1170     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1171     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1172
1173     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1174     rsplit.reverse();
1175     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1176
1177     // Unicode
1178     let split: Vec<&str> = data.split('ä').collect();
1179     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1180
1181     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1182     rsplit.reverse();
1183     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1184
1185     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1186     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1187
1188     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1189     rsplit.reverse();
1190     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1191 }
1192
1193 #[test]
1194 fn test_rev_split_char_iterator_no_trailing() {
1195     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1196
1197     let mut split: Vec<&str> = data.split('\n').rev().collect();
1198     split.reverse();
1199     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1200
1201     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1202     split.reverse();
1203     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1204 }
1205
1206 #[test]
1207 fn test_utf16_code_units() {
1208     use std_unicode::str::Utf16Encoder;
1209     assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
1210                [0xE9, 0xD83D, 0xDCA9])
1211 }
1212
1213 #[test]
1214 fn starts_with_in_unicode() {
1215     assert!(!"├── Cargo.toml".starts_with("# "));
1216 }
1217
1218 #[test]
1219 fn starts_short_long() {
1220     assert!(!"".starts_with("##"));
1221     assert!(!"##".starts_with("####"));
1222     assert!("####".starts_with("##"));
1223     assert!(!"##ä".starts_with("####"));
1224     assert!("####ä".starts_with("##"));
1225     assert!(!"##".starts_with("####ä"));
1226     assert!("##ä##".starts_with("##ä"));
1227
1228     assert!("".starts_with(""));
1229     assert!("ä".starts_with(""));
1230     assert!("#ä".starts_with(""));
1231     assert!("##ä".starts_with(""));
1232     assert!("ä###".starts_with(""));
1233     assert!("#ä##".starts_with(""));
1234     assert!("##ä#".starts_with(""));
1235 }
1236
1237 #[test]
1238 fn contains_weird_cases() {
1239     assert!("* \t".contains(' '));
1240     assert!(!"* \t".contains('?'));
1241     assert!(!"* \t".contains('\u{1F4A9}'));
1242 }
1243
1244 #[test]
1245 fn trim_ws() {
1246     assert_eq!(" \t  a \t  ".trim_left_matches(|c: char| c.is_whitespace()),
1247                     "a \t  ");
1248     assert_eq!(" \t  a \t  ".trim_right_matches(|c: char| c.is_whitespace()),
1249                " \t  a");
1250     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()),
1251                     "a");
1252     assert_eq!(" \t   \t  ".trim_left_matches(|c: char| c.is_whitespace()),
1253                          "");
1254     assert_eq!(" \t   \t  ".trim_right_matches(|c: char| c.is_whitespace()),
1255                "");
1256     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()),
1257                "");
1258 }
1259
1260 #[test]
1261 fn to_lowercase() {
1262     assert_eq!("".to_lowercase(), "");
1263     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1264
1265     // https://github.com/rust-lang/rust/issues/26035
1266     assert_eq!("ΑΣ".to_lowercase(), "ας");
1267     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1268     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1269
1270     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1271     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1272     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1273
1274     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1275     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1276
1277     assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1278     assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1279
1280     assert_eq!("Α Σ".to_lowercase(), "α σ");
1281     assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1282     assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1283
1284     assert_eq!("Σ".to_lowercase(), "σ");
1285     assert_eq!("'Σ".to_lowercase(), "'σ");
1286     assert_eq!("''Σ".to_lowercase(), "''σ");
1287
1288     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1289     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1290     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1291 }
1292
1293 #[test]
1294 fn to_uppercase() {
1295     assert_eq!("".to_uppercase(), "");
1296     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1297 }
1298
1299 #[test]
1300 fn test_into_string() {
1301     // The only way to acquire a Box<str> in the first place is through a String, so just
1302     // test that we can round-trip between Box<str> and String.
1303     let string = String::from("Some text goes here");
1304     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1305 }
1306
1307 #[test]
1308 fn test_box_slice_clone() {
1309     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1310     let data2 = data.clone().into_boxed_str().clone().into_string();
1311
1312     assert_eq!(data, data2);
1313 }
1314
1315 #[test]
1316 fn test_cow_from() {
1317     let borrowed = "borrowed";
1318     let owned = String::from("owned");
1319     match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1320         (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1321         _ => panic!("invalid `Cow::from`"),
1322     }
1323 }
1324
1325 #[test]
1326 fn test_repeat() {
1327     assert_eq!("".repeat(3), "");
1328     assert_eq!("abc".repeat(0), "");
1329     assert_eq!("α".repeat(3), "ααα");
1330 }
1331
1332 mod pattern {
1333     use std::str::pattern::Pattern;
1334     use std::str::pattern::{Searcher, ReverseSearcher};
1335     use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1336
1337     macro_rules! make_test {
1338         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1339             #[allow(unused_imports)]
1340             mod $name {
1341                 use std::str::pattern::SearchStep::{Match, Reject};
1342                 use super::{cmp_search_to_vec};
1343                 #[test]
1344                 fn fwd() {
1345                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1346                 }
1347                 #[test]
1348                 fn bwd() {
1349                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1350                 }
1351             }
1352         }
1353     }
1354
1355     fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1356                                              right: Vec<SearchStep>)
1357     where P::Searcher: ReverseSearcher<'a>
1358     {
1359         let mut searcher = pat.into_searcher(haystack);
1360         let mut v = vec![];
1361         loop {
1362             match if !rev {searcher.next()} else {searcher.next_back()} {
1363                 Match(a, b) => v.push(Match(a, b)),
1364                 Reject(a, b) => v.push(Reject(a, b)),
1365                 Done => break,
1366             }
1367         }
1368         if rev {
1369             v.reverse();
1370         }
1371
1372         let mut first_index = 0;
1373         let mut err = None;
1374
1375         for (i, e) in right.iter().enumerate() {
1376             match *e {
1377                 Match(a, b) | Reject(a, b)
1378                 if a <= b && a == first_index => {
1379                     first_index = b;
1380                 }
1381                 _ => {
1382                     err = Some(i);
1383                     break;
1384                 }
1385             }
1386         }
1387
1388         if let Some(err) = err {
1389             panic!("Input skipped range at {}", err);
1390         }
1391
1392         if first_index != haystack.len() {
1393             panic!("Did not cover whole input");
1394         }
1395
1396         assert_eq!(v, right);
1397     }
1398
1399     make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1400         Reject(0, 1),
1401         Match (1, 3),
1402         Reject(3, 4),
1403         Match (4, 6),
1404         Reject(6, 7),
1405     ]);
1406     make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1407         Reject(0, 1),
1408         Match (1, 3),
1409         Reject(3, 4),
1410         Match (4, 6),
1411         Match (6, 8),
1412         Reject(8, 9),
1413     ]);
1414     make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1415         Match (0, 0),
1416         Reject(0, 1),
1417         Match (1, 1),
1418         Reject(1, 2),
1419         Match (2, 2),
1420         Reject(2, 3),
1421         Match (3, 3),
1422         Reject(3, 4),
1423         Match (4, 4),
1424         Reject(4, 5),
1425         Match (5, 5),
1426         Reject(5, 6),
1427         Match (6, 6),
1428         Reject(6, 7),
1429         Match (7, 7),
1430     ]);
1431     make_test!(str_searcher_mulibyte_haystack, " ", "├──", [
1432         Reject(0, 3),
1433         Reject(3, 6),
1434         Reject(6, 9),
1435     ]);
1436     make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [
1437         Match (0, 0),
1438         Reject(0, 3),
1439         Match (3, 3),
1440         Reject(3, 6),
1441         Match (6, 6),
1442         Reject(6, 9),
1443         Match (9, 9),
1444     ]);
1445     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1446         Match(0, 0),
1447     ]);
1448     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1449     ]);
1450     make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1451         Reject(0, 1),
1452         Match (1, 2),
1453         Match (2, 3),
1454         Reject(3, 4),
1455         Match (4, 5),
1456         Match (5, 6),
1457         Reject(6, 7),
1458     ]);
1459     make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [
1460         Reject(0, 3),
1461         Reject(3, 6),
1462         Reject(6, 9),
1463     ]);
1464     make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1465         Reject(0, 1),
1466         Reject(1, 2),
1467         Reject(2, 3),
1468     ]);
1469
1470 }
1471
1472 macro_rules! generate_iterator_test {
1473     {
1474         $name:ident {
1475             $(
1476                 ($($arg:expr),*) -> [$($t:tt)*];
1477             )*
1478         }
1479         with $fwd:expr, $bwd:expr;
1480     } => {
1481         #[test]
1482         fn $name() {
1483             $(
1484                 {
1485                     let res = vec![$($t)*];
1486
1487                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1488                     assert_eq!(fwd_vec, res);
1489
1490                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1491                     bwd_vec.reverse();
1492                     assert_eq!(bwd_vec, res);
1493                 }
1494             )*
1495         }
1496     };
1497     {
1498         $name:ident {
1499             $(
1500                 ($($arg:expr),*) -> [$($t:tt)*];
1501             )*
1502         }
1503         with $fwd:expr;
1504     } => {
1505         #[test]
1506         fn $name() {
1507             $(
1508                 {
1509                     let res = vec![$($t)*];
1510
1511                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1512                     assert_eq!(fwd_vec, res);
1513                 }
1514             )*
1515         }
1516     }
1517 }
1518
1519 generate_iterator_test! {
1520     double_ended_split {
1521         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1522         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1523     }
1524     with str::split, str::rsplit;
1525 }
1526
1527 generate_iterator_test! {
1528     double_ended_split_terminator {
1529         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1530     }
1531     with str::split_terminator, str::rsplit_terminator;
1532 }
1533
1534 generate_iterator_test! {
1535     double_ended_matches {
1536         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1537     }
1538     with str::matches, str::rmatches;
1539 }
1540
1541 generate_iterator_test! {
1542     double_ended_match_indices {
1543         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1544     }
1545     with str::match_indices, str::rmatch_indices;
1546 }
1547
1548 generate_iterator_test! {
1549     not_double_ended_splitn {
1550         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1551     }
1552     with str::splitn;
1553 }
1554
1555 generate_iterator_test! {
1556     not_double_ended_rsplitn {
1557         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1558     }
1559     with str::rsplitn;
1560 }
1561
1562 #[test]
1563 fn different_str_pattern_forwarding_lifetimes() {
1564     use std::str::pattern::Pattern;
1565
1566     fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
1567         for _ in 0..3 {
1568             "asdf".find(&p);
1569         }
1570     }
1571
1572     foo::<&str>("x");
1573 }