]> git.lizzy.rs Git - rust.git/blob - src/liballoc/tests/str.rs
Auto merge of #63089 - kennytm:use-try-run-for-linkchecker, r=Mark-Simulacrum
[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_bytesator() {
1113     let s = "ศไทย中华Việt Nam";
1114     let v = [
1115         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1116         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1117         109
1118     ];
1119     let mut pos = 0;
1120
1121     for b in s.bytes() {
1122         assert_eq!(b, v[pos]);
1123         pos += 1;
1124     }
1125 }
1126
1127 #[test]
1128 fn test_bytes_revator() {
1129     let s = "ศไทย中华Việt Nam";
1130     let v = [
1131         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1132         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1133         109
1134     ];
1135     let mut pos = v.len();
1136
1137     for b in s.bytes().rev() {
1138         pos -= 1;
1139         assert_eq!(b, v[pos]);
1140     }
1141 }
1142
1143 #[test]
1144 fn test_bytesator_nth() {
1145     let s = "ศไทย中华Việt Nam";
1146     let v = [
1147         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1148         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1149         109
1150     ];
1151
1152     let mut b = s.bytes();
1153     assert_eq!(b.nth(2).unwrap(), v[2]);
1154     assert_eq!(b.nth(10).unwrap(), v[10]);
1155     assert_eq!(b.nth(200), None);
1156 }
1157
1158 #[test]
1159 fn test_bytesator_count() {
1160     let s = "ศไทย中华Việt Nam";
1161
1162     let b = s.bytes();
1163     assert_eq!(b.count(), 28)
1164 }
1165
1166 #[test]
1167 fn test_bytesator_last() {
1168     let s = "ศไทย中华Việt Nam";
1169
1170     let b = s.bytes();
1171     assert_eq!(b.last().unwrap(), 109)
1172 }
1173
1174 #[test]
1175 fn test_char_indicesator() {
1176     let s = "ศไทย中华Việt Nam";
1177     let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1178     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1179
1180     let mut pos = 0;
1181     let it = s.char_indices();
1182
1183     for c in it {
1184         assert_eq!(c, (p[pos], v[pos]));
1185         pos += 1;
1186     }
1187     assert_eq!(pos, v.len());
1188     assert_eq!(pos, p.len());
1189 }
1190
1191 #[test]
1192 fn test_char_indices_revator() {
1193     let s = "ศไทย中华Việt Nam";
1194     let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1195     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1196
1197     let mut pos = 0;
1198     let it = s.char_indices().rev();
1199
1200     for c in it {
1201         assert_eq!(c, (p[pos], v[pos]));
1202         pos += 1;
1203     }
1204     assert_eq!(pos, v.len());
1205     assert_eq!(pos, p.len());
1206 }
1207
1208 #[test]
1209 fn test_char_indices_last() {
1210     let s = "ศไทย中华Việt Nam";
1211     let mut it = s.char_indices();
1212     it.next();
1213     assert_eq!(it.last(), Some((27, 'm')));
1214 }
1215
1216 #[test]
1217 fn test_splitn_char_iterator() {
1218     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1219
1220     let split: Vec<&str> = data.splitn(4, ' ').collect();
1221     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1222
1223     let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1224     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1225
1226     // Unicode
1227     let split: Vec<&str> = data.splitn(4, 'ä').collect();
1228     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1229
1230     let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1231     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1232 }
1233
1234 #[test]
1235 fn test_split_char_iterator_no_trailing() {
1236     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1237
1238     let split: Vec<&str> = data.split('\n').collect();
1239     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1240
1241     let split: Vec<&str> = data.split_terminator('\n').collect();
1242     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1243 }
1244
1245 #[test]
1246 fn test_rsplit() {
1247     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1248
1249     let split: Vec<&str> = data.rsplit(' ').collect();
1250     assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1251
1252     let split: Vec<&str> = data.rsplit("lämb").collect();
1253     assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1254
1255     let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1256     assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1257 }
1258
1259 #[test]
1260 fn test_rsplitn() {
1261     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1262
1263     let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1264     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1265
1266     let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1267     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1268
1269     let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1270     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1271 }
1272
1273 #[test]
1274 fn test_split_whitespace() {
1275     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
1276     let words: Vec<&str> = data.split_whitespace().collect();
1277     assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1278 }
1279
1280 #[test]
1281 fn test_lines() {
1282     let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1283     let lines: Vec<&str> = data.lines().collect();
1284     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1285
1286     let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1287     let lines: Vec<&str> = data.lines().collect();
1288     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1289 }
1290
1291 #[test]
1292 fn test_splitator() {
1293     fn t(s: &str, sep: &str, u: &[&str]) {
1294         let v: Vec<&str> = s.split(sep).collect();
1295         assert_eq!(v, u);
1296     }
1297     t("--1233345--", "12345", &["--1233345--"]);
1298     t("abc::hello::there", "::", &["abc", "hello", "there"]);
1299     t("::hello::there", "::", &["", "hello", "there"]);
1300     t("hello::there::", "::", &["hello", "there", ""]);
1301     t("::hello::there::", "::", &["", "hello", "there", ""]);
1302     t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1303     t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1304     t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1305     t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1306     t("", ".", &[""]);
1307     t("zz", "zz", &["",""]);
1308     t("ok", "z", &["ok"]);
1309     t("zzz", "zz", &["","z"]);
1310     t("zzzzz", "zz", &["","","z"]);
1311 }
1312
1313 #[test]
1314 fn test_str_default() {
1315     use std::default::Default;
1316
1317     fn t<S: Default + AsRef<str>>() {
1318         let s: S = Default::default();
1319         assert_eq!(s.as_ref(), "");
1320     }
1321
1322     t::<&str>();
1323     t::<String>();
1324     t::<&mut str>();
1325 }
1326
1327 #[test]
1328 fn test_str_container() {
1329     fn sum_len(v: &[&str]) -> usize {
1330         v.iter().map(|x| x.len()).sum()
1331     }
1332
1333     let s = "01234";
1334     assert_eq!(5, sum_len(&["012", "", "34"]));
1335     assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1336     assert_eq!(5, sum_len(&[s]));
1337 }
1338
1339 #[test]
1340 fn test_str_from_utf8() {
1341     let xs = b"hello";
1342     assert_eq!(from_utf8(xs), Ok("hello"));
1343
1344     let xs = "ศไทย中华Việt Nam".as_bytes();
1345     assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1346
1347     let xs = b"hello\xFF";
1348     assert!(from_utf8(xs).is_err());
1349 }
1350
1351 #[test]
1352 fn test_pattern_deref_forward() {
1353     let data = "aabcdaa";
1354     assert!(data.contains("bcd"));
1355     assert!(data.contains(&"bcd"));
1356     assert!(data.contains(&"bcd".to_string()));
1357 }
1358
1359 #[test]
1360 fn test_empty_match_indices() {
1361     let data = "aä中!";
1362     let vec: Vec<_> = data.match_indices("").collect();
1363     assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1364 }
1365
1366 #[test]
1367 fn test_bool_from_str() {
1368     assert_eq!("true".parse().ok(), Some(true));
1369     assert_eq!("false".parse().ok(), Some(false));
1370     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1371 }
1372
1373 #[cfg(not(miri))] // Miri is too slow
1374 fn check_contains_all_substrings(s: &str) {
1375     assert!(s.contains(""));
1376     for i in 0..s.len() {
1377         for j in i+1..=s.len() {
1378             assert!(s.contains(&s[i..j]));
1379         }
1380     }
1381 }
1382
1383 #[test]
1384 #[cfg(not(miri))] // Miri is too slow
1385 fn strslice_issue_16589() {
1386     assert!("bananas".contains("nana"));
1387
1388     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1389     // test all substrings for good measure
1390     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1391 }
1392
1393 #[test]
1394 fn strslice_issue_16878() {
1395     assert!(!"1234567ah012345678901ah".contains("hah"));
1396     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1397 }
1398
1399
1400 #[test]
1401 #[cfg(not(miri))] // Miri is too slow
1402 fn test_strslice_contains() {
1403     let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1404     check_contains_all_substrings(x);
1405 }
1406
1407 #[test]
1408 fn test_rsplitn_char_iterator() {
1409     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1410
1411     let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1412     split.reverse();
1413     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1414
1415     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1416     split.reverse();
1417     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1418
1419     // Unicode
1420     let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1421     split.reverse();
1422     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1423
1424     let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1425     split.reverse();
1426     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1427 }
1428
1429 #[test]
1430 fn test_split_char_iterator() {
1431     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1432
1433     let split: Vec<&str> = data.split(' ').collect();
1434     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1435
1436     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1437     rsplit.reverse();
1438     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1439
1440     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1441     assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1442
1443     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1444     rsplit.reverse();
1445     assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1446
1447     // Unicode
1448     let split: Vec<&str> = data.split('ä').collect();
1449     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1450
1451     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1452     rsplit.reverse();
1453     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1454
1455     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1456     assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1457
1458     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1459     rsplit.reverse();
1460     assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1461 }
1462
1463 #[test]
1464 fn test_rev_split_char_iterator_no_trailing() {
1465     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1466
1467     let mut split: Vec<&str> = data.split('\n').rev().collect();
1468     split.reverse();
1469     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1470
1471     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1472     split.reverse();
1473     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1474 }
1475
1476 #[test]
1477 fn test_utf16_code_units() {
1478     assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(),
1479                [0xE9, 0xD83D, 0xDCA9])
1480 }
1481
1482 #[test]
1483 fn starts_with_in_unicode() {
1484     assert!(!"├── Cargo.toml".starts_with("# "));
1485 }
1486
1487 #[test]
1488 fn starts_short_long() {
1489     assert!(!"".starts_with("##"));
1490     assert!(!"##".starts_with("####"));
1491     assert!("####".starts_with("##"));
1492     assert!(!"##ä".starts_with("####"));
1493     assert!("####ä".starts_with("##"));
1494     assert!(!"##".starts_with("####ä"));
1495     assert!("##ä##".starts_with("##ä"));
1496
1497     assert!("".starts_with(""));
1498     assert!("ä".starts_with(""));
1499     assert!("#ä".starts_with(""));
1500     assert!("##ä".starts_with(""));
1501     assert!("ä###".starts_with(""));
1502     assert!("#ä##".starts_with(""));
1503     assert!("##ä#".starts_with(""));
1504 }
1505
1506 #[test]
1507 fn contains_weird_cases() {
1508     assert!("* \t".contains(' '));
1509     assert!(!"* \t".contains('?'));
1510     assert!(!"* \t".contains('\u{1F4A9}'));
1511 }
1512
1513 #[test]
1514 fn trim_ws() {
1515     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1516                     "a \t  ");
1517     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1518                " \t  a");
1519     assert_eq!(" \t  a \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1520                     "a \t  ");
1521     assert_eq!(" \t  a \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1522                " \t  a");
1523     assert_eq!(" \t  a \t  ".trim_matches(|c: char| c.is_whitespace()),
1524                     "a");
1525     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1526                          "");
1527     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1528                "");
1529     assert_eq!(" \t   \t  ".trim_start_matches(|c: char| c.is_whitespace()),
1530                          "");
1531     assert_eq!(" \t   \t  ".trim_end_matches(|c: char| c.is_whitespace()),
1532                "");
1533     assert_eq!(" \t   \t  ".trim_matches(|c: char| c.is_whitespace()),
1534                "");
1535 }
1536
1537 #[test]
1538 fn to_lowercase() {
1539     assert_eq!("".to_lowercase(), "");
1540     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1541
1542     // https://github.com/rust-lang/rust/issues/26035
1543     assert_eq!("ΑΣ".to_lowercase(), "ας");
1544     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1545     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1546
1547     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1548     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1549     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1550
1551     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1552     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1553
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     assert_eq!("''Σ".to_lowercase(), "''σ");
1564
1565     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1566     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1567     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1568 }
1569
1570 #[test]
1571 fn to_uppercase() {
1572     assert_eq!("".to_uppercase(), "");
1573     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1574 }
1575
1576 #[test]
1577 fn test_into_string() {
1578     // The only way to acquire a Box<str> in the first place is through a String, so just
1579     // test that we can round-trip between Box<str> and String.
1580     let string = String::from("Some text goes here");
1581     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1582 }
1583
1584 #[test]
1585 fn test_box_slice_clone() {
1586     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1587     let data2 = data.clone().into_boxed_str().clone().into_string();
1588
1589     assert_eq!(data, data2);
1590 }
1591
1592 #[test]
1593 fn test_cow_from() {
1594     let borrowed = "borrowed";
1595     let owned = String::from("owned");
1596     match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1597         (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1598         _ => panic!("invalid `Cow::from`"),
1599     }
1600 }
1601
1602 #[test]
1603 fn test_repeat() {
1604     assert_eq!("".repeat(3), "");
1605     assert_eq!("abc".repeat(0), "");
1606     assert_eq!("α".repeat(3), "ααα");
1607 }
1608
1609 mod pattern {
1610     use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
1611     use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1612
1613     macro_rules! make_test {
1614         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1615             #[allow(unused_imports)]
1616             mod $name {
1617                 use std::str::pattern::SearchStep::{Match, Reject};
1618                 use super::{cmp_search_to_vec};
1619                 #[test]
1620                 fn fwd() {
1621                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1622                 }
1623                 #[test]
1624                 fn bwd() {
1625                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1626                 }
1627             }
1628         }
1629     }
1630
1631     fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1632                                              right: Vec<SearchStep>)
1633     where P::Searcher: ReverseSearcher<'a>
1634     {
1635         let mut searcher = pat.into_searcher(haystack);
1636         let mut v = vec![];
1637         loop {
1638             match if !rev {searcher.next()} else {searcher.next_back()} {
1639                 Match(a, b) => v.push(Match(a, b)),
1640                 Reject(a, b) => v.push(Reject(a, b)),
1641                 Done => break,
1642             }
1643         }
1644         if rev {
1645             v.reverse();
1646         }
1647
1648         let mut first_index = 0;
1649         let mut err = None;
1650
1651         for (i, e) in right.iter().enumerate() {
1652             match *e {
1653                 Match(a, b) | Reject(a, b)
1654                 if a <= b && a == first_index => {
1655                     first_index = b;
1656                 }
1657                 _ => {
1658                     err = Some(i);
1659                     break;
1660                 }
1661             }
1662         }
1663
1664         if let Some(err) = err {
1665             panic!("Input skipped range at {}", err);
1666         }
1667
1668         if first_index != haystack.len() {
1669             panic!("Did not cover whole input");
1670         }
1671
1672         assert_eq!(v, right);
1673     }
1674
1675     make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1676         Reject(0, 1),
1677         Match (1, 3),
1678         Reject(3, 4),
1679         Match (4, 6),
1680         Reject(6, 7),
1681     ]);
1682     make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1683         Reject(0, 1),
1684         Match (1, 3),
1685         Reject(3, 4),
1686         Match (4, 6),
1687         Match (6, 8),
1688         Reject(8, 9),
1689     ]);
1690     make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1691         Match (0, 0),
1692         Reject(0, 1),
1693         Match (1, 1),
1694         Reject(1, 2),
1695         Match (2, 2),
1696         Reject(2, 3),
1697         Match (3, 3),
1698         Reject(3, 4),
1699         Match (4, 4),
1700         Reject(4, 5),
1701         Match (5, 5),
1702         Reject(5, 6),
1703         Match (6, 6),
1704         Reject(6, 7),
1705         Match (7, 7),
1706     ]);
1707     make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1708         Reject(0, 3),
1709         Reject(3, 6),
1710         Reject(6, 9),
1711     ]);
1712     make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1713         Match (0, 0),
1714         Reject(0, 3),
1715         Match (3, 3),
1716         Reject(3, 6),
1717         Match (6, 6),
1718         Reject(6, 9),
1719         Match (9, 9),
1720     ]);
1721     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1722         Match(0, 0),
1723     ]);
1724     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1725     ]);
1726     make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1727         Reject(0, 1),
1728         Match (1, 2),
1729         Match (2, 3),
1730         Reject(3, 4),
1731         Match (4, 5),
1732         Match (5, 6),
1733         Reject(6, 7),
1734     ]);
1735     make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1736         Reject(0, 3),
1737         Reject(3, 6),
1738         Reject(6, 9),
1739     ]);
1740     make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1741         Reject(0, 1),
1742         Reject(1, 2),
1743         Reject(2, 3),
1744     ]);
1745
1746 }
1747
1748 macro_rules! generate_iterator_test {
1749     {
1750         $name:ident {
1751             $(
1752                 ($($arg:expr),*) -> [$($t:tt)*];
1753             )*
1754         }
1755         with $fwd:expr, $bwd:expr;
1756     } => {
1757         #[test]
1758         fn $name() {
1759             $(
1760                 {
1761                     let res = vec![$($t)*];
1762
1763                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1764                     assert_eq!(fwd_vec, res);
1765
1766                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1767                     bwd_vec.reverse();
1768                     assert_eq!(bwd_vec, res);
1769                 }
1770             )*
1771         }
1772     };
1773     {
1774         $name:ident {
1775             $(
1776                 ($($arg:expr),*) -> [$($t:tt)*];
1777             )*
1778         }
1779         with $fwd:expr;
1780     } => {
1781         #[test]
1782         fn $name() {
1783             $(
1784                 {
1785                     let res = vec![$($t)*];
1786
1787                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1788                     assert_eq!(fwd_vec, res);
1789                 }
1790             )*
1791         }
1792     }
1793 }
1794
1795 generate_iterator_test! {
1796     double_ended_split {
1797         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1798         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1799     }
1800     with str::split, str::rsplit;
1801 }
1802
1803 generate_iterator_test! {
1804     double_ended_split_terminator {
1805         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1806     }
1807     with str::split_terminator, str::rsplit_terminator;
1808 }
1809
1810 generate_iterator_test! {
1811     double_ended_matches {
1812         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1813     }
1814     with str::matches, str::rmatches;
1815 }
1816
1817 generate_iterator_test! {
1818     double_ended_match_indices {
1819         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1820     }
1821     with str::match_indices, str::rmatch_indices;
1822 }
1823
1824 generate_iterator_test! {
1825     not_double_ended_splitn {
1826         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1827     }
1828     with str::splitn;
1829 }
1830
1831 generate_iterator_test! {
1832     not_double_ended_rsplitn {
1833         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1834     }
1835     with str::rsplitn;
1836 }
1837
1838 #[test]
1839 fn different_str_pattern_forwarding_lifetimes() {
1840     use std::str::pattern::Pattern;
1841
1842     fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
1843         for _ in 0..3 {
1844             "asdf".find(&p);
1845         }
1846     }
1847
1848     foo::<&str>("x");
1849 }