]> git.lizzy.rs Git - rust.git/blob - src/libcollectionstest/str.rs
Auto merge of #26848 - oli-obk:const_fn_const_eval, r=pnkfelix
[rust.git] / src / libcollectionstest / 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::cmp::Ordering::{Equal, Greater, Less};
12 use std::str::from_utf8;
13
14 #[test]
15 fn test_le() {
16     assert!("" <= "");
17     assert!("" <= "foo");
18     assert!("foo" <= "foo");
19     assert!("foo" != "bar");
20 }
21
22 #[test]
23 fn test_find() {
24     assert_eq!("hello".find('l'), Some(2));
25     assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
26     assert!("hello".find('x').is_none());
27     assert!("hello".find(|c:char| c == 'x').is_none());
28     assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
29     assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
30 }
31
32 #[test]
33 fn test_rfind() {
34     assert_eq!("hello".rfind('l'), Some(3));
35     assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
36     assert!("hello".rfind('x').is_none());
37     assert!("hello".rfind(|c:char| c == 'x').is_none());
38     assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
39     assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
40 }
41
42 #[test]
43 fn test_collect() {
44     let empty = "";
45     let s: String = empty.chars().collect();
46     assert_eq!(empty, s);
47     let data = "ประเทศไทย中";
48     let s: String = data.chars().collect();
49     assert_eq!(data, s);
50 }
51
52 #[test]
53 fn test_into_bytes() {
54     let data = String::from("asdf");
55     let buf = data.into_bytes();
56     assert_eq!(buf, b"asdf");
57 }
58
59 #[test]
60 fn test_find_str() {
61     // byte positions
62     assert_eq!("".find(""), Some(0));
63     assert!("banana".find("apple pie").is_none());
64
65     let data = "abcabc";
66     assert_eq!(data[0..6].find("ab"), Some(0));
67     assert_eq!(data[2..6].find("ab"), Some(3 - 2));
68     assert!(data[2..4].find("ab").is_none());
69
70     let string = "ประเทศไทย中华Việt Nam";
71     let mut data = String::from(string);
72     data.push_str(string);
73     assert!(data.find("ไท华").is_none());
74     assert_eq!(data[0..43].find(""), Some(0));
75     assert_eq!(data[6..43].find(""), Some(6 - 6));
76
77     assert_eq!(data[0..43].find("ประ"), Some( 0));
78     assert_eq!(data[0..43].find("ทศไ"), Some(12));
79     assert_eq!(data[0..43].find("ย中"), Some(24));
80     assert_eq!(data[0..43].find("iệt"), Some(34));
81     assert_eq!(data[0..43].find("Nam"), Some(40));
82
83     assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
84     assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
85     assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
86     assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
87     assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
88
89     // find every substring -- assert that it finds it, or an earlier occurrence.
90     let string = "Việt Namacbaabcaabaaba";
91     for (i, ci) in string.char_indices() {
92         let ip = i + ci.len_utf8();
93         for j in string[ip..].char_indices()
94                              .map(|(i, _)| i)
95                              .chain(Some(string.len() - ip))
96         {
97             let pat = &string[i..ip + j];
98             assert!(match string.find(pat) {
99                 None => false,
100                 Some(x) => x <= i,
101             });
102             assert!(match string.rfind(pat) {
103                 None => false,
104                 Some(x) => x >= i,
105             });
106         }
107     }
108 }
109
110 fn s(x: &str) -> String { x.to_string() }
111
112 macro_rules! test_concat {
113     ($expected: expr, $string: expr) => {
114         {
115             let s: String = $string.concat();
116             assert_eq!($expected, s);
117         }
118     }
119 }
120
121 #[test]
122 fn test_concat_for_different_types() {
123     test_concat!("ab", vec![s("a"), s("b")]);
124     test_concat!("ab", vec!["a", "b"]);
125     test_concat!("ab", vec!["a", "b"]);
126     test_concat!("ab", vec![s("a"), s("b")]);
127 }
128
129 #[test]
130 fn test_concat_for_different_lengths() {
131     let empty: &[&str] = &[];
132     test_concat!("", empty);
133     test_concat!("a", ["a"]);
134     test_concat!("ab", ["a", "b"]);
135     test_concat!("abc", ["", "a", "bc"]);
136 }
137
138 macro_rules! test_join {
139     ($expected: expr, $string: expr, $delim: expr) => {
140         {
141             let s = $string.join($delim);
142             assert_eq!($expected, s);
143         }
144     }
145 }
146
147 #[test]
148 fn test_join_for_different_types() {
149     test_join!("a-b", ["a", "b"], "-");
150     let hyphen = "-".to_string();
151     test_join!("a-b", [s("a"), s("b")], &*hyphen);
152     test_join!("a-b", vec!["a", "b"], &*hyphen);
153     test_join!("a-b", &*vec!["a", "b"], "-");
154     test_join!("a-b", vec![s("a"), s("b")], "-");
155 }
156
157 #[test]
158 fn test_join_for_different_lengths() {
159     let empty: &[&str] = &[];
160     test_join!("", empty, "-");
161     test_join!("a", ["a"], "-");
162     test_join!("a-b", ["a", "b"], "-");
163     test_join!("-a-bc", ["", "a", "bc"], "-");
164 }
165
166 #[test]
167 fn test_unsafe_slice() {
168     assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)});
169     assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)});
170     assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)});
171     fn a_million_letter_a() -> String {
172         let mut i = 0;
173         let mut rs = String::new();
174         while i < 100000 {
175             rs.push_str("aaaaaaaaaa");
176             i += 1;
177         }
178         rs
179     }
180     fn half_a_million_letter_a() -> String {
181         let mut i = 0;
182         let mut rs = String::new();
183         while i < 100000 {
184             rs.push_str("aaaaa");
185             i += 1;
186         }
187         rs
188     }
189     let letters = a_million_letter_a();
190     assert_eq!(half_a_million_letter_a(),
191         unsafe { letters.slice_unchecked(0, 500000)});
192 }
193
194 #[test]
195 fn test_starts_with() {
196     assert!(("".starts_with("")));
197     assert!(("abc".starts_with("")));
198     assert!(("abc".starts_with("a")));
199     assert!((!"a".starts_with("abc")));
200     assert!((!"".starts_with("abc")));
201     assert!((!"ödd".starts_with("-")));
202     assert!(("ödd".starts_with("öd")));
203 }
204
205 #[test]
206 fn test_ends_with() {
207     assert!(("".ends_with("")));
208     assert!(("abc".ends_with("")));
209     assert!(("abc".ends_with("c")));
210     assert!((!"a".ends_with("abc")));
211     assert!((!"".ends_with("abc")));
212     assert!((!"ddö".ends_with("-")));
213     assert!(("ddö".ends_with("dö")));
214 }
215
216 #[test]
217 fn test_is_empty() {
218     assert!("".is_empty());
219     assert!(!"a".is_empty());
220 }
221
222 #[test]
223 fn test_replace() {
224     let a = "a";
225     assert_eq!("".replace(a, "b"), "");
226     assert_eq!("a".replace(a, "b"), "b");
227     assert_eq!("ab".replace(a, "b"), "bb");
228     let test = "test";
229     assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
230     assert_eq!(" test test ".replace(test, ""), "   ");
231 }
232
233 #[test]
234 fn test_replace_2a() {
235     let data = "ประเทศไทย中华";
236     let repl = "دولة الكويت";
237
238     let a = "ประเ";
239     let a2 = "دولة الكويتทศไทย中华";
240     assert_eq!(data.replace(a, repl), a2);
241 }
242
243 #[test]
244 fn test_replace_2b() {
245     let data = "ประเทศไทย中华";
246     let repl = "دولة الكويت";
247
248     let b = "ะเ";
249     let b2 = "ปรدولة الكويتทศไทย中华";
250     assert_eq!(data.replace(b, repl), b2);
251 }
252
253 #[test]
254 fn test_replace_2c() {
255     let data = "ประเทศไทย中华";
256     let repl = "دولة الكويت";
257
258     let c = "中华";
259     let c2 = "ประเทศไทยدولة الكويت";
260     assert_eq!(data.replace(c, repl), c2);
261 }
262
263 #[test]
264 fn test_replace_2d() {
265     let data = "ประเทศไทย中华";
266     let repl = "دولة الكويت";
267
268     let d = "ไท华";
269     assert_eq!(data.replace(d, repl), data);
270 }
271
272 #[test]
273 fn test_slice() {
274     assert_eq!("ab", &"abc"[0..2]);
275     assert_eq!("bc", &"abc"[1..3]);
276     assert_eq!("", &"abc"[1..1]);
277     assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]);
278
279     let data = "ประเทศไทย中华";
280     assert_eq!("ป", &data[0..3]);
281     assert_eq!("ร", &data[3..6]);
282     assert_eq!("", &data[3..3]);
283     assert_eq!("华", &data[30..33]);
284
285     fn a_million_letter_x() -> String {
286         let mut i = 0;
287         let mut rs = String::new();
288         while i < 100000 {
289             rs.push_str("华华华华华华华华华华");
290             i += 1;
291         }
292         rs
293     }
294     fn half_a_million_letter_x() -> String {
295         let mut i = 0;
296         let mut rs = String::new();
297         while i < 100000 {
298             rs.push_str("华华华华华");
299             i += 1;
300         }
301         rs
302     }
303     let letters = a_million_letter_x();
304     assert_eq!(half_a_million_letter_x(), &letters[0..3 * 500000]);
305 }
306
307 #[test]
308 fn test_slice_2() {
309     let ss = "中华Việt Nam";
310
311     assert_eq!("华", &ss[3..6]);
312     assert_eq!("Việt Nam", &ss[6..16]);
313
314     assert_eq!("ab", &"abc"[0..2]);
315     assert_eq!("bc", &"abc"[1..3]);
316     assert_eq!("", &"abc"[1..1]);
317
318     assert_eq!("中", &ss[0..3]);
319     assert_eq!("华V", &ss[3..7]);
320     assert_eq!("", &ss[3..3]);
321     /*0: 中
322       3: 华
323       6: V
324       7: i
325       8: ệ
326      11: t
327      12:
328      13: N
329      14: a
330      15: m */
331 }
332
333 #[test]
334 #[should_panic]
335 fn test_slice_fail() {
336     &"中华Việt Nam"[0..2];
337 }
338
339 #[test]
340 fn test_slice_from() {
341     assert_eq!(&"abcd"[0..], "abcd");
342     assert_eq!(&"abcd"[2..], "cd");
343     assert_eq!(&"abcd"[4..], "");
344 }
345 #[test]
346 fn test_slice_to() {
347     assert_eq!(&"abcd"[..0], "");
348     assert_eq!(&"abcd"[..2], "ab");
349     assert_eq!(&"abcd"[..4], "abcd");
350 }
351
352 #[test]
353 fn test_trim_left_matches() {
354     let v: &[char] = &[];
355     assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** ");
356     let chars: &[char] = &['*', ' '];
357     assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** ");
358     assert_eq!(" ***  *** ".trim_left_matches(chars), "");
359     assert_eq!("foo *** ".trim_left_matches(chars), "foo *** ");
360
361     assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
362     let chars: &[char] = &['1', '2'];
363     assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12");
364     assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
365 }
366
367 #[test]
368 fn test_trim_right_matches() {
369     let v: &[char] = &[];
370     assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** ");
371     let chars: &[char] = &['*', ' '];
372     assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo");
373     assert_eq!(" ***  *** ".trim_right_matches(chars), "");
374     assert_eq!(" *** foo".trim_right_matches(chars), " *** foo");
375
376     assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
377     let chars: &[char] = &['1', '2'];
378     assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar");
379     assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
380 }
381
382 #[test]
383 fn test_trim_matches() {
384     let v: &[char] = &[];
385     assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
386     let chars: &[char] = &['*', ' '];
387     assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
388     assert_eq!(" ***  *** ".trim_matches(chars), "");
389     assert_eq!("foo".trim_matches(chars), "foo");
390
391     assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
392     let chars: &[char] = &['1', '2'];
393     assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
394     assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
395 }
396
397 #[test]
398 fn test_trim_left() {
399     assert_eq!("".trim_left(), "");
400     assert_eq!("a".trim_left(), "a");
401     assert_eq!("    ".trim_left(), "");
402     assert_eq!("     blah".trim_left(), "blah");
403     assert_eq!("   \u{3000}  wut".trim_left(), "wut");
404     assert_eq!("hey ".trim_left(), "hey ");
405 }
406
407 #[test]
408 fn test_trim_right() {
409     assert_eq!("".trim_right(), "");
410     assert_eq!("a".trim_right(), "a");
411     assert_eq!("    ".trim_right(), "");
412     assert_eq!("blah     ".trim_right(), "blah");
413     assert_eq!("wut   \u{3000}  ".trim_right(), "wut");
414     assert_eq!(" hey".trim_right(), " hey");
415 }
416
417 #[test]
418 fn test_trim() {
419     assert_eq!("".trim(), "");
420     assert_eq!("a".trim(), "a");
421     assert_eq!("    ".trim(), "");
422     assert_eq!("    blah     ".trim(), "blah");
423     assert_eq!("\nwut   \u{3000}  ".trim(), "wut");
424     assert_eq!(" hey dude ".trim(), "hey dude");
425 }
426
427 #[test]
428 fn test_is_whitespace() {
429     assert!("".chars().all(|c| c.is_whitespace()));
430     assert!(" ".chars().all(|c| c.is_whitespace()));
431     assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
432     assert!("  \n\t   ".chars().all(|c| c.is_whitespace()));
433     assert!(!"   _   ".chars().all(|c| c.is_whitespace()));
434 }
435
436 #[test]
437 fn test_slice_shift_char() {
438     let data = "ประเทศไทย中";
439     assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中")));
440 }
441
442 #[test]
443 fn test_slice_shift_char_2() {
444     let empty = "";
445     assert_eq!(empty.slice_shift_char(), None);
446 }
447
448 #[test]
449 fn test_is_utf8() {
450     // deny overlong encodings
451     assert!(from_utf8(&[0xc0, 0x80]).is_err());
452     assert!(from_utf8(&[0xc0, 0xae]).is_err());
453     assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
454     assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
455     assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
456     assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
457     assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
458
459     // deny surrogates
460     assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
461     assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
462
463     assert!(from_utf8(&[0xC2, 0x80]).is_ok());
464     assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
465     assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
466     assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
467     assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
468     assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
469     assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
470     assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
471 }
472
473 #[test]
474 fn test_is_utf16() {
475     use rustc_unicode::str::is_utf16;
476
477     macro_rules! pos {
478         ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } }
479     }
480
481     // non-surrogates
482     pos!(&[0x0000],
483          &[0x0001, 0x0002],
484          &[0xD7FF],
485          &[0xE000]);
486
487     // surrogate pairs (randomly generated with Python 3's
488     // .encode('utf-16be'))
489     pos!(&[0xdb54, 0xdf16, 0xd880, 0xdee0, 0xdb6a, 0xdd45],
490          &[0xd91f, 0xdeb1, 0xdb31, 0xdd84, 0xd8e2, 0xde14],
491          &[0xdb9f, 0xdc26, 0xdb6f, 0xde58, 0xd850, 0xdfae]);
492
493     // mixtures (also random)
494     pos!(&[0xd921, 0xdcc2, 0x002d, 0x004d, 0xdb32, 0xdf65],
495          &[0xdb45, 0xdd2d, 0x006a, 0xdacd, 0xddfe, 0x0006],
496          &[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]);
497
498     // negative tests
499     macro_rules! neg {
500         ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } }
501     }
502
503     neg!(
504         // surrogate + regular unit
505         &[0xdb45, 0x0000],
506         // surrogate + lead surrogate
507         &[0xd900, 0xd900],
508         // unterminated surrogate
509         &[0xd8ff],
510         // trail surrogate without a lead
511         &[0xddb7]);
512
513     // random byte sequences that Python 3's .decode('utf-16be')
514     // failed on
515     neg!(&[0x5b3d, 0x0141, 0xde9e, 0x8fdc, 0xc6e7],
516          &[0xdf5a, 0x82a5, 0x62b9, 0xb447, 0x92f3],
517          &[0xda4e, 0x42bc, 0x4462, 0xee98, 0xc2ca],
518          &[0xbe00, 0xb04a, 0x6ecb, 0xdd89, 0xe278],
519          &[0x0465, 0xab56, 0xdbb6, 0xa893, 0x665e],
520          &[0x6b7f, 0x0a19, 0x40f4, 0xa657, 0xdcc5],
521          &[0x9b50, 0xda5e, 0x24ec, 0x03ad, 0x6dee],
522          &[0x8d17, 0xcaa7, 0xf4ae, 0xdf6e, 0xbed7],
523          &[0xdaee, 0x2584, 0x7d30, 0xa626, 0x121a],
524          &[0xd956, 0x4b43, 0x7570, 0xccd6, 0x4f4a],
525          &[0x9dcf, 0x1b49, 0x4ba5, 0xfce9, 0xdffe],
526          &[0x6572, 0xce53, 0xb05a, 0xf6af, 0xdacf],
527          &[0x1b90, 0x728c, 0x9906, 0xdb68, 0xf46e],
528          &[0x1606, 0xbeca, 0xbe76, 0x860f, 0xdfa5],
529          &[0x8b4f, 0xde7a, 0xd220, 0x9fac, 0x2b6f],
530          &[0xb8fe, 0xebbe, 0xda32, 0x1a5f, 0x8b8b],
531          &[0x934b, 0x8956, 0xc434, 0x1881, 0xddf7],
532          &[0x5a95, 0x13fc, 0xf116, 0xd89b, 0x93f9],
533          &[0xd640, 0x71f1, 0xdd7d, 0x77eb, 0x1cd8],
534          &[0x348b, 0xaef0, 0xdb2c, 0xebf1, 0x1282],
535          &[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]);
536 }
537
538 #[test]
539 fn test_as_bytes() {
540     // no null
541     let v = [
542         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
543         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
544         109
545     ];
546     let b: &[u8] = &[];
547     assert_eq!("".as_bytes(), b);
548     assert_eq!("abc".as_bytes(), b"abc");
549     assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
550 }
551
552 #[test]
553 #[should_panic]
554 fn test_as_bytes_fail() {
555     // Don't double free. (I'm not sure if this exercises the
556     // original problem code path anymore.)
557     let s = String::from("");
558     let _bytes = s.as_bytes();
559     panic!();
560 }
561
562 #[test]
563 fn test_as_ptr() {
564     let buf = "hello".as_ptr();
565     unsafe {
566         assert_eq!(*buf.offset(0), b'h');
567         assert_eq!(*buf.offset(1), b'e');
568         assert_eq!(*buf.offset(2), b'l');
569         assert_eq!(*buf.offset(3), b'l');
570         assert_eq!(*buf.offset(4), b'o');
571     }
572 }
573
574 #[test]
575 fn vec_str_conversions() {
576     let s1: String = String::from("All mimsy were the borogoves");
577
578     let v: Vec<u8> = s1.as_bytes().to_vec();
579     let s2: String = String::from(from_utf8(&v).unwrap());
580     let mut i = 0;
581     let n1 = s1.len();
582     let n2 = v.len();
583     assert_eq!(n1, n2);
584     while i < n1 {
585         let a: u8 = s1.as_bytes()[i];
586         let b: u8 = s2.as_bytes()[i];
587         debug!("{}", a);
588         debug!("{}", b);
589         assert_eq!(a, b);
590         i += 1;
591     }
592 }
593
594 #[test]
595 fn test_contains() {
596     assert!("abcde".contains("bcd"));
597     assert!("abcde".contains("abcd"));
598     assert!("abcde".contains("bcde"));
599     assert!("abcde".contains(""));
600     assert!("".contains(""));
601     assert!(!"abcde".contains("def"));
602     assert!(!"".contains("a"));
603
604     let data = "ประเทศไทย中华Việt Nam";
605     assert!(data.contains("ประเ"));
606     assert!(data.contains("ะเ"));
607     assert!(data.contains("中华"));
608     assert!(!data.contains("ไท华"));
609 }
610
611 #[test]
612 fn test_contains_char() {
613     assert!("abc".contains('b'));
614     assert!("a".contains('a'));
615     assert!(!"abc".contains('d'));
616     assert!(!"".contains('a'));
617 }
618
619 #[test]
620 fn test_char_at() {
621     let s = "ศไทย中华Việt Nam";
622     let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
623     let mut pos = 0;
624     for ch in &v {
625         assert!(s.char_at(pos) == *ch);
626         pos += ch.to_string().len();
627     }
628 }
629
630 #[test]
631 fn test_char_at_reverse() {
632     let s = "ศไทย中华Việt Nam";
633     let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
634     let mut pos = s.len();
635     for ch in v.iter().rev() {
636         assert!(s.char_at_reverse(pos) == *ch);
637         pos -= ch.to_string().len();
638     }
639 }
640
641 #[test]
642 fn test_split_at() {
643     let s = "ศไทย中华Việt Nam";
644     for (index, _) in s.char_indices() {
645         let (a, b) = s.split_at(index);
646         assert_eq!(&s[..a.len()], a);
647         assert_eq!(&s[a.len()..], b);
648     }
649     let (a, b) = s.split_at(s.len());
650     assert_eq!(a, s);
651     assert_eq!(b, "");
652 }
653
654 #[test]
655 fn test_split_at_mut() {
656     use std::ascii::AsciiExt;
657     let mut s = "Hello World".to_string();
658     {
659         let (a, b) = s.split_at_mut(5);
660         a.make_ascii_uppercase();
661         b.make_ascii_lowercase();
662     }
663     assert_eq!(s, "HELLO world");
664 }
665
666 #[test]
667 #[should_panic]
668 fn test_split_at_boundscheck() {
669     let s = "ศไทย中华Việt Nam";
670     s.split_at(1);
671 }
672
673 #[test]
674 fn test_escape_unicode() {
675     assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
676     assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
677     assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
678     assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
679     assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
680     assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
681     assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
682     assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
683     assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
684 }
685
686 #[test]
687 fn test_escape_default() {
688     assert_eq!("abc".escape_default(), "abc");
689     assert_eq!("a c".escape_default(), "a c");
690     assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
691     assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
692     assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
693     assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
694     assert_eq!("ab\u{fb00}".escape_default(), "ab\\u{fb00}");
695     assert_eq!("\u{1d4ea}\r".escape_default(), "\\u{1d4ea}\\r");
696 }
697
698 #[test]
699 fn test_total_ord() {
700     assert_eq!("1234".cmp("123"), Greater);
701     assert_eq!("123".cmp("1234"), Less);
702     assert_eq!("1234".cmp("1234"), Equal);
703     assert_eq!("12345555".cmp("123456"), Less);
704     assert_eq!("22".cmp("1234"), Greater);
705 }
706
707 #[test]
708 fn test_char_range_at() {
709     let data = "b¢€𤭢𤭢€¢b";
710     assert_eq!('b', data.char_range_at(0).ch);
711     assert_eq!('¢', data.char_range_at(1).ch);
712     assert_eq!('€', data.char_range_at(3).ch);
713     assert_eq!('𤭢', data.char_range_at(6).ch);
714     assert_eq!('𤭢', data.char_range_at(10).ch);
715     assert_eq!('€', data.char_range_at(14).ch);
716     assert_eq!('¢', data.char_range_at(17).ch);
717     assert_eq!('b', data.char_range_at(19).ch);
718 }
719
720 #[test]
721 fn test_char_range_at_reverse_underflow() {
722     assert_eq!("abc".char_range_at_reverse(0).next, 0);
723 }
724
725 #[test]
726 fn test_iterator() {
727     let s = "ศไทย中华Việt Nam";
728     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
729
730     let mut pos = 0;
731     let it = s.chars();
732
733     for c in it {
734         assert_eq!(c, v[pos]);
735         pos += 1;
736     }
737     assert_eq!(pos, v.len());
738 }
739
740 #[test]
741 fn test_rev_iterator() {
742     let s = "ศไทย中华Việt Nam";
743     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
744
745     let mut pos = 0;
746     let it = s.chars().rev();
747
748     for c in it {
749         assert_eq!(c, v[pos]);
750         pos += 1;
751     }
752     assert_eq!(pos, v.len());
753 }
754
755 #[test]
756 fn test_chars_decoding() {
757     let mut bytes = [0; 4];
758     for c in (0..0x110000).filter_map(::std::char::from_u32) {
759         let len = c.encode_utf8(&mut bytes).unwrap_or(0);
760         let s = ::std::str::from_utf8(&bytes[..len]).unwrap();
761         if Some(c) != s.chars().next() {
762             panic!("character {:x}={} does not decode correctly", c as u32, c);
763         }
764     }
765 }
766
767 #[test]
768 fn test_chars_rev_decoding() {
769     let mut bytes = [0; 4];
770     for c in (0..0x110000).filter_map(::std::char::from_u32) {
771         let len = c.encode_utf8(&mut bytes).unwrap_or(0);
772         let s = ::std::str::from_utf8(&bytes[..len]).unwrap();
773         if Some(c) != s.chars().rev().next() {
774             panic!("character {:x}={} does not decode correctly", c as u32, c);
775         }
776     }
777 }
778
779 #[test]
780 fn test_iterator_clone() {
781     let s = "ศไทย中华Việt Nam";
782     let mut it = s.chars();
783     it.next();
784     assert!(it.clone().zip(it).all(|(x,y)| x == y));
785 }
786
787 #[test]
788 fn test_bytesator() {
789     let s = "ศไทย中华Việt Nam";
790     let v = [
791         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
792         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
793         109
794     ];
795     let mut pos = 0;
796
797     for b in s.bytes() {
798         assert_eq!(b, v[pos]);
799         pos += 1;
800     }
801 }
802
803 #[test]
804 fn test_bytes_revator() {
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 = v.len();
812
813     for b in s.bytes().rev() {
814         pos -= 1;
815         assert_eq!(b, v[pos]);
816     }
817 }
818
819 #[test]
820 fn test_bytesator_nth() {
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
828     let mut b = s.bytes();
829     assert_eq!(b.nth(2).unwrap(), v[2]);
830     assert_eq!(b.nth(10).unwrap(), v[10]);
831     assert_eq!(b.nth(200), None);
832 }
833
834 #[test]
835 fn test_bytesator_count() {
836     let s = "ศไทย中华Việt Nam";
837
838     let b = s.bytes();
839     assert_eq!(b.count(), 28)
840 }
841
842 #[test]
843 fn test_bytesator_last() {
844     let s = "ศไทย中华Việt Nam";
845
846     let b = s.bytes();
847     assert_eq!(b.last().unwrap(), 109)
848 }
849
850 #[test]
851 fn test_char_indicesator() {
852     let s = "ศไทย中华Việt Nam";
853     let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
854     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
855
856     let mut pos = 0;
857     let it = s.char_indices();
858
859     for c in it {
860         assert_eq!(c, (p[pos], v[pos]));
861         pos += 1;
862     }
863     assert_eq!(pos, v.len());
864     assert_eq!(pos, p.len());
865 }
866
867 #[test]
868 fn test_char_indices_revator() {
869     let s = "ศไทย中华Việt Nam";
870     let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
871     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
872
873     let mut pos = 0;
874     let it = s.char_indices().rev();
875
876     for c in it {
877         assert_eq!(c, (p[pos], v[pos]));
878         pos += 1;
879     }
880     assert_eq!(pos, v.len());
881     assert_eq!(pos, p.len());
882 }
883
884 #[test]
885 fn test_splitn_char_iterator() {
886     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
887
888     let split: Vec<&str> = data.splitn(4, ' ').collect();
889     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
890
891     let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
892     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
893
894     // Unicode
895     let split: Vec<&str> = data.splitn(4, 'ä').collect();
896     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
897
898     let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
899     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
900 }
901
902 #[test]
903 fn test_split_char_iterator_no_trailing() {
904     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
905
906     let split: Vec<&str> = data.split('\n').collect();
907     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
908
909     let split: Vec<&str> = data.split_terminator('\n').collect();
910     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
911 }
912
913 #[test]
914 fn test_rsplit() {
915     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
916
917     let split: Vec<&str> = data.rsplit(' ').collect();
918     assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
919
920     let split: Vec<&str> = data.rsplit("lämb").collect();
921     assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
922
923     let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
924     assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
925 }
926
927 #[test]
928 fn test_rsplitn() {
929     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
930
931     let split: Vec<&str> = data.rsplitn(2, ' ').collect();
932     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
933
934     let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
935     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
936
937     let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
938     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
939 }
940
941 #[test]
942 fn test_split_whitespace() {
943     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
944     let words: Vec<&str> = data.split_whitespace().collect();
945     assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
946 }
947
948 #[test]
949 fn test_lines() {
950     let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
951     let lines: Vec<&str> = data.lines().collect();
952     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
953
954     let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
955     let lines: Vec<&str> = data.lines().collect();
956     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
957 }
958
959 #[test]
960 fn test_splitator() {
961     fn t(s: &str, sep: &str, u: &[&str]) {
962         let v: Vec<&str> = s.split(sep).collect();
963         assert_eq!(v, u);
964     }
965     t("--1233345--", "12345", &["--1233345--"]);
966     t("abc::hello::there", "::", &["abc", "hello", "there"]);
967     t("::hello::there", "::", &["", "hello", "there"]);
968     t("hello::there::", "::", &["hello", "there", ""]);
969     t("::hello::there::", "::", &["", "hello", "there", ""]);
970     t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
971     t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
972     t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
973     t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
974     t("", ".", &[""]);
975     t("zz", "zz", &["",""]);
976     t("ok", "z", &["ok"]);
977     t("zzz", "zz", &["","z"]);
978     t("zzzzz", "zz", &["","","z"]);
979 }
980
981 #[test]
982 fn test_str_default() {
983     use std::default::Default;
984
985     fn t<S: Default + AsRef<str>>() {
986         let s: S = Default::default();
987         assert_eq!(s.as_ref(), "");
988     }
989
990     t::<&str>();
991     t::<String>();
992 }
993
994 #[test]
995 fn test_str_container() {
996     fn sum_len(v: &[&str]) -> usize {
997         v.iter().map(|x| x.len()).sum()
998     }
999
1000     let s = "01234";
1001     assert_eq!(5, sum_len(&["012", "", "34"]));
1002     assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1003     assert_eq!(5, sum_len(&[s]));
1004 }
1005
1006 #[test]
1007 fn test_str_from_utf8() {
1008     let xs = b"hello";
1009     assert_eq!(from_utf8(xs), Ok("hello"));
1010
1011     let xs = "ศไทย中华Việt Nam".as_bytes();
1012     assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1013
1014     let xs = b"hello\xFF";
1015     assert!(from_utf8(xs).is_err());
1016 }
1017
1018 #[test]
1019 fn test_pattern_deref_forward() {
1020     let data = "aabcdaa";
1021     assert!(data.contains("bcd"));
1022     assert!(data.contains(&"bcd"));
1023     assert!(data.contains(&"bcd".to_string()));
1024 }
1025
1026 #[test]
1027 fn test_empty_match_indices() {
1028     let data = "aä中!";
1029     let vec: Vec<_> = data.match_indices("").collect();
1030     assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1031 }
1032
1033 #[test]
1034 fn test_bool_from_str() {
1035     assert_eq!("true".parse().ok(), Some(true));
1036     assert_eq!("false".parse().ok(), Some(false));
1037     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1038 }
1039
1040 fn check_contains_all_substrings(s: &str) {
1041     assert!(s.contains(""));
1042     for i in 0..s.len() {
1043         for j in i+1..s.len() + 1 {
1044             assert!(s.contains(&s[i..j]));
1045         }
1046     }
1047 }
1048
1049 #[test]
1050 fn strslice_issue_16589() {
1051     assert!("bananas".contains("nana"));
1052
1053     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1054     // test all substrings for good measure
1055     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1056 }
1057
1058 #[test]
1059 fn strslice_issue_16878() {
1060     assert!(!"1234567ah012345678901ah".contains("hah"));
1061     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1062 }
1063
1064
1065 #[test]
1066 fn test_strslice_contains() {
1067     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1068     check_contains_all_substrings(x);
1069 }
1070
1071 #[test]
1072 fn test_rsplitn_char_iterator() {
1073     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1074
1075     let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1076     split.reverse();
1077     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1078
1079     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1080     split.reverse();
1081     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1082
1083     // Unicode
1084     let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1085     split.reverse();
1086     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1087
1088     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1089     split.reverse();
1090     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1091 }
1092
1093 #[test]
1094 fn test_split_char_iterator() {
1095     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1096
1097     let split: Vec<&str> = data.split(' ').collect();
1098     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1099
1100     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1101     rsplit.reverse();
1102     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1103
1104     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1105     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1106
1107     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1108     rsplit.reverse();
1109     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1110
1111     // Unicode
1112     let split: Vec<&str> = data.split('ä').collect();
1113     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1114
1115     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1116     rsplit.reverse();
1117     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1118
1119     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1120     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1121
1122     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1123     rsplit.reverse();
1124     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1125 }
1126
1127 #[test]
1128 fn test_rev_split_char_iterator_no_trailing() {
1129     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1130
1131     let mut split: Vec<&str> = data.split('\n').rev().collect();
1132     split.reverse();
1133     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1134
1135     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1136     split.reverse();
1137     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1138 }
1139
1140 #[test]
1141 fn test_utf16_code_units() {
1142     use rustc_unicode::str::Utf16Encoder;
1143     assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
1144                [0xE9, 0xD83D, 0xDCA9])
1145 }
1146
1147 #[test]
1148 fn starts_with_in_unicode() {
1149     assert!(!"├── Cargo.toml".starts_with("# "));
1150 }
1151
1152 #[test]
1153 fn starts_short_long() {
1154     assert!(!"".starts_with("##"));
1155     assert!(!"##".starts_with("####"));
1156     assert!("####".starts_with("##"));
1157     assert!(!"##ä".starts_with("####"));
1158     assert!("####ä".starts_with("##"));
1159     assert!(!"##".starts_with("####ä"));
1160     assert!("##ä##".starts_with("##ä"));
1161
1162     assert!("".starts_with(""));
1163     assert!("ä".starts_with(""));
1164     assert!("#ä".starts_with(""));
1165     assert!("##ä".starts_with(""));
1166     assert!("ä###".starts_with(""));
1167     assert!("#ä##".starts_with(""));
1168     assert!("##ä#".starts_with(""));
1169 }
1170
1171 #[test]
1172 fn contains_weird_cases() {
1173     assert!("* \t".contains(' '));
1174     assert!(!"* \t".contains('?'));
1175     assert!(!"* \t".contains('\u{1F4A9}'));
1176 }
1177
1178 #[test]
1179 fn trim_ws() {
1180     assert_eq!(" \t  a \t  ".trim_left_matches(|c: char| c.is_whitespace()),
1181                     "a \t  ");
1182     assert_eq!(" \t  a \t  ".trim_right_matches(|c: char| c.is_whitespace()),
1183                " \t  a");
1184     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()),
1185                     "a");
1186     assert_eq!(" \t   \t  ".trim_left_matches(|c: char| c.is_whitespace()),
1187                          "");
1188     assert_eq!(" \t   \t  ".trim_right_matches(|c: char| c.is_whitespace()),
1189                "");
1190     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()),
1191                "");
1192 }
1193
1194 #[test]
1195 fn to_lowercase() {
1196     assert_eq!("".to_lowercase(), "");
1197     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1198
1199     // https://github.com/rust-lang/rust/issues/26035
1200     assert_eq!("ΑΣ".to_lowercase(), "ας");
1201     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1202     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1203
1204     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1205     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1206     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1207
1208     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1209     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1210
1211     assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1212     assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1213
1214     assert_eq!("Α Σ".to_lowercase(), "α σ");
1215     assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1216     assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1217
1218     assert_eq!("Σ".to_lowercase(), "σ");
1219     assert_eq!("'Σ".to_lowercase(), "'σ");
1220     assert_eq!("''Σ".to_lowercase(), "''σ");
1221
1222     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1223     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1224     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1225 }
1226
1227 #[test]
1228 fn to_uppercase() {
1229     assert_eq!("".to_uppercase(), "");
1230     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1231 }
1232
1233 #[test]
1234 fn test_into_string() {
1235     // The only way to acquire a Box<str> in the first place is through a String, so just
1236     // test that we can round-trip between Box<str> and String.
1237     let string = String::from("Some text goes here");
1238     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1239 }
1240
1241 #[test]
1242 fn test_box_slice_clone() {
1243     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1244     let data2 = data.clone().into_boxed_str().clone().into_string();
1245
1246     assert_eq!(data, data2);
1247 }
1248
1249 mod pattern {
1250     use std::str::pattern::Pattern;
1251     use std::str::pattern::{Searcher, ReverseSearcher};
1252     use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1253
1254     macro_rules! make_test {
1255         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1256             #[allow(unused_imports)]
1257             mod $name {
1258                 use std::str::pattern::SearchStep::{Match, Reject};
1259                 use super::{cmp_search_to_vec};
1260                 #[test]
1261                 fn fwd() {
1262                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1263                 }
1264                 #[test]
1265                 fn bwd() {
1266                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1267                 }
1268             }
1269         }
1270     }
1271
1272     fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1273                                              right: Vec<SearchStep>)
1274     where P::Searcher: ReverseSearcher<'a>
1275     {
1276         let mut searcher = pat.into_searcher(haystack);
1277         let mut v = vec![];
1278         loop {
1279             match if !rev {searcher.next()} else {searcher.next_back()} {
1280                 Match(a, b) => v.push(Match(a, b)),
1281                 Reject(a, b) => v.push(Reject(a, b)),
1282                 Done => break,
1283             }
1284         }
1285         if rev {
1286             v.reverse();
1287         }
1288
1289         let mut first_index = 0;
1290         let mut err = None;
1291
1292         for (i, e) in right.iter().enumerate() {
1293             match *e {
1294                 Match(a, b) | Reject(a, b)
1295                 if a <= b && a == first_index => {
1296                     first_index = b;
1297                 }
1298                 _ => {
1299                     err = Some(i);
1300                     break;
1301                 }
1302             }
1303         }
1304
1305         if let Some(err) = err {
1306             panic!("Input skipped range at {}", err);
1307         }
1308
1309         if first_index != haystack.len() {
1310             panic!("Did not cover whole input");
1311         }
1312
1313         assert_eq!(v, right);
1314     }
1315
1316     make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1317         Reject(0, 1),
1318         Match (1, 3),
1319         Reject(3, 4),
1320         Match (4, 6),
1321         Reject(6, 7),
1322     ]);
1323     make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1324         Reject(0, 1),
1325         Match (1, 3),
1326         Reject(3, 4),
1327         Match (4, 6),
1328         Match (6, 8),
1329         Reject(8, 9),
1330     ]);
1331     make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1332         Match (0, 0),
1333         Reject(0, 1),
1334         Match (1, 1),
1335         Reject(1, 2),
1336         Match (2, 2),
1337         Reject(2, 3),
1338         Match (3, 3),
1339         Reject(3, 4),
1340         Match (4, 4),
1341         Reject(4, 5),
1342         Match (5, 5),
1343         Reject(5, 6),
1344         Match (6, 6),
1345         Reject(6, 7),
1346         Match (7, 7),
1347     ]);
1348     make_test!(str_searcher_mulibyte_haystack, " ", "├──", [
1349         Reject(0, 3),
1350         Reject(3, 6),
1351         Reject(6, 9),
1352     ]);
1353     make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [
1354         Match (0, 0),
1355         Reject(0, 3),
1356         Match (3, 3),
1357         Reject(3, 6),
1358         Match (6, 6),
1359         Reject(6, 9),
1360         Match (9, 9),
1361     ]);
1362     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1363         Match(0, 0),
1364     ]);
1365     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1366     ]);
1367     make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1368         Reject(0, 1),
1369         Match (1, 2),
1370         Match (2, 3),
1371         Reject(3, 4),
1372         Match (4, 5),
1373         Match (5, 6),
1374         Reject(6, 7),
1375     ]);
1376     make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [
1377         Reject(0, 3),
1378         Reject(3, 6),
1379         Reject(6, 9),
1380     ]);
1381     make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1382         Reject(0, 1),
1383         Reject(1, 2),
1384         Reject(2, 3),
1385     ]);
1386
1387 }
1388
1389 macro_rules! generate_iterator_test {
1390     {
1391         $name:ident {
1392             $(
1393                 ($($arg:expr),*) -> [$($t:tt)*];
1394             )*
1395         }
1396         with $fwd:expr, $bwd:expr;
1397     } => {
1398         #[test]
1399         fn $name() {
1400             $(
1401                 {
1402                     let res = vec![$($t)*];
1403
1404                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1405                     assert_eq!(fwd_vec, res);
1406
1407                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1408                     bwd_vec.reverse();
1409                     assert_eq!(bwd_vec, res);
1410                 }
1411             )*
1412         }
1413     };
1414     {
1415         $name:ident {
1416             $(
1417                 ($($arg:expr),*) -> [$($t:tt)*];
1418             )*
1419         }
1420         with $fwd:expr;
1421     } => {
1422         #[test]
1423         fn $name() {
1424             $(
1425                 {
1426                     let res = vec![$($t)*];
1427
1428                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1429                     assert_eq!(fwd_vec, res);
1430                 }
1431             )*
1432         }
1433     }
1434 }
1435
1436 generate_iterator_test! {
1437     double_ended_split {
1438         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1439         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1440     }
1441     with str::split, str::rsplit;
1442 }
1443
1444 generate_iterator_test! {
1445     double_ended_split_terminator {
1446         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1447     }
1448     with str::split_terminator, str::rsplit_terminator;
1449 }
1450
1451 generate_iterator_test! {
1452     double_ended_matches {
1453         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1454     }
1455     with str::matches, str::rmatches;
1456 }
1457
1458 generate_iterator_test! {
1459     double_ended_match_indices {
1460         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1461     }
1462     with str::match_indices, str::rmatch_indices;
1463 }
1464
1465 generate_iterator_test! {
1466     not_double_ended_splitn {
1467         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1468     }
1469     with str::splitn;
1470 }
1471
1472 generate_iterator_test! {
1473     not_double_ended_rsplitn {
1474         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1475     }
1476     with str::rsplitn;
1477 }
1478
1479 mod bench {
1480     use test::{Bencher, black_box};
1481
1482     #[bench]
1483     fn char_iterator(b: &mut Bencher) {
1484         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1485
1486         b.iter(|| s.chars().count());
1487     }
1488
1489     #[bench]
1490     fn char_iterator_for(b: &mut Bencher) {
1491         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1492
1493         b.iter(|| {
1494             for ch in s.chars() { black_box(ch); }
1495         });
1496     }
1497
1498     #[bench]
1499     fn char_iterator_ascii(b: &mut Bencher) {
1500         let s = "Mary had a little lamb, Little lamb
1501         Mary had a little lamb, Little lamb
1502         Mary had a little lamb, Little lamb
1503         Mary had a little lamb, Little lamb
1504         Mary had a little lamb, Little lamb
1505         Mary had a little lamb, Little lamb";
1506
1507         b.iter(|| s.chars().count());
1508     }
1509
1510     #[bench]
1511     fn char_iterator_rev(b: &mut Bencher) {
1512         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1513
1514         b.iter(|| s.chars().rev().count());
1515     }
1516
1517     #[bench]
1518     fn char_iterator_rev_for(b: &mut Bencher) {
1519         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1520
1521         b.iter(|| {
1522             for ch in s.chars().rev() { black_box(ch); }
1523         });
1524     }
1525
1526     #[bench]
1527     fn char_indicesator(b: &mut Bencher) {
1528         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1529         let len = s.chars().count();
1530
1531         b.iter(|| assert_eq!(s.char_indices().count(), len));
1532     }
1533
1534     #[bench]
1535     fn char_indicesator_rev(b: &mut Bencher) {
1536         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1537         let len = s.chars().count();
1538
1539         b.iter(|| assert_eq!(s.char_indices().rev().count(), len));
1540     }
1541
1542     #[bench]
1543     fn split_unicode_ascii(b: &mut Bencher) {
1544         let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
1545
1546         b.iter(|| assert_eq!(s.split('V').count(), 3));
1547     }
1548
1549     #[bench]
1550     fn split_ascii(b: &mut Bencher) {
1551         let s = "Mary had a little lamb, Little lamb, little-lamb.";
1552         let len = s.split(' ').count();
1553
1554         b.iter(|| assert_eq!(s.split(' ').count(), len));
1555     }
1556
1557     #[bench]
1558     fn split_extern_fn(b: &mut Bencher) {
1559         let s = "Mary had a little lamb, Little lamb, little-lamb.";
1560         let len = s.split(' ').count();
1561         fn pred(c: char) -> bool { c == ' ' }
1562
1563         b.iter(|| assert_eq!(s.split(pred).count(), len));
1564     }
1565
1566     #[bench]
1567     fn split_closure(b: &mut Bencher) {
1568         let s = "Mary had a little lamb, Little lamb, little-lamb.";
1569         let len = s.split(' ').count();
1570
1571         b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len));
1572     }
1573
1574     #[bench]
1575     fn split_slice(b: &mut Bencher) {
1576         let s = "Mary had a little lamb, Little lamb, little-lamb.";
1577         let len = s.split(' ').count();
1578
1579         let c: &[char] = &[' '];
1580         b.iter(|| assert_eq!(s.split(c).count(), len));
1581     }
1582
1583     #[bench]
1584     fn bench_join(b: &mut Bencher) {
1585         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1586         let sep = "→";
1587         let v = vec![s, s, s, s, s, s, s, s, s, s];
1588         b.iter(|| {
1589             assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9);
1590         })
1591     }
1592
1593     #[bench]
1594     fn bench_contains_short_short(b: &mut Bencher) {
1595         let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
1596         let needle = "sit";
1597
1598         b.iter(|| {
1599             assert!(haystack.contains(needle));
1600         })
1601     }
1602
1603     #[bench]
1604     fn bench_contains_short_long(b: &mut Bencher) {
1605         let haystack = "\
1606 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
1607 ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
1608 eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
1609 sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
1610 tempus vel, gravida nec quam.
1611
1612 In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
1613 sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
1614 diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
1615 lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
1616 eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
1617 interdum. Curabitur ut nisi justo.
1618
1619 Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
1620 mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
1621 lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
1622 est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
1623 felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
1624 ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
1625 feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
1626 Aliquam sit amet placerat lorem.
1627
1628 Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
1629 mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
1630 Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
1631 lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
1632 suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
1633 cursus accumsan.
1634
1635 Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
1636 feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
1637 vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
1638 leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
1639 malesuada sollicitudin quam eu fermentum.";
1640         let needle = "english";
1641
1642         b.iter(|| {
1643             assert!(!haystack.contains(needle));
1644         })
1645     }
1646
1647     #[bench]
1648     fn bench_contains_bad_naive(b: &mut Bencher) {
1649         let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
1650         let needle = "aaaaaaaab";
1651
1652         b.iter(|| {
1653             assert!(!haystack.contains(needle));
1654         })
1655     }
1656
1657     #[bench]
1658     fn bench_contains_equal(b: &mut Bencher) {
1659         let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
1660         let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
1661
1662         b.iter(|| {
1663             assert!(haystack.contains(needle));
1664         })
1665     }
1666
1667     macro_rules! make_test_inner {
1668         ($s:ident, $code:expr, $name:ident, $str:expr) => {
1669             #[bench]
1670             fn $name(bencher: &mut Bencher) {
1671                 let mut $s = $str;
1672                 black_box(&mut $s);
1673                 bencher.iter(|| $code);
1674             }
1675         }
1676     }
1677
1678     macro_rules! make_test {
1679         ($name:ident, $s:ident, $code:expr) => {
1680             mod $name {
1681                 use test::Bencher;
1682                 use test::black_box;
1683
1684                 // Short strings: 65 bytes each
1685                 make_test_inner!($s, $code, short_ascii,
1686                     "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
1687                 make_test_inner!($s, $code, short_mixed,
1688                     "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
1689                 make_test_inner!($s, $code, short_pile_of_poo,
1690                     "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
1691                 make_test_inner!($s, $code, long_lorem_ipsum,"\
1692 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
1693 ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
1694 eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
1695 sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
1696 tempus vel, gravida nec quam.
1697
1698 In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
1699 sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
1700 diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
1701 lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
1702 eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
1703 interdum. Curabitur ut nisi justo.
1704
1705 Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
1706 mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
1707 lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
1708 est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
1709 felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
1710 ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
1711 feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
1712 Aliquam sit amet placerat lorem.
1713
1714 Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
1715 mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
1716 Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
1717 lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
1718 suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
1719 cursus accumsan.
1720
1721 Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
1722 feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
1723 vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
1724 leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
1725 malesuada sollicitudin quam eu fermentum!");
1726             }
1727         }
1728     }
1729
1730     make_test!(chars_count, s, s.chars().count());
1731
1732     make_test!(contains_bang_str, s, s.contains("!"));
1733     make_test!(contains_bang_char, s, s.contains('!'));
1734
1735     make_test!(match_indices_a_str, s, s.match_indices("a").count());
1736
1737     make_test!(split_a_str, s, s.split("a").count());
1738
1739     make_test!(trim_ascii_char, s, {
1740         use std::ascii::AsciiExt;
1741         s.trim_matches(|c: char| c.is_ascii())
1742     });
1743     make_test!(trim_left_ascii_char, s, {
1744         use std::ascii::AsciiExt;
1745         s.trim_left_matches(|c: char| c.is_ascii())
1746     });
1747     make_test!(trim_right_ascii_char, s, {
1748         use std::ascii::AsciiExt;
1749         s.trim_right_matches(|c: char| c.is_ascii())
1750     });
1751
1752     make_test!(find_underscore_char, s, s.find('_'));
1753     make_test!(rfind_underscore_char, s, s.rfind('_'));
1754     make_test!(find_underscore_str, s, s.find("_"));
1755
1756     make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
1757     make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
1758     make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
1759
1760     make_test!(split_space_char, s, s.split(' ').count());
1761     make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
1762
1763     make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
1764     make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
1765
1766     make_test!(split_space_str, s, s.split(" ").count());
1767     make_test!(split_ad_str, s, s.split("ad").count());
1768 }