]> git.lizzy.rs Git - rust.git/blob - src/liballoc/tests/str.rs
liballoc: elide &'static.
[rust.git] / src / liballoc / tests / str.rs
1 use std::{
2     borrow::Cow,
3     cmp::Ordering::{Equal, Greater, Less},
4     str::from_utf8,
5 };
6
7 #[test]
8 fn test_le() {
9     assert!("" <= "");
10     assert!("" <= "foo");
11     assert!("foo" <= "foo");
12     assert!("foo" != "bar");
13 }
14
15 #[test]
16 fn test_find() {
17     assert_eq!("hello".find('l'), Some(2));
18     assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
19     assert!("hello".find('x').is_none());
20     assert!("hello".find(|c:char| c == 'x').is_none());
21     assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
22     assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
23 }
24
25 #[test]
26 fn test_rfind() {
27     assert_eq!("hello".rfind('l'), Some(3));
28     assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
29     assert!("hello".rfind('x').is_none());
30     assert!("hello".rfind(|c:char| c == 'x').is_none());
31     assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
32     assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
33 }
34
35 #[test]
36 fn test_collect() {
37     let empty = "";
38     let s: String = empty.chars().collect();
39     assert_eq!(empty, s);
40     let data = "ประเทศไทย中";
41     let s: String = data.chars().collect();
42     assert_eq!(data, s);
43 }
44
45 #[test]
46 fn test_into_bytes() {
47     let data = String::from("asdf");
48     let buf = data.into_bytes();
49     assert_eq!(buf, b"asdf");
50 }
51
52 #[test]
53 fn test_find_str() {
54     // byte positions
55     assert_eq!("".find(""), Some(0));
56     assert!("banana".find("apple pie").is_none());
57
58     let data = "abcabc";
59     assert_eq!(data[0..6].find("ab"), Some(0));
60     assert_eq!(data[2..6].find("ab"), Some(3 - 2));
61     assert!(data[2..4].find("ab").is_none());
62
63     let string = "ประเทศไทย中华Việt Nam";
64     let mut data = String::from(string);
65     data.push_str(string);
66     assert!(data.find("ไท华").is_none());
67     assert_eq!(data[0..43].find(""), Some(0));
68     assert_eq!(data[6..43].find(""), Some(6 - 6));
69
70     assert_eq!(data[0..43].find("ประ"), Some( 0));
71     assert_eq!(data[0..43].find("ทศไ"), Some(12));
72     assert_eq!(data[0..43].find("ย中"), Some(24));
73     assert_eq!(data[0..43].find("iệt"), Some(34));
74     assert_eq!(data[0..43].find("Nam"), Some(40));
75
76     assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
77     assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
78     assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
79     assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
80     assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
81
82     // find every substring -- assert that it finds it, or an earlier occurrence.
83     let string = "Việt Namacbaabcaabaaba";
84     for (i, ci) in string.char_indices() {
85         let ip = i + ci.len_utf8();
86         for j in string[ip..].char_indices()
87                              .map(|(i, _)| i)
88                              .chain(Some(string.len() - ip))
89         {
90             let pat = &string[i..ip + j];
91             assert!(match string.find(pat) {
92                 None => false,
93                 Some(x) => x <= i,
94             });
95             assert!(match string.rfind(pat) {
96                 None => false,
97                 Some(x) => x >= i,
98             });
99         }
100     }
101 }
102
103 fn s(x: &str) -> String { x.to_string() }
104
105 macro_rules! test_concat {
106     ($expected: expr, $string: expr) => {
107         {
108             let s: String = $string.concat();
109             assert_eq!($expected, s);
110         }
111     }
112 }
113
114 #[test]
115 fn test_concat_for_different_types() {
116     test_concat!("ab", vec![s("a"), s("b")]);
117     test_concat!("ab", vec!["a", "b"]);
118 }
119
120 #[test]
121 fn test_concat_for_different_lengths() {
122     let empty: &[&str] = &[];
123     test_concat!("", empty);
124     test_concat!("a", ["a"]);
125     test_concat!("ab", ["a", "b"]);
126     test_concat!("abc", ["", "a", "bc"]);
127 }
128
129 macro_rules! test_join {
130     ($expected: expr, $string: expr, $delim: expr) => {
131         {
132             let s = $string.join($delim);
133             assert_eq!($expected, s);
134         }
135     }
136 }
137
138 #[test]
139 fn test_join_for_different_types() {
140     test_join!("a-b", ["a", "b"], "-");
141     let hyphen = "-".to_string();
142     test_join!("a-b", [s("a"), s("b")], &*hyphen);
143     test_join!("a-b", vec!["a", "b"], &*hyphen);
144     test_join!("a-b", &*vec!["a", "b"], "-");
145     test_join!("a-b", vec![s("a"), s("b")], "-");
146 }
147
148 #[test]
149 fn test_join_for_different_lengths() {
150     let empty: &[&str] = &[];
151     test_join!("", empty, "-");
152     test_join!("a", ["a"], "-");
153     test_join!("a-b", ["a", "b"], "-");
154     test_join!("-a-bc", ["", "a", "bc"], "-");
155 }
156
157 // join has fast paths for small separators up to 4 bytes
158 // this tests the slow paths.
159 #[test]
160 fn test_join_for_different_lengths_with_long_separator() {
161     assert_eq!("~~~~~".len(), 15);
162
163     let empty: &[&str] = &[];
164     test_join!("", empty, "~~~~~");
165     test_join!("a", ["a"], "~~~~~");
166     test_join!("a~~~~~b", ["a", "b"], "~~~~~");
167     test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
168 }
169
170 #[test]
171 fn test_unsafe_slice() {
172     assert_eq!("ab", unsafe {"abc".get_unchecked(0..2)});
173     assert_eq!("bc", unsafe {"abc".get_unchecked(1..3)});
174     assert_eq!("", unsafe {"abc".get_unchecked(1..1)});
175     fn a_million_letter_a() -> String {
176         let mut i = 0;
177         let mut rs = String::new();
178         while i < 100000 {
179             rs.push_str("aaaaaaaaaa");
180             i += 1;
181         }
182         rs
183     }
184     fn half_a_million_letter_a() -> String {
185         let mut i = 0;
186         let mut rs = String::new();
187         while i < 100000 {
188             rs.push_str("aaaaa");
189             i += 1;
190         }
191         rs
192     }
193     let letters = a_million_letter_a();
194     assert_eq!(half_a_million_letter_a(),
195         unsafe { letters.get_unchecked(0..500000)});
196 }
197
198 #[test]
199 fn test_starts_with() {
200     assert!("".starts_with(""));
201     assert!("abc".starts_with(""));
202     assert!("abc".starts_with("a"));
203     assert!(!"a".starts_with("abc"));
204     assert!(!"".starts_with("abc"));
205     assert!(!"ödd".starts_with("-"));
206     assert!("ödd".starts_with("öd"));
207 }
208
209 #[test]
210 fn test_ends_with() {
211     assert!("".ends_with(""));
212     assert!("abc".ends_with(""));
213     assert!("abc".ends_with("c"));
214     assert!(!"a".ends_with("abc"));
215     assert!(!"".ends_with("abc"));
216     assert!(!"ddö".ends_with("-"));
217     assert!("ddö".ends_with("dö"));
218 }
219
220 #[test]
221 fn test_is_empty() {
222     assert!("".is_empty());
223     assert!(!"a".is_empty());
224 }
225
226 #[test]
227 fn test_replacen() {
228     assert_eq!("".replacen('a', "b", 5), "");
229     assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
230     assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
231
232     let test = "test";
233     assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
234     assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
235     assert_eq!(" test test ".replacen(test, "", 5), "   ");
236
237     assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
238 }
239
240 #[test]
241 fn test_replace() {
242     let a = "a";
243     assert_eq!("".replace(a, "b"), "");
244     assert_eq!("a".replace(a, "b"), "b");
245     assert_eq!("ab".replace(a, "b"), "bb");
246     let test = "test";
247     assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
248     assert_eq!(" test test ".replace(test, ""), "   ");
249 }
250
251 #[test]
252 fn test_replace_2a() {
253     let data = "ประเทศไทย中华";
254     let repl = "دولة الكويت";
255
256     let a = "ประเ";
257     let a2 = "دولة الكويتทศไทย中华";
258     assert_eq!(data.replace(a, repl), a2);
259 }
260
261 #[test]
262 fn test_replace_2b() {
263     let data = "ประเทศไทย中华";
264     let repl = "دولة الكويت";
265
266     let b = "ะเ";
267     let b2 = "ปรدولة الكويتทศไทย中华";
268     assert_eq!(data.replace(b, repl), b2);
269 }
270
271 #[test]
272 fn test_replace_2c() {
273     let data = "ประเทศไทย中华";
274     let repl = "دولة الكويت";
275
276     let c = "中华";
277     let c2 = "ประเทศไทยدولة الكويت";
278     assert_eq!(data.replace(c, repl), c2);
279 }
280
281 #[test]
282 fn test_replace_2d() {
283     let data = "ประเทศไทย中华";
284     let repl = "دولة الكويت";
285
286     let d = "ไท华";
287     assert_eq!(data.replace(d, repl), data);
288 }
289
290 #[test]
291 fn test_replace_pattern() {
292     let data = "abcdαβγδabcdαβγδ";
293     assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
294     assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
295     assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
296     assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
297 }
298
299 // The current implementation of SliceIndex fails to handle methods
300 // orthogonally from range types; therefore, it is worth testing
301 // all of the indexing operations on each input.
302 mod slice_index {
303     // Test a slicing operation **that should succeed,**
304     // testing it on all of the indexing methods.
305     //
306     // This is not suitable for testing failure on invalid inputs.
307     macro_rules! assert_range_eq {
308         ($s:expr, $range:expr, $expected:expr)
309         => {
310             let mut s: String = $s.to_owned();
311             let mut expected: String = $expected.to_owned();
312             {
313                 let s: &str = &s;
314                 let expected: &str = &expected;
315
316                 assert_eq!(&s[$range], expected, "(in assertion for: index)");
317                 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
318                 unsafe {
319                     assert_eq!(
320                         s.get_unchecked($range), expected,
321                         "(in assertion for: get_unchecked)",
322                     );
323                 }
324             }
325             {
326                 let s: &mut str = &mut s;
327                 let expected: &mut str = &mut expected;
328
329                 assert_eq!(
330                     &mut s[$range], expected,
331                     "(in assertion for: index_mut)",
332                 );
333                 assert_eq!(
334                     s.get_mut($range), Some(&mut expected[..]),
335                     "(in assertion for: get_mut)",
336                 );
337                 unsafe {
338                     assert_eq!(
339                         s.get_unchecked_mut($range), expected,
340                         "(in assertion for: get_unchecked_mut)",
341                     );
342                 }
343             }
344         }
345     }
346
347     // Make sure the macro can actually detect bugs,
348     // because if it can't, then what are we even doing here?
349     //
350     // (Be aware this only demonstrates the ability to detect bugs
351     //  in the FIRST method that panics, as the macro is not designed
352     //  to be used in `should_panic`)
353     #[test]
354     #[should_panic(expected = "out of bounds")]
355     fn assert_range_eq_can_fail_by_panic() {
356         assert_range_eq!("abc", 0..5, "abc");
357     }
358
359     // (Be aware this only demonstrates the ability to detect bugs
360     //  in the FIRST method it calls, as the macro is not designed
361     //  to be used in `should_panic`)
362     #[test]
363     #[should_panic(expected = "==")]
364     fn assert_range_eq_can_fail_by_inequality() {
365         assert_range_eq!("abc", 0..2, "abc");
366     }
367
368     // Generates test cases for bad index operations.
369     //
370     // This generates `should_panic` test cases for Index/IndexMut
371     // and `None` test cases for get/get_mut.
372     macro_rules! panic_cases {
373         ($(
374             in mod $case_name:ident {
375                 data: $data:expr;
376
377                 // optional:
378                 //
379                 // a similar input for which DATA[input] succeeds, and the corresponding
380                 // output str. This helps validate "critical points" where an input range
381                 // straddles the boundary between valid and invalid.
382                 // (such as the input `len..len`, which is just barely valid)
383                 $(
384                     good: data[$good:expr] == $output:expr;
385                 )*
386
387                 bad: data[$bad:expr];
388                 message: $expect_msg:expr; // must be a literal
389             }
390         )*) => {$(
391             mod $case_name {
392                 #[test]
393                 fn pass() {
394                     let mut v: String = $data.into();
395
396                     $( assert_range_eq!(v, $good, $output); )*
397
398                     {
399                         let v: &str = &v;
400                         assert_eq!(v.get($bad), None, "(in None assertion for get)");
401                     }
402
403                     {
404                         let v: &mut str = &mut v;
405                         assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
406                     }
407                 }
408
409                 #[test]
410                 #[should_panic(expected = $expect_msg)]
411                 fn index_fail() {
412                     let v: String = $data.into();
413                     let v: &str = &v;
414                     let _v = &v[$bad];
415                 }
416
417                 #[test]
418                 #[should_panic(expected = $expect_msg)]
419                 fn index_mut_fail() {
420                     let mut v: String = $data.into();
421                     let v: &mut str = &mut v;
422                     let _v = &mut v[$bad];
423                 }
424             }
425         )*};
426     }
427
428     #[test]
429     fn simple_ascii() {
430         assert_range_eq!("abc", .., "abc");
431
432         assert_range_eq!("abc", 0..2, "ab");
433         assert_range_eq!("abc", 0..=1, "ab");
434         assert_range_eq!("abc", ..2, "ab");
435         assert_range_eq!("abc", ..=1, "ab");
436
437         assert_range_eq!("abc", 1..3, "bc");
438         assert_range_eq!("abc", 1..=2, "bc");
439         assert_range_eq!("abc", 1..1, "");
440         assert_range_eq!("abc", 1..=0, "");
441     }
442
443     #[test]
444     fn simple_unicode() {
445         // 日本
446         assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
447
448         assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
449         assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
450         assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
451         assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
452
453         assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
454         assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
455         assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
456
457         let data = "ประเทศไทย中华";
458         assert_range_eq!(data, 0..3, "ป");
459         assert_range_eq!(data, 3..6, "ร");
460         assert_range_eq!(data, 3..3, "");
461         assert_range_eq!(data, 30..33, "华");
462
463         /*0: 中
464           3: 华
465           6: V
466           7: i
467           8: ệ
468          11: t
469          12:
470          13: N
471          14: a
472          15: m */
473         let ss = "中华Việt Nam";
474         assert_range_eq!(ss, 3..6, "华");
475         assert_range_eq!(ss, 6..16, "Việt Nam");
476         assert_range_eq!(ss, 6..=15, "Việt Nam");
477         assert_range_eq!(ss, 6.., "Việt Nam");
478
479         assert_range_eq!(ss, 0..3, "中");
480         assert_range_eq!(ss, 3..7, "华V");
481         assert_range_eq!(ss, 3..=6, "华V");
482         assert_range_eq!(ss, 3..3, "");
483         assert_range_eq!(ss, 3..=2, "");
484     }
485
486     #[test]
487     #[cfg(not(target_arch = "asmjs"))] // hits an OOM
488     fn simple_big() {
489         fn a_million_letter_x() -> String {
490             let mut i = 0;
491             let mut rs = String::new();
492             while i < 100000 {
493                 rs.push_str("华华华华华华华华华华");
494                 i += 1;
495             }
496             rs
497         }
498         fn half_a_million_letter_x() -> String {
499             let mut i = 0;
500             let mut rs = String::new();
501             while i < 100000 {
502                 rs.push_str("华华华华华");
503                 i += 1;
504             }
505             rs
506         }
507         let letters = a_million_letter_x();
508         assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
509     }
510
511     #[test]
512     #[should_panic]
513     fn test_slice_fail() {
514         &"中华Việt Nam"[0..2];
515     }
516
517     panic_cases! {
518         in mod rangefrom_len {
519             data: "abcdef";
520             good: data[6..] == "";
521             bad: data[7..];
522             message: "out of bounds";
523         }
524
525         in mod rangeto_len {
526             data: "abcdef";
527             good: data[..6] == "abcdef";
528             bad: data[..7];
529             message: "out of bounds";
530         }
531
532         in mod rangetoinclusive_len {
533             data: "abcdef";
534             good: data[..=5] == "abcdef";
535             bad: data[..=6];
536             message: "out of bounds";
537         }
538
539         in mod range_len_len {
540             data: "abcdef";
541             good: data[6..6] == "";
542             bad: data[7..7];
543             message: "out of bounds";
544         }
545
546         in mod rangeinclusive_len_len {
547             data: "abcdef";
548             good: data[6..=5] == "";
549             bad: data[7..=6];
550             message: "out of bounds";
551         }
552     }
553
554     panic_cases! {
555         in mod range_neg_width {
556             data: "abcdef";
557             good: data[4..4] == "";
558             bad: data[4..3];
559             message: "begin <= end (4 <= 3)";
560         }
561
562         in mod rangeinclusive_neg_width {
563             data: "abcdef";
564             good: data[4..=3] == "";
565             bad: data[4..=2];
566             message: "begin <= end (4 <= 3)";
567         }
568     }
569
570     mod overflow {
571         panic_cases! {
572             in mod rangeinclusive {
573                 data: "hello";
574                 // note: using 0 specifically ensures that the result of overflowing is 0..0,
575                 //       so that `get` doesn't simply return None for the wrong reason.
576                 bad: data[0..=usize::max_value()];
577                 message: "maximum usize";
578             }
579
580             in mod rangetoinclusive {
581                 data: "hello";
582                 bad: data[..=usize::max_value()];
583                 message: "maximum usize";
584             }
585         }
586     }
587
588     mod boundary {
589         const DATA: &str = "abcαβγ";
590
591         const BAD_START: usize = 4;
592         const GOOD_START: usize = 3;
593         const BAD_END: usize = 6;
594         const GOOD_END: usize = 7;
595         const BAD_END_INCL: usize = BAD_END - 1;
596         const GOOD_END_INCL: usize = GOOD_END - 1;
597
598         // it is especially important to test all of the different range types here
599         // because some of the logic may be duplicated as part of micro-optimizations
600         // to dodge unicode boundary checks on half-ranges.
601         panic_cases! {
602             in mod range_1 {
603                 data: super::DATA;
604                 bad: data[super::BAD_START..super::GOOD_END];
605                 message:
606                     "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
607             }
608
609             in mod range_2 {
610                 data: super::DATA;
611                 bad: data[super::GOOD_START..super::BAD_END];
612                 message:
613                     "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
614             }
615
616             in mod rangefrom {
617                 data: super::DATA;
618                 bad: data[super::BAD_START..];
619                 message:
620                     "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
621             }
622
623             in mod rangeto {
624                 data: super::DATA;
625                 bad: data[..super::BAD_END];
626                 message:
627                     "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
628             }
629
630             in mod rangeinclusive_1 {
631                 data: super::DATA;
632                 bad: data[super::BAD_START..=super::GOOD_END_INCL];
633                 message:
634                     "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of";
635             }
636
637             in mod rangeinclusive_2 {
638                 data: super::DATA;
639                 bad: data[super::GOOD_START..=super::BAD_END_INCL];
640                 message:
641                     "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
642             }
643
644             in mod rangetoinclusive {
645                 data: super::DATA;
646                 bad: data[..=super::BAD_END_INCL];
647                 message:
648                     "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of";
649             }
650         }
651     }
652
653     const LOREM_PARAGRAPH: &str = "\
654     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \
655     sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \
656     quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \
657     nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \
658     tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \
659     gravida nec quam.";
660
661     // check the panic includes the prefix of the sliced string
662     #[test]
663     #[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
664     fn test_slice_fail_truncated_1() {
665         &LOREM_PARAGRAPH[..1024];
666     }
667     // check the truncation in the panic message
668     #[test]
669     #[should_panic(expected="luctus, im`[...]")]
670     fn test_slice_fail_truncated_2() {
671         &LOREM_PARAGRAPH[..1024];
672     }
673 }
674
675 #[test]
676 fn test_str_slice_rangetoinclusive_ok() {
677     let s = "abcαβγ";
678     assert_eq!(&s[..=2], "abc");
679     assert_eq!(&s[..=4], "abcα");
680 }
681
682 #[test]
683 #[should_panic]
684 fn test_str_slice_rangetoinclusive_notok() {
685     let s = "abcαβγ";
686     &s[..=3];
687 }
688
689 #[test]
690 fn test_str_slicemut_rangetoinclusive_ok() {
691     let mut s = "abcαβγ".to_owned();
692     let s: &mut str = &mut s;
693     assert_eq!(&mut s[..=2], "abc");
694     assert_eq!(&mut s[..=4], "abcα");
695 }
696
697 #[test]
698 #[should_panic]
699 fn test_str_slicemut_rangetoinclusive_notok() {
700     let mut s = "abcαβγ".to_owned();
701     let s: &mut str = &mut s;
702     &mut s[..=3];
703 }
704
705 #[test]
706 fn test_is_char_boundary() {
707     let s = "ศไทย中华Việt Nam β-release 🐱123";
708     assert!(s.is_char_boundary(0));
709     assert!(s.is_char_boundary(s.len()));
710     assert!(!s.is_char_boundary(s.len() + 1));
711     for (i, ch) in s.char_indices() {
712         // ensure character locations are boundaries and continuation bytes are not
713         assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
714         for j in 1..ch.len_utf8() {
715             assert!(!s.is_char_boundary(i + j),
716                     "{} should not be a char boundary in {:?}", i + j, s);
717         }
718     }
719 }
720
721 #[test]
722 fn test_trim_start_matches() {
723     let v: &[char] = &[];
724     assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
725     let chars: &[char] = &['*', ' '];
726     assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
727     assert_eq!(" ***  *** ".trim_start_matches(chars), "");
728     assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
729
730     assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
731     let chars: &[char] = &['1', '2'];
732     assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
733     assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
734 }
735
736 #[test]
737 fn test_trim_end_matches() {
738     let v: &[char] = &[];
739     assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
740     let chars: &[char] = &['*', ' '];
741     assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
742     assert_eq!(" ***  *** ".trim_end_matches(chars), "");
743     assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
744
745     assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
746     let chars: &[char] = &['1', '2'];
747     assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
748     assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
749 }
750
751 #[test]
752 fn test_trim_matches() {
753     let v: &[char] = &[];
754     assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
755     let chars: &[char] = &['*', ' '];
756     assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
757     assert_eq!(" ***  *** ".trim_matches(chars), "");
758     assert_eq!("foo".trim_matches(chars), "foo");
759
760     assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
761     let chars: &[char] = &['1', '2'];
762     assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
763     assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
764 }
765
766 #[test]
767 fn test_trim_start() {
768     assert_eq!("".trim_start(), "");
769     assert_eq!("a".trim_start(), "a");
770     assert_eq!("    ".trim_start(), "");
771     assert_eq!("     blah".trim_start(), "blah");
772     assert_eq!("   \u{3000}  wut".trim_start(), "wut");
773     assert_eq!("hey ".trim_start(), "hey ");
774 }
775
776 #[test]
777 fn test_trim_end() {
778     assert_eq!("".trim_end(), "");
779     assert_eq!("a".trim_end(), "a");
780     assert_eq!("    ".trim_end(), "");
781     assert_eq!("blah     ".trim_end(), "blah");
782     assert_eq!("wut   \u{3000}  ".trim_end(), "wut");
783     assert_eq!(" hey".trim_end(), " hey");
784 }
785
786 #[test]
787 fn test_trim() {
788     assert_eq!("".trim(), "");
789     assert_eq!("a".trim(), "a");
790     assert_eq!("    ".trim(), "");
791     assert_eq!("    blah     ".trim(), "blah");
792     assert_eq!("\nwut   \u{3000}  ".trim(), "wut");
793     assert_eq!(" hey dude ".trim(), "hey dude");
794 }
795
796 #[test]
797 fn test_is_whitespace() {
798     assert!("".chars().all(|c| c.is_whitespace()));
799     assert!(" ".chars().all(|c| c.is_whitespace()));
800     assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
801     assert!("  \n\t   ".chars().all(|c| c.is_whitespace()));
802     assert!(!"   _   ".chars().all(|c| c.is_whitespace()));
803 }
804
805 #[test]
806 fn test_is_utf8() {
807     // deny overlong encodings
808     assert!(from_utf8(&[0xc0, 0x80]).is_err());
809     assert!(from_utf8(&[0xc0, 0xae]).is_err());
810     assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
811     assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
812     assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
813     assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
814     assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
815
816     // deny surrogates
817     assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
818     assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
819
820     assert!(from_utf8(&[0xC2, 0x80]).is_ok());
821     assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
822     assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
823     assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
824     assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
825     assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
826     assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
827     assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
828 }
829
830 #[test]
831 fn from_utf8_mostly_ascii() {
832     // deny invalid bytes embedded in long stretches of ascii
833     for i in 32..64 {
834         let mut data = [0; 128];
835         data[i] = 0xC0;
836         assert!(from_utf8(&data).is_err());
837         data[i] = 0xC2;
838         assert!(from_utf8(&data).is_err());
839     }
840 }
841
842 #[test]
843 fn from_utf8_error() {
844     macro_rules! test {
845         ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
846             let error = from_utf8($input).unwrap_err();
847             assert_eq!(error.valid_up_to(), $expected_valid_up_to);
848             assert_eq!(error.error_len(), $expected_error_len);
849         }
850     }
851     test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
852     test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
853     test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
854     test!(b"A\xC3\xA9 \xC1", 4, Some(1));
855     test!(b"A\xC3\xA9 \xC2", 4, None);
856     test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
857     test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
858     test!(b"A\xC3\xA9 \xE0", 4, None);
859     test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
860     test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
861     test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
862     test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
863     test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
864     test!(b"A\xC3\xA9 \xF1", 4, None);
865     test!(b"A\xC3\xA9 \xF1\x80", 4, None);
866     test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
867     test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
868     test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
869     test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
870 }
871
872 #[test]
873 fn test_as_bytes() {
874     // no null
875     let v = [
876         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
877         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
878         109
879     ];
880     let b: &[u8] = &[];
881     assert_eq!("".as_bytes(), b);
882     assert_eq!("abc".as_bytes(), b"abc");
883     assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
884 }
885
886 #[test]
887 #[should_panic]
888 fn test_as_bytes_fail() {
889     // Don't double free. (I'm not sure if this exercises the
890     // original problem code path anymore.)
891     let s = String::from("");
892     let _bytes = s.as_bytes();
893     panic!();
894 }
895
896 #[test]
897 fn test_as_ptr() {
898     let buf = "hello".as_ptr();
899     unsafe {
900         assert_eq!(*buf.offset(0), b'h');
901         assert_eq!(*buf.offset(1), b'e');
902         assert_eq!(*buf.offset(2), b'l');
903         assert_eq!(*buf.offset(3), b'l');
904         assert_eq!(*buf.offset(4), b'o');
905     }
906 }
907
908 #[test]
909 fn vec_str_conversions() {
910     let s1: String = String::from("All mimsy were the borogoves");
911
912     let v: Vec<u8> = s1.as_bytes().to_vec();
913     let s2: String = String::from(from_utf8(&v).unwrap());
914     let mut i = 0;
915     let n1 = s1.len();
916     let n2 = v.len();
917     assert_eq!(n1, n2);
918     while i < n1 {
919         let a: u8 = s1.as_bytes()[i];
920         let b: u8 = s2.as_bytes()[i];
921         assert_eq!(a, b);
922         i += 1;
923     }
924 }
925
926 #[test]
927 fn test_contains() {
928     assert!("abcde".contains("bcd"));
929     assert!("abcde".contains("abcd"));
930     assert!("abcde".contains("bcde"));
931     assert!("abcde".contains(""));
932     assert!("".contains(""));
933     assert!(!"abcde".contains("def"));
934     assert!(!"".contains("a"));
935
936     let data = "ประเทศไทย中华Việt Nam";
937     assert!(data.contains("ประเ"));
938     assert!(data.contains("ะเ"));
939     assert!(data.contains("中华"));
940     assert!(!data.contains("ไท华"));
941 }
942
943 #[test]
944 fn test_contains_char() {
945     assert!("abc".contains('b'));
946     assert!("a".contains('a'));
947     assert!(!"abc".contains('d'));
948     assert!(!"".contains('a'));
949 }
950
951 #[test]
952 fn test_split_at() {
953     let s = "ศไทย中华Việt Nam";
954     for (index, _) in s.char_indices() {
955         let (a, b) = s.split_at(index);
956         assert_eq!(&s[..a.len()], a);
957         assert_eq!(&s[a.len()..], b);
958     }
959     let (a, b) = s.split_at(s.len());
960     assert_eq!(a, s);
961     assert_eq!(b, "");
962 }
963
964 #[test]
965 fn test_split_at_mut() {
966     let mut s = "Hello World".to_string();
967     {
968         let (a, b) = s.split_at_mut(5);
969         a.make_ascii_uppercase();
970         b.make_ascii_lowercase();
971     }
972     assert_eq!(s, "HELLO world");
973 }
974
975 #[test]
976 #[should_panic]
977 fn test_split_at_boundscheck() {
978     let s = "ศไทย中华Việt Nam";
979     s.split_at(1);
980 }
981
982 #[test]
983 fn test_escape_unicode() {
984     assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
985     assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
986     assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
987     assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
988     assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
989     assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
990     assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
991     assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
992     assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
993 }
994
995 #[test]
996 fn test_escape_debug() {
997     // Note that there are subtleties with the number of backslashes
998     // on the left- and right-hand sides. In particular, Unicode code points
999     // are usually escaped with two backslashes on the right-hand side, as
1000     // they are escaped. However, when the character is unescaped (e.g., for
1001     // printable characters), only a single backslash appears (as the character
1002     // itself appears in the debug string).
1003     assert_eq!("abc".escape_debug(), "abc");
1004     assert_eq!("a c".escape_debug(), "a c");
1005     assert_eq!("éèê".escape_debug(), "éèê");
1006     assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
1007     assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
1008     assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
1009     assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
1010     assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
1011     assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
1012     assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
1013     assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug(), "\\u{301}a\u{301}bé\\u{e000}");
1014 }
1015
1016 #[test]
1017 fn test_escape_default() {
1018     assert_eq!("abc".escape_default(), "abc");
1019     assert_eq!("a c".escape_default(), "a c");
1020     assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
1021     assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
1022     assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
1023     assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
1024     assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
1025     assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
1026     assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
1027     assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
1028 }
1029
1030 #[test]
1031 fn test_total_ord() {
1032     assert_eq!("1234".cmp("123"), Greater);
1033     assert_eq!("123".cmp("1234"), Less);
1034     assert_eq!("1234".cmp("1234"), Equal);
1035     assert_eq!("12345555".cmp("123456"), Less);
1036     assert_eq!("22".cmp("1234"), Greater);
1037 }
1038
1039 #[test]
1040 fn test_iterator() {
1041     let s = "ศไทย中华Việt Nam";
1042     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1043
1044     let mut pos = 0;
1045     let it = s.chars();
1046
1047     for c in it {
1048         assert_eq!(c, v[pos]);
1049         pos += 1;
1050     }
1051     assert_eq!(pos, v.len());
1052     assert_eq!(s.chars().count(), v.len());
1053 }
1054
1055 #[test]
1056 fn test_rev_iterator() {
1057     let s = "ศไทย中华Việt Nam";
1058     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1059
1060     let mut pos = 0;
1061     let it = s.chars().rev();
1062
1063     for c in it {
1064         assert_eq!(c, v[pos]);
1065         pos += 1;
1066     }
1067     assert_eq!(pos, v.len());
1068 }
1069
1070 #[test]
1071 fn test_chars_decoding() {
1072     let mut bytes = [0; 4];
1073     for c in (0..0x110000).filter_map(std::char::from_u32) {
1074         let s = c.encode_utf8(&mut bytes);
1075         if Some(c) != s.chars().next() {
1076             panic!("character {:x}={} does not decode correctly", c as u32, c);
1077         }
1078     }
1079 }
1080
1081 #[test]
1082 fn test_chars_rev_decoding() {
1083     let mut bytes = [0; 4];
1084     for c in (0..0x110000).filter_map(std::char::from_u32) {
1085         let s = c.encode_utf8(&mut bytes);
1086         if Some(c) != s.chars().rev().next() {
1087             panic!("character {:x}={} does not decode correctly", c as u32, c);
1088         }
1089     }
1090 }
1091
1092 #[test]
1093 fn test_iterator_clone() {
1094     let s = "ศไทย中华Việt Nam";
1095     let mut it = s.chars();
1096     it.next();
1097     assert!(it.clone().zip(it).all(|(x,y)| x == y));
1098 }
1099
1100 #[test]
1101 fn test_iterator_last() {
1102     let s = "ศไทย中华Việt Nam";
1103     let mut it = s.chars();
1104     it.next();
1105     assert_eq!(it.last(), Some('m'));
1106 }
1107
1108 #[test]
1109 fn test_bytesator() {
1110     let s = "ศไทย中华Việt Nam";
1111     let v = [
1112         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1113         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1114         109
1115     ];
1116     let mut pos = 0;
1117
1118     for b in s.bytes() {
1119         assert_eq!(b, v[pos]);
1120         pos += 1;
1121     }
1122 }
1123
1124 #[test]
1125 fn test_bytes_revator() {
1126     let s = "ศไทย中华Việt Nam";
1127     let v = [
1128         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1129         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1130         109
1131     ];
1132     let mut pos = v.len();
1133
1134     for b in s.bytes().rev() {
1135         pos -= 1;
1136         assert_eq!(b, v[pos]);
1137     }
1138 }
1139
1140 #[test]
1141 fn test_bytesator_nth() {
1142     let s = "ศไทย中华Việt Nam";
1143     let v = [
1144         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1145         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1146         109
1147     ];
1148
1149     let mut b = s.bytes();
1150     assert_eq!(b.nth(2).unwrap(), v[2]);
1151     assert_eq!(b.nth(10).unwrap(), v[10]);
1152     assert_eq!(b.nth(200), None);
1153 }
1154
1155 #[test]
1156 fn test_bytesator_count() {
1157     let s = "ศไทย中华Việt Nam";
1158
1159     let b = s.bytes();
1160     assert_eq!(b.count(), 28)
1161 }
1162
1163 #[test]
1164 fn test_bytesator_last() {
1165     let s = "ศไทย中华Việt Nam";
1166
1167     let b = s.bytes();
1168     assert_eq!(b.last().unwrap(), 109)
1169 }
1170
1171 #[test]
1172 fn test_char_indicesator() {
1173     let s = "ศไทย中华Việt Nam";
1174     let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1175     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1176
1177     let mut pos = 0;
1178     let it = s.char_indices();
1179
1180     for c in it {
1181         assert_eq!(c, (p[pos], v[pos]));
1182         pos += 1;
1183     }
1184     assert_eq!(pos, v.len());
1185     assert_eq!(pos, p.len());
1186 }
1187
1188 #[test]
1189 fn test_char_indices_revator() {
1190     let s = "ศไทย中华Việt Nam";
1191     let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1192     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1193
1194     let mut pos = 0;
1195     let it = s.char_indices().rev();
1196
1197     for c in it {
1198         assert_eq!(c, (p[pos], v[pos]));
1199         pos += 1;
1200     }
1201     assert_eq!(pos, v.len());
1202     assert_eq!(pos, p.len());
1203 }
1204
1205 #[test]
1206 fn test_char_indices_last() {
1207     let s = "ศไทย中华Việt Nam";
1208     let mut it = s.char_indices();
1209     it.next();
1210     assert_eq!(it.last(), Some((27, 'm')));
1211 }
1212
1213 #[test]
1214 fn test_splitn_char_iterator() {
1215     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1216
1217     let split: Vec<&str> = data.splitn(4, ' ').collect();
1218     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1219
1220     let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1221     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1222
1223     // Unicode
1224     let split: Vec<&str> = data.splitn(4, 'ä').collect();
1225     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1226
1227     let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1228     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1229 }
1230
1231 #[test]
1232 fn test_split_char_iterator_no_trailing() {
1233     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1234
1235     let split: Vec<&str> = data.split('\n').collect();
1236     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1237
1238     let split: Vec<&str> = data.split_terminator('\n').collect();
1239     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1240 }
1241
1242 #[test]
1243 fn test_rsplit() {
1244     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1245
1246     let split: Vec<&str> = data.rsplit(' ').collect();
1247     assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1248
1249     let split: Vec<&str> = data.rsplit("lämb").collect();
1250     assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1251
1252     let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1253     assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1254 }
1255
1256 #[test]
1257 fn test_rsplitn() {
1258     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1259
1260     let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1261     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1262
1263     let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1264     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1265
1266     let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1267     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1268 }
1269
1270 #[test]
1271 fn test_split_whitespace() {
1272     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
1273     let words: Vec<&str> = data.split_whitespace().collect();
1274     assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1275 }
1276
1277 #[test]
1278 fn test_lines() {
1279     let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1280     let lines: Vec<&str> = data.lines().collect();
1281     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1282
1283     let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1284     let lines: Vec<&str> = data.lines().collect();
1285     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1286 }
1287
1288 #[test]
1289 fn test_splitator() {
1290     fn t(s: &str, sep: &str, u: &[&str]) {
1291         let v: Vec<&str> = s.split(sep).collect();
1292         assert_eq!(v, u);
1293     }
1294     t("--1233345--", "12345", &["--1233345--"]);
1295     t("abc::hello::there", "::", &["abc", "hello", "there"]);
1296     t("::hello::there", "::", &["", "hello", "there"]);
1297     t("hello::there::", "::", &["hello", "there", ""]);
1298     t("::hello::there::", "::", &["", "hello", "there", ""]);
1299     t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1300     t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1301     t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1302     t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1303     t("", ".", &[""]);
1304     t("zz", "zz", &["",""]);
1305     t("ok", "z", &["ok"]);
1306     t("zzz", "zz", &["","z"]);
1307     t("zzzzz", "zz", &["","","z"]);
1308 }
1309
1310 #[test]
1311 fn test_str_default() {
1312     use std::default::Default;
1313
1314     fn t<S: Default + AsRef<str>>() {
1315         let s: S = Default::default();
1316         assert_eq!(s.as_ref(), "");
1317     }
1318
1319     t::<&str>();
1320     t::<String>();
1321     t::<&mut str>();
1322 }
1323
1324 #[test]
1325 fn test_str_container() {
1326     fn sum_len(v: &[&str]) -> usize {
1327         v.iter().map(|x| x.len()).sum()
1328     }
1329
1330     let s = "01234";
1331     assert_eq!(5, sum_len(&["012", "", "34"]));
1332     assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1333     assert_eq!(5, sum_len(&[s]));
1334 }
1335
1336 #[test]
1337 fn test_str_from_utf8() {
1338     let xs = b"hello";
1339     assert_eq!(from_utf8(xs), Ok("hello"));
1340
1341     let xs = "ศไทย中华Việt Nam".as_bytes();
1342     assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1343
1344     let xs = b"hello\xFF";
1345     assert!(from_utf8(xs).is_err());
1346 }
1347
1348 #[test]
1349 fn test_pattern_deref_forward() {
1350     let data = "aabcdaa";
1351     assert!(data.contains("bcd"));
1352     assert!(data.contains(&"bcd"));
1353     assert!(data.contains(&"bcd".to_string()));
1354 }
1355
1356 #[test]
1357 fn test_empty_match_indices() {
1358     let data = "aä中!";
1359     let vec: Vec<_> = data.match_indices("").collect();
1360     assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1361 }
1362
1363 #[test]
1364 fn test_bool_from_str() {
1365     assert_eq!("true".parse().ok(), Some(true));
1366     assert_eq!("false".parse().ok(), Some(false));
1367     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1368 }
1369
1370 fn check_contains_all_substrings(s: &str) {
1371     assert!(s.contains(""));
1372     for i in 0..s.len() {
1373         for j in i+1..=s.len() {
1374             assert!(s.contains(&s[i..j]));
1375         }
1376     }
1377 }
1378
1379 #[test]
1380 fn strslice_issue_16589() {
1381     assert!("bananas".contains("nana"));
1382
1383     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1384     // test all substrings for good measure
1385     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1386 }
1387
1388 #[test]
1389 fn strslice_issue_16878() {
1390     assert!(!"1234567ah012345678901ah".contains("hah"));
1391     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1392 }
1393
1394
1395 #[test]
1396 fn test_strslice_contains() {
1397     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1398     check_contains_all_substrings(x);
1399 }
1400
1401 #[test]
1402 fn test_rsplitn_char_iterator() {
1403     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1404
1405     let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1406     split.reverse();
1407     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1408
1409     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1410     split.reverse();
1411     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1412
1413     // Unicode
1414     let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1415     split.reverse();
1416     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1417
1418     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1419     split.reverse();
1420     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1421 }
1422
1423 #[test]
1424 fn test_split_char_iterator() {
1425     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1426
1427     let split: Vec<&str> = data.split(' ').collect();
1428     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1429
1430     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1431     rsplit.reverse();
1432     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1433
1434     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1435     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1436
1437     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1438     rsplit.reverse();
1439     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1440
1441     // Unicode
1442     let split: Vec<&str> = data.split('ä').collect();
1443     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1444
1445     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1446     rsplit.reverse();
1447     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1448
1449     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1450     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1451
1452     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1453     rsplit.reverse();
1454     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1455 }
1456
1457 #[test]
1458 fn test_rev_split_char_iterator_no_trailing() {
1459     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1460
1461     let mut split: Vec<&str> = data.split('\n').rev().collect();
1462     split.reverse();
1463     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1464
1465     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1466     split.reverse();
1467     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1468 }
1469
1470 #[test]
1471 fn test_utf16_code_units() {
1472     assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
1473                [0xE9, 0xD83D, 0xDCA9])
1474 }
1475
1476 #[test]
1477 fn starts_with_in_unicode() {
1478     assert!(!"├── Cargo.toml".starts_with("# "));
1479 }
1480
1481 #[test]
1482 fn starts_short_long() {
1483     assert!(!"".starts_with("##"));
1484     assert!(!"##".starts_with("####"));
1485     assert!("####".starts_with("##"));
1486     assert!(!"##ä".starts_with("####"));
1487     assert!("####ä".starts_with("##"));
1488     assert!(!"##".starts_with("####ä"));
1489     assert!("##ä##".starts_with("##ä"));
1490
1491     assert!("".starts_with(""));
1492     assert!("ä".starts_with(""));
1493     assert!("#ä".starts_with(""));
1494     assert!("##ä".starts_with(""));
1495     assert!("ä###".starts_with(""));
1496     assert!("#ä##".starts_with(""));
1497     assert!("##ä#".starts_with(""));
1498 }
1499
1500 #[test]
1501 fn contains_weird_cases() {
1502     assert!("* \t".contains(' '));
1503     assert!(!"* \t".contains('?'));
1504     assert!(!"* \t".contains('\u{1F4A9}'));
1505 }
1506
1507 #[test]
1508 fn trim_ws() {
1509     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1510                     "a \t  ");
1511     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1512                " \t  a");
1513     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1514                     "a \t  ");
1515     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1516                " \t  a");
1517     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()),
1518                     "a");
1519     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1520                          "");
1521     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1522                "");
1523     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1524                          "");
1525     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1526                "");
1527     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()),
1528                "");
1529 }
1530
1531 #[test]
1532 fn to_lowercase() {
1533     assert_eq!("".to_lowercase(), "");
1534     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1535
1536     // https://github.com/rust-lang/rust/issues/26035
1537     assert_eq!("ΑΣ".to_lowercase(), "ας");
1538     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1539     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1540
1541     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1542     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1543     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1544
1545     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1546     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1547
1548     assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1549     assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1550
1551     assert_eq!("Α Σ".to_lowercase(), "α σ");
1552     assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1553     assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1554
1555     assert_eq!("Σ".to_lowercase(), "σ");
1556     assert_eq!("'Σ".to_lowercase(), "'σ");
1557     assert_eq!("''Σ".to_lowercase(), "''σ");
1558
1559     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1560     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1561     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1562 }
1563
1564 #[test]
1565 fn to_uppercase() {
1566     assert_eq!("".to_uppercase(), "");
1567     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1568 }
1569
1570 #[test]
1571 fn test_into_string() {
1572     // The only way to acquire a Box<str> in the first place is through a String, so just
1573     // test that we can round-trip between Box<str> and String.
1574     let string = String::from("Some text goes here");
1575     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1576 }
1577
1578 #[test]
1579 fn test_box_slice_clone() {
1580     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1581     let data2 = data.clone().into_boxed_str().clone().into_string();
1582
1583     assert_eq!(data, data2);
1584 }
1585
1586 #[test]
1587 fn test_cow_from() {
1588     let borrowed = "borrowed";
1589     let owned = String::from("owned");
1590     match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1591         (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1592         _ => panic!("invalid `Cow::from`"),
1593     }
1594 }
1595
1596 #[test]
1597 fn test_repeat() {
1598     assert_eq!("".repeat(3), "");
1599     assert_eq!("abc".repeat(0), "");
1600     assert_eq!("α".repeat(3), "ααα");
1601 }
1602
1603 mod pattern {
1604     use std::str::pattern::{
1605         Pattern, Searcher, ReverseSearcher,
1606         SearchStep::{self, Match, Reject, Done},
1607     };
1608
1609     macro_rules! make_test {
1610         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1611             #[allow(unused_imports)]
1612             mod $name {
1613                 use std::str::pattern::SearchStep::{Match, Reject};
1614                 use super::{cmp_search_to_vec};
1615                 #[test]
1616                 fn fwd() {
1617                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1618                 }
1619                 #[test]
1620                 fn bwd() {
1621                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1622                 }
1623             }
1624         }
1625     }
1626
1627     fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1628                                              right: Vec<SearchStep>)
1629     where P::Searcher: ReverseSearcher<'a>
1630     {
1631         let mut searcher = pat.into_searcher(haystack);
1632         let mut v = vec![];
1633         loop {
1634             match if !rev {searcher.next()} else {searcher.next_back()} {
1635                 Match(a, b) => v.push(Match(a, b)),
1636                 Reject(a, b) => v.push(Reject(a, b)),
1637                 Done => break,
1638             }
1639         }
1640         if rev {
1641             v.reverse();
1642         }
1643
1644         let mut first_index = 0;
1645         let mut err = None;
1646
1647         for (i, e) in right.iter().enumerate() {
1648             match *e {
1649                 Match(a, b) | Reject(a, b)
1650                 if a <= b && a == first_index => {
1651                     first_index = b;
1652                 }
1653                 _ => {
1654                     err = Some(i);
1655                     break;
1656                 }
1657             }
1658         }
1659
1660         if let Some(err) = err {
1661             panic!("Input skipped range at {}", err);
1662         }
1663
1664         if first_index != haystack.len() {
1665             panic!("Did not cover whole input");
1666         }
1667
1668         assert_eq!(v, right);
1669     }
1670
1671     make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1672         Reject(0, 1),
1673         Match (1, 3),
1674         Reject(3, 4),
1675         Match (4, 6),
1676         Reject(6, 7),
1677     ]);
1678     make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1679         Reject(0, 1),
1680         Match (1, 3),
1681         Reject(3, 4),
1682         Match (4, 6),
1683         Match (6, 8),
1684         Reject(8, 9),
1685     ]);
1686     make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1687         Match (0, 0),
1688         Reject(0, 1),
1689         Match (1, 1),
1690         Reject(1, 2),
1691         Match (2, 2),
1692         Reject(2, 3),
1693         Match (3, 3),
1694         Reject(3, 4),
1695         Match (4, 4),
1696         Reject(4, 5),
1697         Match (5, 5),
1698         Reject(5, 6),
1699         Match (6, 6),
1700         Reject(6, 7),
1701         Match (7, 7),
1702     ]);
1703     make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1704         Reject(0, 3),
1705         Reject(3, 6),
1706         Reject(6, 9),
1707     ]);
1708     make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1709         Match (0, 0),
1710         Reject(0, 3),
1711         Match (3, 3),
1712         Reject(3, 6),
1713         Match (6, 6),
1714         Reject(6, 9),
1715         Match (9, 9),
1716     ]);
1717     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1718         Match(0, 0),
1719     ]);
1720     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1721     ]);
1722     make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1723         Reject(0, 1),
1724         Match (1, 2),
1725         Match (2, 3),
1726         Reject(3, 4),
1727         Match (4, 5),
1728         Match (5, 6),
1729         Reject(6, 7),
1730     ]);
1731     make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1732         Reject(0, 3),
1733         Reject(3, 6),
1734         Reject(6, 9),
1735     ]);
1736     make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1737         Reject(0, 1),
1738         Reject(1, 2),
1739         Reject(2, 3),
1740     ]);
1741
1742 }
1743
1744 macro_rules! generate_iterator_test {
1745     {
1746         $name:ident {
1747             $(
1748                 ($($arg:expr),*) -> [$($t:tt)*];
1749             )*
1750         }
1751         with $fwd:expr, $bwd:expr;
1752     } => {
1753         #[test]
1754         fn $name() {
1755             $(
1756                 {
1757                     let res = vec![$($t)*];
1758
1759                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1760                     assert_eq!(fwd_vec, res);
1761
1762                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1763                     bwd_vec.reverse();
1764                     assert_eq!(bwd_vec, res);
1765                 }
1766             )*
1767         }
1768     };
1769     {
1770         $name:ident {
1771             $(
1772                 ($($arg:expr),*) -> [$($t:tt)*];
1773             )*
1774         }
1775         with $fwd:expr;
1776     } => {
1777         #[test]
1778         fn $name() {
1779             $(
1780                 {
1781                     let res = vec![$($t)*];
1782
1783                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1784                     assert_eq!(fwd_vec, res);
1785                 }
1786             )*
1787         }
1788     }
1789 }
1790
1791 generate_iterator_test! {
1792     double_ended_split {
1793         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1794         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1795     }
1796     with str::split, str::rsplit;
1797 }
1798
1799 generate_iterator_test! {
1800     double_ended_split_terminator {
1801         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1802     }
1803     with str::split_terminator, str::rsplit_terminator;
1804 }
1805
1806 generate_iterator_test! {
1807     double_ended_matches {
1808         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1809     }
1810     with str::matches, str::rmatches;
1811 }
1812
1813 generate_iterator_test! {
1814     double_ended_match_indices {
1815         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1816     }
1817     with str::match_indices, str::rmatch_indices;
1818 }
1819
1820 generate_iterator_test! {
1821     not_double_ended_splitn {
1822         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1823     }
1824     with str::splitn;
1825 }
1826
1827 generate_iterator_test! {
1828     not_double_ended_rsplitn {
1829         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1830     }
1831     with str::rsplitn;
1832 }
1833
1834 #[test]
1835 fn different_str_pattern_forwarding_lifetimes() {
1836     use std::str::pattern::Pattern;
1837
1838     fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
1839         for _ in 0..3 {
1840             "asdf".find(&p);
1841         }
1842     }
1843
1844     foo::<&str>("x");
1845 }