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