]> git.lizzy.rs Git - rust.git/blob - src/liballoc/tests/str.rs
Auto merge of #63124 - Centril:rollup-onohtqt, r=Centril
[rust.git] / src / liballoc / tests / str.rs
1 use std::borrow::Cow;
2 use std::cmp::Ordering::{Equal, Greater, Less};
3 use std::str::from_utf8;
4
5 #[test]
6 fn test_le() {
7     assert!("" <= "");
8     assert!("" <= "foo");
9     assert!("foo" <= "foo");
10     assert_ne!("foo", "bar");
11 }
12
13 #[test]
14 fn test_find() {
15     assert_eq!("hello".find('l'), Some(2));
16     assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
17     assert!("hello".find('x').is_none());
18     assert!("hello".find(|c:char| c == 'x').is_none());
19     assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
20     assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
21 }
22
23 #[test]
24 fn test_rfind() {
25     assert_eq!("hello".rfind('l'), Some(3));
26     assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
27     assert!("hello".rfind('x').is_none());
28     assert!("hello".rfind(|c:char| c == 'x').is_none());
29     assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
30     assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
31 }
32
33 #[test]
34 fn test_collect() {
35     let empty = "";
36     let s: String = empty.chars().collect();
37     assert_eq!(empty, s);
38     let data = "ประเทศไทย中";
39     let s: String = data.chars().collect();
40     assert_eq!(data, s);
41 }
42
43 #[test]
44 fn test_into_bytes() {
45     let data = String::from("asdf");
46     let buf = data.into_bytes();
47     assert_eq!(buf, b"asdf");
48 }
49
50 #[test]
51 fn test_find_str() {
52     // byte positions
53     assert_eq!("".find(""), Some(0));
54     assert!("banana".find("apple pie").is_none());
55
56     let data = "abcabc";
57     assert_eq!(data[0..6].find("ab"), Some(0));
58     assert_eq!(data[2..6].find("ab"), Some(3 - 2));
59     assert!(data[2..4].find("ab").is_none());
60
61     let string = "ประเทศไทย中华Việt Nam";
62     let mut data = String::from(string);
63     data.push_str(string);
64     assert!(data.find("ไท华").is_none());
65     assert_eq!(data[0..43].find(""), Some(0));
66     assert_eq!(data[6..43].find(""), Some(6 - 6));
67
68     assert_eq!(data[0..43].find("ประ"), Some( 0));
69     assert_eq!(data[0..43].find("ทศไ"), Some(12));
70     assert_eq!(data[0..43].find("ย中"), Some(24));
71     assert_eq!(data[0..43].find("iệt"), Some(34));
72     assert_eq!(data[0..43].find("Nam"), Some(40));
73
74     assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
75     assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
76     assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
77     assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
78     assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
79
80     // find every substring -- assert that it finds it, or an earlier occurrence.
81     let string = "Việt Namacbaabcaabaaba";
82     for (i, ci) in string.char_indices() {
83         let ip = i + ci.len_utf8();
84         for j in string[ip..].char_indices()
85                              .map(|(i, _)| i)
86                              .chain(Some(string.len() - ip))
87         {
88             let pat = &string[i..ip + j];
89             assert!(match string.find(pat) {
90                 None => false,
91                 Some(x) => x <= i,
92             });
93             assert!(match string.rfind(pat) {
94                 None => false,
95                 Some(x) => x >= i,
96             });
97         }
98     }
99 }
100
101 fn s(x: &str) -> String { x.to_string() }
102
103 macro_rules! test_concat {
104     ($expected: expr, $string: expr) => {
105         {
106             let s: String = $string.concat();
107             assert_eq!($expected, s);
108         }
109     }
110 }
111
112 #[test]
113 fn test_concat_for_different_types() {
114     test_concat!("ab", vec![s("a"), s("b")]);
115     test_concat!("ab", vec!["a", "b"]);
116 }
117
118 #[test]
119 fn test_concat_for_different_lengths() {
120     let empty: &[&str] = &[];
121     test_concat!("", empty);
122     test_concat!("a", ["a"]);
123     test_concat!("ab", ["a", "b"]);
124     test_concat!("abc", ["", "a", "bc"]);
125 }
126
127 macro_rules! test_join {
128     ($expected: expr, $string: expr, $delim: expr) => {
129         {
130             let s = $string.join($delim);
131             assert_eq!($expected, s);
132         }
133     }
134 }
135
136 #[test]
137 fn test_join_for_different_types() {
138     test_join!("a-b", ["a", "b"], "-");
139     let hyphen = "-".to_string();
140     test_join!("a-b", [s("a"), s("b")], &*hyphen);
141     test_join!("a-b", vec!["a", "b"], &*hyphen);
142     test_join!("a-b", &*vec!["a", "b"], "-");
143     test_join!("a-b", vec![s("a"), s("b")], "-");
144 }
145
146 #[test]
147 fn test_join_for_different_lengths() {
148     let empty: &[&str] = &[];
149     test_join!("", empty, "-");
150     test_join!("a", ["a"], "-");
151     test_join!("a-b", ["a", "b"], "-");
152     test_join!("-a-bc", ["", "a", "bc"], "-");
153 }
154
155 // join has fast paths for small separators up to 4 bytes
156 // this tests the slow paths.
157 #[test]
158 fn test_join_for_different_lengths_with_long_separator() {
159     assert_eq!("~~~~~".len(), 15);
160
161     let empty: &[&str] = &[];
162     test_join!("", empty, "~~~~~");
163     test_join!("a", ["a"], "~~~~~");
164     test_join!("a~~~~~b", ["a", "b"], "~~~~~");
165     test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~");
166 }
167
168 #[test]
169 #[cfg(not(miri))] // Miri is too slow
170 fn test_unsafe_slice() {
171     assert_eq!("ab", unsafe {"abc".get_unchecked(0..2)});
172     assert_eq!("bc", unsafe {"abc".get_unchecked(1..3)});
173     assert_eq!("", unsafe {"abc".get_unchecked(1..1)});
174     fn a_million_letter_a() -> String {
175         let mut i = 0;
176         let mut rs = String::new();
177         while i < 100000 {
178             rs.push_str("aaaaaaaaaa");
179             i += 1;
180         }
181         rs
182     }
183     fn half_a_million_letter_a() -> String {
184         let mut i = 0;
185         let mut rs = String::new();
186         while i < 100000 {
187             rs.push_str("aaaaa");
188             i += 1;
189         }
190         rs
191     }
192     let letters = a_million_letter_a();
193     assert_eq!(half_a_million_letter_a(),
194         unsafe { letters.get_unchecked(0..500000)});
195 }
196
197 #[test]
198 fn test_starts_with() {
199     assert!("".starts_with(""));
200     assert!("abc".starts_with(""));
201     assert!("abc".starts_with("a"));
202     assert!(!"a".starts_with("abc"));
203     assert!(!"".starts_with("abc"));
204     assert!(!"ödd".starts_with("-"));
205     assert!("ödd".starts_with("öd"));
206 }
207
208 #[test]
209 fn test_ends_with() {
210     assert!("".ends_with(""));
211     assert!("abc".ends_with(""));
212     assert!("abc".ends_with("c"));
213     assert!(!"a".ends_with("abc"));
214     assert!(!"".ends_with("abc"));
215     assert!(!"ddö".ends_with("-"));
216     assert!("ddö".ends_with("dö"));
217 }
218
219 #[test]
220 fn test_is_empty() {
221     assert!("".is_empty());
222     assert!(!"a".is_empty());
223 }
224
225 #[test]
226 fn test_replacen() {
227     assert_eq!("".replacen('a', "b", 5), "");
228     assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
229     assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
230
231     let test = "test";
232     assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
233     assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
234     assert_eq!(" test test ".replacen(test, "", 5), "   ");
235
236     assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
237 }
238
239 #[test]
240 fn test_replace() {
241     let a = "a";
242     assert_eq!("".replace(a, "b"), "");
243     assert_eq!("a".replace(a, "b"), "b");
244     assert_eq!("ab".replace(a, "b"), "bb");
245     let test = "test";
246     assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
247     assert_eq!(" test test ".replace(test, ""), "   ");
248 }
249
250 #[test]
251 fn test_replace_2a() {
252     let data = "ประเทศไทย中华";
253     let repl = "دولة الكويت";
254
255     let a = "ประเ";
256     let a2 = "دولة الكويتทศไทย中华";
257     assert_eq!(data.replace(a, repl), a2);
258 }
259
260 #[test]
261 fn test_replace_2b() {
262     let data = "ประเทศไทย中华";
263     let repl = "دولة الكويت";
264
265     let b = "ะเ";
266     let b2 = "ปรدولة الكويتทศไทย中华";
267     assert_eq!(data.replace(b, repl), b2);
268 }
269
270 #[test]
271 fn test_replace_2c() {
272     let data = "ประเทศไทย中华";
273     let repl = "دولة الكويت";
274
275     let c = "中华";
276     let c2 = "ประเทศไทยدولة الكويت";
277     assert_eq!(data.replace(c, repl), c2);
278 }
279
280 #[test]
281 fn test_replace_2d() {
282     let data = "ประเทศไทย中华";
283     let repl = "دولة الكويت";
284
285     let d = "ไท华";
286     assert_eq!(data.replace(d, repl), data);
287 }
288
289 #[test]
290 fn test_replace_pattern() {
291     let data = "abcdαβγδabcdαβγδ";
292     assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
293     assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
294     assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
295     assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
296 }
297
298 // The current implementation of SliceIndex fails to handle methods
299 // orthogonally from range types; therefore, it is worth testing
300 // all of the indexing operations on each input.
301 mod slice_index {
302     // Test a slicing operation **that should succeed,**
303     // testing it on all of the indexing methods.
304     //
305     // This is not suitable for testing failure on invalid inputs.
306     macro_rules! assert_range_eq {
307         ($s:expr, $range:expr, $expected:expr)
308         => {
309             let mut s: String = $s.to_owned();
310             let mut expected: String = $expected.to_owned();
311             {
312                 let s: &str = &s;
313                 let expected: &str = &expected;
314
315                 assert_eq!(&s[$range], expected, "(in assertion for: index)");
316                 assert_eq!(s.get($range), Some(expected), "(in assertion for: get)");
317                 unsafe {
318                     assert_eq!(
319                         s.get_unchecked($range), expected,
320                         "(in assertion for: get_unchecked)",
321                     );
322                 }
323             }
324             {
325                 let s: &mut str = &mut s;
326                 let expected: &mut str = &mut expected;
327
328                 assert_eq!(
329                     &mut s[$range], expected,
330                     "(in assertion for: index_mut)",
331                 );
332                 assert_eq!(
333                     s.get_mut($range), Some(&mut expected[..]),
334                     "(in assertion for: get_mut)",
335                 );
336                 unsafe {
337                     assert_eq!(
338                         s.get_unchecked_mut($range), expected,
339                         "(in assertion for: get_unchecked_mut)",
340                     );
341                 }
342             }
343         }
344     }
345
346     // Make sure the macro can actually detect bugs,
347     // because if it can't, then what are we even doing here?
348     //
349     // (Be aware this only demonstrates the ability to detect bugs
350     //  in the FIRST method that panics, as the macro is not designed
351     //  to be used in `should_panic`)
352     #[test]
353     #[should_panic(expected = "out of bounds")]
354     fn assert_range_eq_can_fail_by_panic() {
355         assert_range_eq!("abc", 0..5, "abc");
356     }
357
358     // (Be aware this only demonstrates the ability to detect bugs
359     //  in the FIRST method it calls, as the macro is not designed
360     //  to be used in `should_panic`)
361     #[test]
362     #[should_panic(expected = "==")]
363     fn assert_range_eq_can_fail_by_inequality() {
364         assert_range_eq!("abc", 0..2, "abc");
365     }
366
367     // Generates test cases for bad index operations.
368     //
369     // This generates `should_panic` test cases for Index/IndexMut
370     // and `None` test cases for get/get_mut.
371     macro_rules! panic_cases {
372         ($(
373             in mod $case_name:ident {
374                 data: $data:expr;
375
376                 // optional:
377                 //
378                 // a similar input for which DATA[input] succeeds, and the corresponding
379                 // output str. This helps validate "critical points" where an input range
380                 // straddles the boundary between valid and invalid.
381                 // (such as the input `len..len`, which is just barely valid)
382                 $(
383                     good: data[$good:expr] == $output:expr;
384                 )*
385
386                 bad: data[$bad:expr];
387                 message: $expect_msg:expr; // must be a literal
388             }
389         )*) => {$(
390             mod $case_name {
391                 #[test]
392                 fn pass() {
393                     let mut v: String = $data.into();
394
395                     $( assert_range_eq!(v, $good, $output); )*
396
397                     {
398                         let v: &str = &v;
399                         assert_eq!(v.get($bad), None, "(in None assertion for get)");
400                     }
401
402                     {
403                         let v: &mut str = &mut v;
404                         assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
405                     }
406                 }
407
408                 #[test]
409                 #[should_panic(expected = $expect_msg)]
410                 fn index_fail() {
411                     let v: String = $data.into();
412                     let v: &str = &v;
413                     let _v = &v[$bad];
414                 }
415
416                 #[test]
417                 #[should_panic(expected = $expect_msg)]
418                 fn index_mut_fail() {
419                     let mut v: String = $data.into();
420                     let v: &mut str = &mut v;
421                     let _v = &mut v[$bad];
422                 }
423             }
424         )*};
425     }
426
427     #[test]
428     fn simple_ascii() {
429         assert_range_eq!("abc", .., "abc");
430
431         assert_range_eq!("abc", 0..2, "ab");
432         assert_range_eq!("abc", 0..=1, "ab");
433         assert_range_eq!("abc", ..2, "ab");
434         assert_range_eq!("abc", ..=1, "ab");
435
436         assert_range_eq!("abc", 1..3, "bc");
437         assert_range_eq!("abc", 1..=2, "bc");
438         assert_range_eq!("abc", 1..1, "");
439         assert_range_eq!("abc", 1..=0, "");
440     }
441
442     #[test]
443     fn simple_unicode() {
444         // 日本
445         assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
446
447         assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
448         assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
449         assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
450         assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
451
452         assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
453         assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
454         assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
455
456         let data = "ประเทศไทย中华";
457         assert_range_eq!(data, 0..3, "ป");
458         assert_range_eq!(data, 3..6, "ร");
459         assert_range_eq!(data, 3..3, "");
460         assert_range_eq!(data, 30..33, "华");
461
462         /*0: 中
463           3: 华
464           6: V
465           7: i
466           8: ệ
467          11: t
468          12:
469          13: N
470          14: a
471          15: m */
472         let ss = "中华Việt Nam";
473         assert_range_eq!(ss, 3..6, "华");
474         assert_range_eq!(ss, 6..16, "Việt Nam");
475         assert_range_eq!(ss, 6..=15, "Việt Nam");
476         assert_range_eq!(ss, 6.., "Việt Nam");
477
478         assert_range_eq!(ss, 0..3, "中");
479         assert_range_eq!(ss, 3..7, "华V");
480         assert_range_eq!(ss, 3..=6, "华V");
481         assert_range_eq!(ss, 3..3, "");
482         assert_range_eq!(ss, 3..=2, "");
483     }
484
485     #[test]
486     #[cfg(not(target_arch = "asmjs"))] // hits an OOM
487     #[cfg(not(miri))] // Miri is too slow
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().to_string(), "\\u{61}\\u{62}\\u{63}");
985     assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
986     assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
987     assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
988     assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
989     assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
990     assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
991     assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
992     assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\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().to_string(), "abc");
1004     assert_eq!("a c".escape_debug().to_string(), "a c");
1005     assert_eq!("éèê".escape_debug().to_string(), "éèê");
1006     assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1007     assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1008     assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1009     assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1010     assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1011     assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1012     assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1013     assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1014                "\\u{301}a\u{301}bé\\u{e000}");
1015 }
1016
1017 #[test]
1018 fn test_escape_default() {
1019     assert_eq!("abc".escape_default().to_string(), "abc");
1020     assert_eq!("a c".escape_default().to_string(), "a c");
1021     assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1022     assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1023     assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1024     assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1025     assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1026     assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1027     assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1028     assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1029 }
1030
1031 #[test]
1032 fn test_total_ord() {
1033     assert_eq!("1234".cmp("123"), Greater);
1034     assert_eq!("123".cmp("1234"), Less);
1035     assert_eq!("1234".cmp("1234"), Equal);
1036     assert_eq!("12345555".cmp("123456"), Less);
1037     assert_eq!("22".cmp("1234"), Greater);
1038 }
1039
1040 #[test]
1041 fn test_iterator() {
1042     let s = "ศไทย中华Việt Nam";
1043     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1044
1045     let mut pos = 0;
1046     let it = s.chars();
1047
1048     for c in it {
1049         assert_eq!(c, v[pos]);
1050         pos += 1;
1051     }
1052     assert_eq!(pos, v.len());
1053     assert_eq!(s.chars().count(), v.len());
1054 }
1055
1056 #[test]
1057 fn test_rev_iterator() {
1058     let s = "ศไทย中华Việt Nam";
1059     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1060
1061     let mut pos = 0;
1062     let it = s.chars().rev();
1063
1064     for c in it {
1065         assert_eq!(c, v[pos]);
1066         pos += 1;
1067     }
1068     assert_eq!(pos, v.len());
1069 }
1070
1071 #[test]
1072 #[cfg(not(miri))] // Miri is too slow
1073 fn test_chars_decoding() {
1074     let mut bytes = [0; 4];
1075     for c in (0..0x110000).filter_map(std::char::from_u32) {
1076         let s = c.encode_utf8(&mut bytes);
1077         if Some(c) != s.chars().next() {
1078             panic!("character {:x}={} does not decode correctly", c as u32, c);
1079         }
1080     }
1081 }
1082
1083 #[test]
1084 #[cfg(not(miri))] // Miri is too slow
1085 fn test_chars_rev_decoding() {
1086     let mut bytes = [0; 4];
1087     for c in (0..0x110000).filter_map(std::char::from_u32) {
1088         let s = c.encode_utf8(&mut bytes);
1089         if Some(c) != s.chars().rev().next() {
1090             panic!("character {:x}={} does not decode correctly", c as u32, c);
1091         }
1092     }
1093 }
1094
1095 #[test]
1096 fn test_iterator_clone() {
1097     let s = "ศไทย中华Việt Nam";
1098     let mut it = s.chars();
1099     it.next();
1100     assert!(it.clone().zip(it).all(|(x,y)| x == y));
1101 }
1102
1103 #[test]
1104 fn test_iterator_last() {
1105     let s = "ศไทย中华Việt Nam";
1106     let mut it = s.chars();
1107     it.next();
1108     assert_eq!(it.last(), Some('m'));
1109 }
1110
1111 #[test]
1112 fn test_chars_debug() {
1113     let s = "ศไทย中华Việt Nam";
1114     let c = s.chars();
1115     assert_eq!(
1116         format!("{:?}", c),
1117         r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"#
1118     );
1119 }
1120
1121 #[test]
1122 fn test_bytesator() {
1123     let s = "ศไทย中华Việt Nam";
1124     let v = [
1125         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1126         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1127         109
1128     ];
1129     let mut pos = 0;
1130
1131     for b in s.bytes() {
1132         assert_eq!(b, v[pos]);
1133         pos += 1;
1134     }
1135 }
1136
1137 #[test]
1138 fn test_bytes_revator() {
1139     let s = "ศไทย中华Việt Nam";
1140     let v = [
1141         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1142         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1143         109
1144     ];
1145     let mut pos = v.len();
1146
1147     for b in s.bytes().rev() {
1148         pos -= 1;
1149         assert_eq!(b, v[pos]);
1150     }
1151 }
1152
1153 #[test]
1154 fn test_bytesator_nth() {
1155     let s = "ศไทย中华Việt Nam";
1156     let v = [
1157         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1158         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1159         109
1160     ];
1161
1162     let mut b = s.bytes();
1163     assert_eq!(b.nth(2).unwrap(), v[2]);
1164     assert_eq!(b.nth(10).unwrap(), v[10]);
1165     assert_eq!(b.nth(200), None);
1166 }
1167
1168 #[test]
1169 fn test_bytesator_count() {
1170     let s = "ศไทย中华Việt Nam";
1171
1172     let b = s.bytes();
1173     assert_eq!(b.count(), 28)
1174 }
1175
1176 #[test]
1177 fn test_bytesator_last() {
1178     let s = "ศไทย中华Việt Nam";
1179
1180     let b = s.bytes();
1181     assert_eq!(b.last().unwrap(), 109)
1182 }
1183
1184 #[test]
1185 fn test_char_indicesator() {
1186     let s = "ศไทย中华Việt Nam";
1187     let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1188     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1189
1190     let mut pos = 0;
1191     let it = s.char_indices();
1192
1193     for c in it {
1194         assert_eq!(c, (p[pos], v[pos]));
1195         pos += 1;
1196     }
1197     assert_eq!(pos, v.len());
1198     assert_eq!(pos, p.len());
1199 }
1200
1201 #[test]
1202 fn test_char_indices_revator() {
1203     let s = "ศไทย中华Việt Nam";
1204     let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1205     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1206
1207     let mut pos = 0;
1208     let it = s.char_indices().rev();
1209
1210     for c in it {
1211         assert_eq!(c, (p[pos], v[pos]));
1212         pos += 1;
1213     }
1214     assert_eq!(pos, v.len());
1215     assert_eq!(pos, p.len());
1216 }
1217
1218 #[test]
1219 fn test_char_indices_last() {
1220     let s = "ศไทย中华Việt Nam";
1221     let mut it = s.char_indices();
1222     it.next();
1223     assert_eq!(it.last(), Some((27, 'm')));
1224 }
1225
1226 #[test]
1227 fn test_splitn_char_iterator() {
1228     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1229
1230     let split: Vec<&str> = data.splitn(4, ' ').collect();
1231     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1232
1233     let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1234     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1235
1236     // Unicode
1237     let split: Vec<&str> = data.splitn(4, 'ä').collect();
1238     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1239
1240     let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1241     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1242 }
1243
1244 #[test]
1245 fn test_split_char_iterator_no_trailing() {
1246     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1247
1248     let split: Vec<&str> = data.split('\n').collect();
1249     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1250
1251     let split: Vec<&str> = data.split_terminator('\n').collect();
1252     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1253 }
1254
1255 #[test]
1256 fn test_rsplit() {
1257     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1258
1259     let split: Vec<&str> = data.rsplit(' ').collect();
1260     assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1261
1262     let split: Vec<&str> = data.rsplit("lämb").collect();
1263     assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1264
1265     let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1266     assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1267 }
1268
1269 #[test]
1270 fn test_rsplitn() {
1271     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1272
1273     let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1274     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1275
1276     let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1277     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1278
1279     let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1280     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1281 }
1282
1283 #[test]
1284 fn test_split_whitespace() {
1285     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
1286     let words: Vec<&str> = data.split_whitespace().collect();
1287     assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1288 }
1289
1290 #[test]
1291 fn test_lines() {
1292     let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1293     let lines: Vec<&str> = data.lines().collect();
1294     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1295
1296     let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1297     let lines: Vec<&str> = data.lines().collect();
1298     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1299 }
1300
1301 #[test]
1302 fn test_splitator() {
1303     fn t(s: &str, sep: &str, u: &[&str]) {
1304         let v: Vec<&str> = s.split(sep).collect();
1305         assert_eq!(v, u);
1306     }
1307     t("--1233345--", "12345", &["--1233345--"]);
1308     t("abc::hello::there", "::", &["abc", "hello", "there"]);
1309     t("::hello::there", "::", &["", "hello", "there"]);
1310     t("hello::there::", "::", &["hello", "there", ""]);
1311     t("::hello::there::", "::", &["", "hello", "there", ""]);
1312     t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1313     t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1314     t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1315     t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1316     t("", ".", &[""]);
1317     t("zz", "zz", &["",""]);
1318     t("ok", "z", &["ok"]);
1319     t("zzz", "zz", &["","z"]);
1320     t("zzzzz", "zz", &["","","z"]);
1321 }
1322
1323 #[test]
1324 fn test_str_default() {
1325     use std::default::Default;
1326
1327     fn t<S: Default + AsRef<str>>() {
1328         let s: S = Default::default();
1329         assert_eq!(s.as_ref(), "");
1330     }
1331
1332     t::<&str>();
1333     t::<String>();
1334     t::<&mut str>();
1335 }
1336
1337 #[test]
1338 fn test_str_container() {
1339     fn sum_len(v: &[&str]) -> usize {
1340         v.iter().map(|x| x.len()).sum()
1341     }
1342
1343     let s = "01234";
1344     assert_eq!(5, sum_len(&["012", "", "34"]));
1345     assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1346     assert_eq!(5, sum_len(&[s]));
1347 }
1348
1349 #[test]
1350 fn test_str_from_utf8() {
1351     let xs = b"hello";
1352     assert_eq!(from_utf8(xs), Ok("hello"));
1353
1354     let xs = "ศไทย中华Việt Nam".as_bytes();
1355     assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1356
1357     let xs = b"hello\xFF";
1358     assert!(from_utf8(xs).is_err());
1359 }
1360
1361 #[test]
1362 fn test_pattern_deref_forward() {
1363     let data = "aabcdaa";
1364     assert!(data.contains("bcd"));
1365     assert!(data.contains(&"bcd"));
1366     assert!(data.contains(&"bcd".to_string()));
1367 }
1368
1369 #[test]
1370 fn test_empty_match_indices() {
1371     let data = "aä中!";
1372     let vec: Vec<_> = data.match_indices("").collect();
1373     assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1374 }
1375
1376 #[test]
1377 fn test_bool_from_str() {
1378     assert_eq!("true".parse().ok(), Some(true));
1379     assert_eq!("false".parse().ok(), Some(false));
1380     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1381 }
1382
1383 #[cfg(not(miri))] // Miri is too slow
1384 fn check_contains_all_substrings(s: &str) {
1385     assert!(s.contains(""));
1386     for i in 0..s.len() {
1387         for j in i+1..=s.len() {
1388             assert!(s.contains(&s[i..j]));
1389         }
1390     }
1391 }
1392
1393 #[test]
1394 #[cfg(not(miri))] // Miri is too slow
1395 fn strslice_issue_16589() {
1396     assert!("bananas".contains("nana"));
1397
1398     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1399     // test all substrings for good measure
1400     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1401 }
1402
1403 #[test]
1404 fn strslice_issue_16878() {
1405     assert!(!"1234567ah012345678901ah".contains("hah"));
1406     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1407 }
1408
1409
1410 #[test]
1411 #[cfg(not(miri))] // Miri is too slow
1412 fn test_strslice_contains() {
1413     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1414     check_contains_all_substrings(x);
1415 }
1416
1417 #[test]
1418 fn test_rsplitn_char_iterator() {
1419     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1420
1421     let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1422     split.reverse();
1423     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1424
1425     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1426     split.reverse();
1427     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1428
1429     // Unicode
1430     let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1431     split.reverse();
1432     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1433
1434     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1435     split.reverse();
1436     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1437 }
1438
1439 #[test]
1440 fn test_split_char_iterator() {
1441     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1442
1443     let split: Vec<&str> = data.split(' ').collect();
1444     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1445
1446     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1447     rsplit.reverse();
1448     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1449
1450     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1451     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1452
1453     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1454     rsplit.reverse();
1455     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1456
1457     // Unicode
1458     let split: Vec<&str> = data.split('ä').collect();
1459     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1460
1461     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1462     rsplit.reverse();
1463     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1464
1465     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1466     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1467
1468     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1469     rsplit.reverse();
1470     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1471 }
1472
1473 #[test]
1474 fn test_rev_split_char_iterator_no_trailing() {
1475     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1476
1477     let mut split: Vec<&str> = data.split('\n').rev().collect();
1478     split.reverse();
1479     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1480
1481     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1482     split.reverse();
1483     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1484 }
1485
1486 #[test]
1487 fn test_utf16_code_units() {
1488     assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
1489                [0xE9, 0xD83D, 0xDCA9])
1490 }
1491
1492 #[test]
1493 fn starts_with_in_unicode() {
1494     assert!(!"├── Cargo.toml".starts_with("# "));
1495 }
1496
1497 #[test]
1498 fn starts_short_long() {
1499     assert!(!"".starts_with("##"));
1500     assert!(!"##".starts_with("####"));
1501     assert!("####".starts_with("##"));
1502     assert!(!"##ä".starts_with("####"));
1503     assert!("####ä".starts_with("##"));
1504     assert!(!"##".starts_with("####ä"));
1505     assert!("##ä##".starts_with("##ä"));
1506
1507     assert!("".starts_with(""));
1508     assert!("ä".starts_with(""));
1509     assert!("#ä".starts_with(""));
1510     assert!("##ä".starts_with(""));
1511     assert!("ä###".starts_with(""));
1512     assert!("#ä##".starts_with(""));
1513     assert!("##ä#".starts_with(""));
1514 }
1515
1516 #[test]
1517 fn contains_weird_cases() {
1518     assert!("* \t".contains(' '));
1519     assert!(!"* \t".contains('?'));
1520     assert!(!"* \t".contains('\u{1F4A9}'));
1521 }
1522
1523 #[test]
1524 fn trim_ws() {
1525     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1526                     "a \t  ");
1527     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1528                " \t  a");
1529     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1530                     "a \t  ");
1531     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1532                " \t  a");
1533     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()),
1534                     "a");
1535     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1536                          "");
1537     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1538                "");
1539     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1540                          "");
1541     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1542                "");
1543     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()),
1544                "");
1545 }
1546
1547 #[test]
1548 fn to_lowercase() {
1549     assert_eq!("".to_lowercase(), "");
1550     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1551
1552     // https://github.com/rust-lang/rust/issues/26035
1553     assert_eq!("ΑΣ".to_lowercase(), "ας");
1554     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1555     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1556
1557     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1558     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1559     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1560
1561     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1562     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1563
1564     assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1565     assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1566
1567     assert_eq!("Α Σ".to_lowercase(), "α σ");
1568     assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1569     assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1570
1571     assert_eq!("Σ".to_lowercase(), "σ");
1572     assert_eq!("'Σ".to_lowercase(), "'σ");
1573     assert_eq!("''Σ".to_lowercase(), "''σ");
1574
1575     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1576     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1577     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1578 }
1579
1580 #[test]
1581 fn to_uppercase() {
1582     assert_eq!("".to_uppercase(), "");
1583     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1584 }
1585
1586 #[test]
1587 fn test_into_string() {
1588     // The only way to acquire a Box<str> in the first place is through a String, so just
1589     // test that we can round-trip between Box<str> and String.
1590     let string = String::from("Some text goes here");
1591     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1592 }
1593
1594 #[test]
1595 fn test_box_slice_clone() {
1596     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1597     let data2 = data.clone().into_boxed_str().clone().into_string();
1598
1599     assert_eq!(data, data2);
1600 }
1601
1602 #[test]
1603 fn test_cow_from() {
1604     let borrowed = "borrowed";
1605     let owned = String::from("owned");
1606     match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1607         (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1608         _ => panic!("invalid `Cow::from`"),
1609     }
1610 }
1611
1612 #[test]
1613 fn test_repeat() {
1614     assert_eq!("".repeat(3), "");
1615     assert_eq!("abc".repeat(0), "");
1616     assert_eq!("α".repeat(3), "ααα");
1617 }
1618
1619 mod pattern {
1620     use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
1621     use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1622
1623     macro_rules! make_test {
1624         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1625             #[allow(unused_imports)]
1626             mod $name {
1627                 use std::str::pattern::SearchStep::{Match, Reject};
1628                 use super::{cmp_search_to_vec};
1629                 #[test]
1630                 fn fwd() {
1631                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1632                 }
1633                 #[test]
1634                 fn bwd() {
1635                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1636                 }
1637             }
1638         }
1639     }
1640
1641     fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1642                                              right: Vec<SearchStep>)
1643     where P::Searcher: ReverseSearcher<'a>
1644     {
1645         let mut searcher = pat.into_searcher(haystack);
1646         let mut v = vec![];
1647         loop {
1648             match if !rev {searcher.next()} else {searcher.next_back()} {
1649                 Match(a, b) => v.push(Match(a, b)),
1650                 Reject(a, b) => v.push(Reject(a, b)),
1651                 Done => break,
1652             }
1653         }
1654         if rev {
1655             v.reverse();
1656         }
1657
1658         let mut first_index = 0;
1659         let mut err = None;
1660
1661         for (i, e) in right.iter().enumerate() {
1662             match *e {
1663                 Match(a, b) | Reject(a, b)
1664                 if a <= b && a == first_index => {
1665                     first_index = b;
1666                 }
1667                 _ => {
1668                     err = Some(i);
1669                     break;
1670                 }
1671             }
1672         }
1673
1674         if let Some(err) = err {
1675             panic!("Input skipped range at {}", err);
1676         }
1677
1678         if first_index != haystack.len() {
1679             panic!("Did not cover whole input");
1680         }
1681
1682         assert_eq!(v, right);
1683     }
1684
1685     make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1686         Reject(0, 1),
1687         Match (1, 3),
1688         Reject(3, 4),
1689         Match (4, 6),
1690         Reject(6, 7),
1691     ]);
1692     make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1693         Reject(0, 1),
1694         Match (1, 3),
1695         Reject(3, 4),
1696         Match (4, 6),
1697         Match (6, 8),
1698         Reject(8, 9),
1699     ]);
1700     make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1701         Match (0, 0),
1702         Reject(0, 1),
1703         Match (1, 1),
1704         Reject(1, 2),
1705         Match (2, 2),
1706         Reject(2, 3),
1707         Match (3, 3),
1708         Reject(3, 4),
1709         Match (4, 4),
1710         Reject(4, 5),
1711         Match (5, 5),
1712         Reject(5, 6),
1713         Match (6, 6),
1714         Reject(6, 7),
1715         Match (7, 7),
1716     ]);
1717     make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1718         Reject(0, 3),
1719         Reject(3, 6),
1720         Reject(6, 9),
1721     ]);
1722     make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1723         Match (0, 0),
1724         Reject(0, 3),
1725         Match (3, 3),
1726         Reject(3, 6),
1727         Match (6, 6),
1728         Reject(6, 9),
1729         Match (9, 9),
1730     ]);
1731     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1732         Match(0, 0),
1733     ]);
1734     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1735     ]);
1736     make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1737         Reject(0, 1),
1738         Match (1, 2),
1739         Match (2, 3),
1740         Reject(3, 4),
1741         Match (4, 5),
1742         Match (5, 6),
1743         Reject(6, 7),
1744     ]);
1745     make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1746         Reject(0, 3),
1747         Reject(3, 6),
1748         Reject(6, 9),
1749     ]);
1750     make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1751         Reject(0, 1),
1752         Reject(1, 2),
1753         Reject(2, 3),
1754     ]);
1755
1756 }
1757
1758 macro_rules! generate_iterator_test {
1759     {
1760         $name:ident {
1761             $(
1762                 ($($arg:expr),*) -> [$($t:tt)*];
1763             )*
1764         }
1765         with $fwd:expr, $bwd:expr;
1766     } => {
1767         #[test]
1768         fn $name() {
1769             $(
1770                 {
1771                     let res = vec![$($t)*];
1772
1773                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1774                     assert_eq!(fwd_vec, res);
1775
1776                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1777                     bwd_vec.reverse();
1778                     assert_eq!(bwd_vec, res);
1779                 }
1780             )*
1781         }
1782     };
1783     {
1784         $name:ident {
1785             $(
1786                 ($($arg:expr),*) -> [$($t:tt)*];
1787             )*
1788         }
1789         with $fwd:expr;
1790     } => {
1791         #[test]
1792         fn $name() {
1793             $(
1794                 {
1795                     let res = vec![$($t)*];
1796
1797                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1798                     assert_eq!(fwd_vec, res);
1799                 }
1800             )*
1801         }
1802     }
1803 }
1804
1805 generate_iterator_test! {
1806     double_ended_split {
1807         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1808         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1809     }
1810     with str::split, str::rsplit;
1811 }
1812
1813 generate_iterator_test! {
1814     double_ended_split_terminator {
1815         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1816     }
1817     with str::split_terminator, str::rsplit_terminator;
1818 }
1819
1820 generate_iterator_test! {
1821     double_ended_matches {
1822         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1823     }
1824     with str::matches, str::rmatches;
1825 }
1826
1827 generate_iterator_test! {
1828     double_ended_match_indices {
1829         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1830     }
1831     with str::match_indices, str::rmatch_indices;
1832 }
1833
1834 generate_iterator_test! {
1835     not_double_ended_splitn {
1836         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1837     }
1838     with str::splitn;
1839 }
1840
1841 generate_iterator_test! {
1842     not_double_ended_rsplitn {
1843         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1844     }
1845     with str::rsplitn;
1846 }
1847
1848 #[test]
1849 fn different_str_pattern_forwarding_lifetimes() {
1850     use std::str::pattern::Pattern;
1851
1852     fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
1853         for _ in 0..3 {
1854             "asdf".find(&p);
1855         }
1856     }
1857
1858     foo::<&str>("x");
1859 }