]> git.lizzy.rs Git - rust.git/blob - src/libcollections/tests/str.rs
Rollup merge of #42408 - bjorn3:patch-2, r=michaelwoerister
[rust.git] / src / libcollections / 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
362 #[test]
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);
374         }
375     }
376 }
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.";
383
384 // check the panic includes the prefix of the sliced string
385 #[test]
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];
389 }
390 // check the truncation in the panic message
391 #[test]
392 #[should_panic(expected="luctus, im`[...]")]
393 fn test_slice_fail_truncated_2() {
394     &LOREM_PARAGRAPH[..1024];
395 }
396
397 #[test]
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() {
400     &"abcαβγ"[4..];
401 }
402
403 #[test]
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() {
406     &"abcαβγ"[2..6];
407 }
408
409 #[test]
410 fn test_slice_from() {
411     assert_eq!(&"abcd"[0..], "abcd");
412     assert_eq!(&"abcd"[2..], "cd");
413     assert_eq!(&"abcd"[4..], "");
414 }
415 #[test]
416 fn test_slice_to() {
417     assert_eq!(&"abcd"[..0], "");
418     assert_eq!(&"abcd"[..2], "ab");
419     assert_eq!(&"abcd"[..4], "abcd");
420 }
421
422 #[test]
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 *** ");
430
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");
435 }
436
437 #[test]
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");
445
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");
450 }
451
452 #[test]
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");
460
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");
465 }
466
467 #[test]
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 ");
475 }
476
477 #[test]
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");
485 }
486
487 #[test]
488 fn test_trim() {
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");
495 }
496
497 #[test]
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()));
504 }
505
506 #[test]
507 fn test_is_utf8() {
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());
516
517     // deny surrogates
518     assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
519     assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
520
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());
529 }
530
531 #[test]
532 fn from_utf8_mostly_ascii() {
533     // deny invalid bytes embedded in long stretches of ascii
534     for i in 32..64 {
535         let mut data = [0; 128];
536         data[i] = 0xC0;
537         assert!(from_utf8(&data).is_err());
538         data[i] = 0xC2;
539         assert!(from_utf8(&data).is_err());
540     }
541 }
542
543 #[test]
544 fn from_utf8_error() {
545     macro_rules! test {
546         ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
547             let error = from_utf8($input).unwrap_err();
548             assert_eq!(error.valid_up_to(), $expected_valid_up_to);
549             assert_eq!(error.error_len(), $expected_error_len);
550         }
551     }
552     test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
553     test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
554     test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
555     test!(b"A\xC3\xA9 \xC1", 4, Some(1));
556     test!(b"A\xC3\xA9 \xC2", 4, None);
557     test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
558     test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
559     test!(b"A\xC3\xA9 \xE0", 4, None);
560     test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
561     test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
562     test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
563     test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
564     test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
565     test!(b"A\xC3\xA9 \xF1", 4, None);
566     test!(b"A\xC3\xA9 \xF1\x80", 4, None);
567     test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
568     test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
569     test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
570     test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
571 }
572
573 #[test]
574 fn test_as_bytes() {
575     // no null
576     let v = [
577         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
578         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
579         109
580     ];
581     let b: &[u8] = &[];
582     assert_eq!("".as_bytes(), b);
583     assert_eq!("abc".as_bytes(), b"abc");
584     assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
585 }
586
587 #[test]
588 #[should_panic]
589 fn test_as_bytes_fail() {
590     // Don't double free. (I'm not sure if this exercises the
591     // original problem code path anymore.)
592     let s = String::from("");
593     let _bytes = s.as_bytes();
594     panic!();
595 }
596
597 #[test]
598 fn test_as_ptr() {
599     let buf = "hello".as_ptr();
600     unsafe {
601         assert_eq!(*buf.offset(0), b'h');
602         assert_eq!(*buf.offset(1), b'e');
603         assert_eq!(*buf.offset(2), b'l');
604         assert_eq!(*buf.offset(3), b'l');
605         assert_eq!(*buf.offset(4), b'o');
606     }
607 }
608
609 #[test]
610 fn vec_str_conversions() {
611     let s1: String = String::from("All mimsy were the borogoves");
612
613     let v: Vec<u8> = s1.as_bytes().to_vec();
614     let s2: String = String::from(from_utf8(&v).unwrap());
615     let mut i = 0;
616     let n1 = s1.len();
617     let n2 = v.len();
618     assert_eq!(n1, n2);
619     while i < n1 {
620         let a: u8 = s1.as_bytes()[i];
621         let b: u8 = s2.as_bytes()[i];
622         assert_eq!(a, b);
623         i += 1;
624     }
625 }
626
627 #[test]
628 fn test_contains() {
629     assert!("abcde".contains("bcd"));
630     assert!("abcde".contains("abcd"));
631     assert!("abcde".contains("bcde"));
632     assert!("abcde".contains(""));
633     assert!("".contains(""));
634     assert!(!"abcde".contains("def"));
635     assert!(!"".contains("a"));
636
637     let data = "ประเทศไทย中华Việt Nam";
638     assert!(data.contains("ประเ"));
639     assert!(data.contains("ะเ"));
640     assert!(data.contains("中华"));
641     assert!(!data.contains("ไท华"));
642 }
643
644 #[test]
645 fn test_contains_char() {
646     assert!("abc".contains('b'));
647     assert!("a".contains('a'));
648     assert!(!"abc".contains('d'));
649     assert!(!"".contains('a'));
650 }
651
652 #[test]
653 fn test_split_at() {
654     let s = "ศไทย中华Việt Nam";
655     for (index, _) in s.char_indices() {
656         let (a, b) = s.split_at(index);
657         assert_eq!(&s[..a.len()], a);
658         assert_eq!(&s[a.len()..], b);
659     }
660     let (a, b) = s.split_at(s.len());
661     assert_eq!(a, s);
662     assert_eq!(b, "");
663 }
664
665 #[test]
666 fn test_split_at_mut() {
667     use std::ascii::AsciiExt;
668     let mut s = "Hello World".to_string();
669     {
670         let (a, b) = s.split_at_mut(5);
671         a.make_ascii_uppercase();
672         b.make_ascii_lowercase();
673     }
674     assert_eq!(s, "HELLO world");
675 }
676
677 #[test]
678 #[should_panic]
679 fn test_split_at_boundscheck() {
680     let s = "ศไทย中华Việt Nam";
681     s.split_at(1);
682 }
683
684 #[test]
685 fn test_escape_unicode() {
686     assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
687     assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
688     assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
689     assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
690     assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
691     assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
692     assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
693     assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
694     assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
695 }
696
697 #[test]
698 fn test_escape_debug() {
699     assert_eq!("abc".escape_debug(), "abc");
700     assert_eq!("a c".escape_debug(), "a c");
701     assert_eq!("éèê".escape_debug(), "éèê");
702     assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
703     assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
704     assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
705     assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
706     assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
707     assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
708     assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
709 }
710
711 #[test]
712 fn test_escape_default() {
713     assert_eq!("abc".escape_default(), "abc");
714     assert_eq!("a c".escape_default(), "a c");
715     assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
716     assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
717     assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
718     assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
719     assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
720     assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
721     assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
722     assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
723 }
724
725 #[test]
726 fn test_total_ord() {
727     assert_eq!("1234".cmp("123"), Greater);
728     assert_eq!("123".cmp("1234"), Less);
729     assert_eq!("1234".cmp("1234"), Equal);
730     assert_eq!("12345555".cmp("123456"), Less);
731     assert_eq!("22".cmp("1234"), Greater);
732 }
733
734 #[test]
735 fn test_iterator() {
736     let s = "ศไทย中华Việt Nam";
737     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
738
739     let mut pos = 0;
740     let it = s.chars();
741
742     for c in it {
743         assert_eq!(c, v[pos]);
744         pos += 1;
745     }
746     assert_eq!(pos, v.len());
747     assert_eq!(s.chars().count(), v.len());
748 }
749
750 #[test]
751 fn test_rev_iterator() {
752     let s = "ศไทย中华Việt Nam";
753     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
754
755     let mut pos = 0;
756     let it = s.chars().rev();
757
758     for c in it {
759         assert_eq!(c, v[pos]);
760         pos += 1;
761     }
762     assert_eq!(pos, v.len());
763 }
764
765 #[test]
766 fn test_chars_decoding() {
767     let mut bytes = [0; 4];
768     for c in (0..0x110000).filter_map(::std::char::from_u32) {
769         let s = c.encode_utf8(&mut bytes);
770         if Some(c) != s.chars().next() {
771             panic!("character {:x}={} does not decode correctly", c as u32, c);
772         }
773     }
774 }
775
776 #[test]
777 fn test_chars_rev_decoding() {
778     let mut bytes = [0; 4];
779     for c in (0..0x110000).filter_map(::std::char::from_u32) {
780         let s = c.encode_utf8(&mut bytes);
781         if Some(c) != s.chars().rev().next() {
782             panic!("character {:x}={} does not decode correctly", c as u32, c);
783         }
784     }
785 }
786
787 #[test]
788 fn test_iterator_clone() {
789     let s = "ศไทย中华Việt Nam";
790     let mut it = s.chars();
791     it.next();
792     assert!(it.clone().zip(it).all(|(x,y)| x == y));
793 }
794
795 #[test]
796 fn test_iterator_last() {
797     let s = "ศไทย中华Việt Nam";
798     let mut it = s.chars();
799     it.next();
800     assert_eq!(it.last(), Some('m'));
801 }
802
803 #[test]
804 fn test_bytesator() {
805     let s = "ศไทย中华Việt Nam";
806     let v = [
807         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
808         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
809         109
810     ];
811     let mut pos = 0;
812
813     for b in s.bytes() {
814         assert_eq!(b, v[pos]);
815         pos += 1;
816     }
817 }
818
819 #[test]
820 fn test_bytes_revator() {
821     let s = "ศไทย中华Việt Nam";
822     let v = [
823         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
824         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
825         109
826     ];
827     let mut pos = v.len();
828
829     for b in s.bytes().rev() {
830         pos -= 1;
831         assert_eq!(b, v[pos]);
832     }
833 }
834
835 #[test]
836 fn test_bytesator_nth() {
837     let s = "ศไทย中华Việt Nam";
838     let v = [
839         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
840         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
841         109
842     ];
843
844     let mut b = s.bytes();
845     assert_eq!(b.nth(2).unwrap(), v[2]);
846     assert_eq!(b.nth(10).unwrap(), v[10]);
847     assert_eq!(b.nth(200), None);
848 }
849
850 #[test]
851 fn test_bytesator_count() {
852     let s = "ศไทย中华Việt Nam";
853
854     let b = s.bytes();
855     assert_eq!(b.count(), 28)
856 }
857
858 #[test]
859 fn test_bytesator_last() {
860     let s = "ศไทย中华Việt Nam";
861
862     let b = s.bytes();
863     assert_eq!(b.last().unwrap(), 109)
864 }
865
866 #[test]
867 fn test_char_indicesator() {
868     let s = "ศไทย中华Việt Nam";
869     let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
870     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
871
872     let mut pos = 0;
873     let it = s.char_indices();
874
875     for c in it {
876         assert_eq!(c, (p[pos], v[pos]));
877         pos += 1;
878     }
879     assert_eq!(pos, v.len());
880     assert_eq!(pos, p.len());
881 }
882
883 #[test]
884 fn test_char_indices_revator() {
885     let s = "ศไทย中华Việt Nam";
886     let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
887     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
888
889     let mut pos = 0;
890     let it = s.char_indices().rev();
891
892     for c in it {
893         assert_eq!(c, (p[pos], v[pos]));
894         pos += 1;
895     }
896     assert_eq!(pos, v.len());
897     assert_eq!(pos, p.len());
898 }
899
900 #[test]
901 fn test_char_indices_last() {
902     let s = "ศไทย中华Việt Nam";
903     let mut it = s.char_indices();
904     it.next();
905     assert_eq!(it.last(), Some((27, 'm')));
906 }
907
908 #[test]
909 fn test_splitn_char_iterator() {
910     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
911
912     let split: Vec<&str> = data.splitn(4, ' ').collect();
913     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
914
915     let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
916     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
917
918     // Unicode
919     let split: Vec<&str> = data.splitn(4, 'ä').collect();
920     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
921
922     let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
923     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
924 }
925
926 #[test]
927 fn test_split_char_iterator_no_trailing() {
928     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
929
930     let split: Vec<&str> = data.split('\n').collect();
931     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
932
933     let split: Vec<&str> = data.split_terminator('\n').collect();
934     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
935 }
936
937 #[test]
938 fn test_rsplit() {
939     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
940
941     let split: Vec<&str> = data.rsplit(' ').collect();
942     assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
943
944     let split: Vec<&str> = data.rsplit("lämb").collect();
945     assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
946
947     let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
948     assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
949 }
950
951 #[test]
952 fn test_rsplitn() {
953     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
954
955     let split: Vec<&str> = data.rsplitn(2, ' ').collect();
956     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
957
958     let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
959     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
960
961     let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
962     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
963 }
964
965 #[test]
966 fn test_split_whitespace() {
967     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
968     let words: Vec<&str> = data.split_whitespace().collect();
969     assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
970 }
971
972 #[test]
973 fn test_lines() {
974     let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
975     let lines: Vec<&str> = data.lines().collect();
976     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
977
978     let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
979     let lines: Vec<&str> = data.lines().collect();
980     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
981 }
982
983 #[test]
984 fn test_splitator() {
985     fn t(s: &str, sep: &str, u: &[&str]) {
986         let v: Vec<&str> = s.split(sep).collect();
987         assert_eq!(v, u);
988     }
989     t("--1233345--", "12345", &["--1233345--"]);
990     t("abc::hello::there", "::", &["abc", "hello", "there"]);
991     t("::hello::there", "::", &["", "hello", "there"]);
992     t("hello::there::", "::", &["hello", "there", ""]);
993     t("::hello::there::", "::", &["", "hello", "there", ""]);
994     t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
995     t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
996     t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
997     t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
998     t("", ".", &[""]);
999     t("zz", "zz", &["",""]);
1000     t("ok", "z", &["ok"]);
1001     t("zzz", "zz", &["","z"]);
1002     t("zzzzz", "zz", &["","","z"]);
1003 }
1004
1005 #[test]
1006 fn test_str_default() {
1007     use std::default::Default;
1008
1009     fn t<S: Default + AsRef<str>>() {
1010         let s: S = Default::default();
1011         assert_eq!(s.as_ref(), "");
1012     }
1013
1014     t::<&str>();
1015     t::<String>();
1016 }
1017
1018 #[test]
1019 fn test_str_container() {
1020     fn sum_len(v: &[&str]) -> usize {
1021         v.iter().map(|x| x.len()).sum()
1022     }
1023
1024     let s = "01234";
1025     assert_eq!(5, sum_len(&["012", "", "34"]));
1026     assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1027     assert_eq!(5, sum_len(&[s]));
1028 }
1029
1030 #[test]
1031 fn test_str_from_utf8() {
1032     let xs = b"hello";
1033     assert_eq!(from_utf8(xs), Ok("hello"));
1034
1035     let xs = "ศไทย中华Việt Nam".as_bytes();
1036     assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1037
1038     let xs = b"hello\xFF";
1039     assert!(from_utf8(xs).is_err());
1040 }
1041
1042 #[test]
1043 fn test_pattern_deref_forward() {
1044     let data = "aabcdaa";
1045     assert!(data.contains("bcd"));
1046     assert!(data.contains(&"bcd"));
1047     assert!(data.contains(&"bcd".to_string()));
1048 }
1049
1050 #[test]
1051 fn test_empty_match_indices() {
1052     let data = "aä中!";
1053     let vec: Vec<_> = data.match_indices("").collect();
1054     assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1055 }
1056
1057 #[test]
1058 fn test_bool_from_str() {
1059     assert_eq!("true".parse().ok(), Some(true));
1060     assert_eq!("false".parse().ok(), Some(false));
1061     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1062 }
1063
1064 fn check_contains_all_substrings(s: &str) {
1065     assert!(s.contains(""));
1066     for i in 0..s.len() {
1067         for j in i+1..s.len() + 1 {
1068             assert!(s.contains(&s[i..j]));
1069         }
1070     }
1071 }
1072
1073 #[test]
1074 fn strslice_issue_16589() {
1075     assert!("bananas".contains("nana"));
1076
1077     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1078     // test all substrings for good measure
1079     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1080 }
1081
1082 #[test]
1083 fn strslice_issue_16878() {
1084     assert!(!"1234567ah012345678901ah".contains("hah"));
1085     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1086 }
1087
1088
1089 #[test]
1090 fn test_strslice_contains() {
1091     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1092     check_contains_all_substrings(x);
1093 }
1094
1095 #[test]
1096 fn test_rsplitn_char_iterator() {
1097     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1098
1099     let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1100     split.reverse();
1101     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1102
1103     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1104     split.reverse();
1105     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1106
1107     // Unicode
1108     let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1109     split.reverse();
1110     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1111
1112     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1113     split.reverse();
1114     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1115 }
1116
1117 #[test]
1118 fn test_split_char_iterator() {
1119     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1120
1121     let split: Vec<&str> = data.split(' ').collect();
1122     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1123
1124     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1125     rsplit.reverse();
1126     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1127
1128     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1129     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1130
1131     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1132     rsplit.reverse();
1133     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1134
1135     // Unicode
1136     let split: Vec<&str> = data.split('ä').collect();
1137     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1138
1139     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1140     rsplit.reverse();
1141     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1142
1143     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1144     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1145
1146     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1147     rsplit.reverse();
1148     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1149 }
1150
1151 #[test]
1152 fn test_rev_split_char_iterator_no_trailing() {
1153     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1154
1155     let mut split: Vec<&str> = data.split('\n').rev().collect();
1156     split.reverse();
1157     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1158
1159     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1160     split.reverse();
1161     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1162 }
1163
1164 #[test]
1165 fn test_utf16_code_units() {
1166     use std_unicode::str::Utf16Encoder;
1167     assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
1168                [0xE9, 0xD83D, 0xDCA9])
1169 }
1170
1171 #[test]
1172 fn starts_with_in_unicode() {
1173     assert!(!"├── Cargo.toml".starts_with("# "));
1174 }
1175
1176 #[test]
1177 fn starts_short_long() {
1178     assert!(!"".starts_with("##"));
1179     assert!(!"##".starts_with("####"));
1180     assert!("####".starts_with("##"));
1181     assert!(!"##ä".starts_with("####"));
1182     assert!("####ä".starts_with("##"));
1183     assert!(!"##".starts_with("####ä"));
1184     assert!("##ä##".starts_with("##ä"));
1185
1186     assert!("".starts_with(""));
1187     assert!("ä".starts_with(""));
1188     assert!("#ä".starts_with(""));
1189     assert!("##ä".starts_with(""));
1190     assert!("ä###".starts_with(""));
1191     assert!("#ä##".starts_with(""));
1192     assert!("##ä#".starts_with(""));
1193 }
1194
1195 #[test]
1196 fn contains_weird_cases() {
1197     assert!("* \t".contains(' '));
1198     assert!(!"* \t".contains('?'));
1199     assert!(!"* \t".contains('\u{1F4A9}'));
1200 }
1201
1202 #[test]
1203 fn trim_ws() {
1204     assert_eq!(" \t  a \t  ".trim_left_matches(|c: char| c.is_whitespace()),
1205                     "a \t  ");
1206     assert_eq!(" \t  a \t  ".trim_right_matches(|c: char| c.is_whitespace()),
1207                " \t  a");
1208     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()),
1209                     "a");
1210     assert_eq!(" \t   \t  ".trim_left_matches(|c: char| c.is_whitespace()),
1211                          "");
1212     assert_eq!(" \t   \t  ".trim_right_matches(|c: char| c.is_whitespace()),
1213                "");
1214     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()),
1215                "");
1216 }
1217
1218 #[test]
1219 fn to_lowercase() {
1220     assert_eq!("".to_lowercase(), "");
1221     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1222
1223     // https://github.com/rust-lang/rust/issues/26035
1224     assert_eq!("ΑΣ".to_lowercase(), "ας");
1225     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1226     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1227
1228     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1229     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1230     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1231
1232     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1233     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1234
1235     assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1236     assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1237
1238     assert_eq!("Α Σ".to_lowercase(), "α σ");
1239     assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1240     assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1241
1242     assert_eq!("Σ".to_lowercase(), "σ");
1243     assert_eq!("'Σ".to_lowercase(), "'σ");
1244     assert_eq!("''Σ".to_lowercase(), "''σ");
1245
1246     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1247     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1248     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1249 }
1250
1251 #[test]
1252 fn to_uppercase() {
1253     assert_eq!("".to_uppercase(), "");
1254     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1255 }
1256
1257 #[test]
1258 fn test_into_string() {
1259     // The only way to acquire a Box<str> in the first place is through a String, so just
1260     // test that we can round-trip between Box<str> and String.
1261     let string = String::from("Some text goes here");
1262     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1263 }
1264
1265 #[test]
1266 fn test_box_slice_clone() {
1267     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1268     let data2 = data.clone().into_boxed_str().clone().into_string();
1269
1270     assert_eq!(data, data2);
1271 }
1272
1273 #[test]
1274 fn test_cow_from() {
1275     let borrowed = "borrowed";
1276     let owned = String::from("owned");
1277     match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1278         (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1279         _ => panic!("invalid `Cow::from`"),
1280     }
1281 }
1282
1283 #[test]
1284 fn test_repeat() {
1285     assert_eq!("".repeat(3), "");
1286     assert_eq!("abc".repeat(0), "");
1287     assert_eq!("α".repeat(3), "ααα");
1288 }
1289
1290 mod pattern {
1291     use std::str::pattern::Pattern;
1292     use std::str::pattern::{Searcher, ReverseSearcher};
1293     use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1294
1295     macro_rules! make_test {
1296         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1297             #[allow(unused_imports)]
1298             mod $name {
1299                 use std::str::pattern::SearchStep::{Match, Reject};
1300                 use super::{cmp_search_to_vec};
1301                 #[test]
1302                 fn fwd() {
1303                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1304                 }
1305                 #[test]
1306                 fn bwd() {
1307                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1308                 }
1309             }
1310         }
1311     }
1312
1313     fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1314                                              right: Vec<SearchStep>)
1315     where P::Searcher: ReverseSearcher<'a>
1316     {
1317         let mut searcher = pat.into_searcher(haystack);
1318         let mut v = vec![];
1319         loop {
1320             match if !rev {searcher.next()} else {searcher.next_back()} {
1321                 Match(a, b) => v.push(Match(a, b)),
1322                 Reject(a, b) => v.push(Reject(a, b)),
1323                 Done => break,
1324             }
1325         }
1326         if rev {
1327             v.reverse();
1328         }
1329
1330         let mut first_index = 0;
1331         let mut err = None;
1332
1333         for (i, e) in right.iter().enumerate() {
1334             match *e {
1335                 Match(a, b) | Reject(a, b)
1336                 if a <= b && a == first_index => {
1337                     first_index = b;
1338                 }
1339                 _ => {
1340                     err = Some(i);
1341                     break;
1342                 }
1343             }
1344         }
1345
1346         if let Some(err) = err {
1347             panic!("Input skipped range at {}", err);
1348         }
1349
1350         if first_index != haystack.len() {
1351             panic!("Did not cover whole input");
1352         }
1353
1354         assert_eq!(v, right);
1355     }
1356
1357     make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1358         Reject(0, 1),
1359         Match (1, 3),
1360         Reject(3, 4),
1361         Match (4, 6),
1362         Reject(6, 7),
1363     ]);
1364     make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1365         Reject(0, 1),
1366         Match (1, 3),
1367         Reject(3, 4),
1368         Match (4, 6),
1369         Match (6, 8),
1370         Reject(8, 9),
1371     ]);
1372     make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1373         Match (0, 0),
1374         Reject(0, 1),
1375         Match (1, 1),
1376         Reject(1, 2),
1377         Match (2, 2),
1378         Reject(2, 3),
1379         Match (3, 3),
1380         Reject(3, 4),
1381         Match (4, 4),
1382         Reject(4, 5),
1383         Match (5, 5),
1384         Reject(5, 6),
1385         Match (6, 6),
1386         Reject(6, 7),
1387         Match (7, 7),
1388     ]);
1389     make_test!(str_searcher_mulibyte_haystack, " ", "├──", [
1390         Reject(0, 3),
1391         Reject(3, 6),
1392         Reject(6, 9),
1393     ]);
1394     make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [
1395         Match (0, 0),
1396         Reject(0, 3),
1397         Match (3, 3),
1398         Reject(3, 6),
1399         Match (6, 6),
1400         Reject(6, 9),
1401         Match (9, 9),
1402     ]);
1403     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1404         Match(0, 0),
1405     ]);
1406     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1407     ]);
1408     make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1409         Reject(0, 1),
1410         Match (1, 2),
1411         Match (2, 3),
1412         Reject(3, 4),
1413         Match (4, 5),
1414         Match (5, 6),
1415         Reject(6, 7),
1416     ]);
1417     make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [
1418         Reject(0, 3),
1419         Reject(3, 6),
1420         Reject(6, 9),
1421     ]);
1422     make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1423         Reject(0, 1),
1424         Reject(1, 2),
1425         Reject(2, 3),
1426     ]);
1427
1428 }
1429
1430 macro_rules! generate_iterator_test {
1431     {
1432         $name:ident {
1433             $(
1434                 ($($arg:expr),*) -> [$($t:tt)*];
1435             )*
1436         }
1437         with $fwd:expr, $bwd:expr;
1438     } => {
1439         #[test]
1440         fn $name() {
1441             $(
1442                 {
1443                     let res = vec![$($t)*];
1444
1445                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1446                     assert_eq!(fwd_vec, res);
1447
1448                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1449                     bwd_vec.reverse();
1450                     assert_eq!(bwd_vec, res);
1451                 }
1452             )*
1453         }
1454     };
1455     {
1456         $name:ident {
1457             $(
1458                 ($($arg:expr),*) -> [$($t:tt)*];
1459             )*
1460         }
1461         with $fwd:expr;
1462     } => {
1463         #[test]
1464         fn $name() {
1465             $(
1466                 {
1467                     let res = vec![$($t)*];
1468
1469                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1470                     assert_eq!(fwd_vec, res);
1471                 }
1472             )*
1473         }
1474     }
1475 }
1476
1477 generate_iterator_test! {
1478     double_ended_split {
1479         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1480         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1481     }
1482     with str::split, str::rsplit;
1483 }
1484
1485 generate_iterator_test! {
1486     double_ended_split_terminator {
1487         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1488     }
1489     with str::split_terminator, str::rsplit_terminator;
1490 }
1491
1492 generate_iterator_test! {
1493     double_ended_matches {
1494         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1495     }
1496     with str::matches, str::rmatches;
1497 }
1498
1499 generate_iterator_test! {
1500     double_ended_match_indices {
1501         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1502     }
1503     with str::match_indices, str::rmatch_indices;
1504 }
1505
1506 generate_iterator_test! {
1507     not_double_ended_splitn {
1508         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1509     }
1510     with str::splitn;
1511 }
1512
1513 generate_iterator_test! {
1514     not_double_ended_rsplitn {
1515         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1516     }
1517     with str::rsplitn;
1518 }
1519
1520 #[test]
1521 fn different_str_pattern_forwarding_lifetimes() {
1522     use std::str::pattern::Pattern;
1523
1524     fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
1525         for _ in 0..3 {
1526             "asdf".find(&p);
1527         }
1528     }
1529
1530     foo::<&str>("x");
1531 }