]> git.lizzy.rs Git - rust.git/blob - src/liballoc/tests/str.rs
review failures in binary_heap, str, vec_deque
[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 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     #[cfg(not(miri))] // Miri does not support panics
355     fn assert_range_eq_can_fail_by_panic() {
356         assert_range_eq!("abc", 0..5, "abc");
357     }
358
359     // (Be aware this only demonstrates the ability to detect bugs
360     //  in the FIRST method it calls, as the macro is not designed
361     //  to be used in `should_panic`)
362     #[test]
363     #[should_panic(expected = "==")]
364     #[cfg(not(miri))] // Miri does not support panics
365     fn assert_range_eq_can_fail_by_inequality() {
366         assert_range_eq!("abc", 0..2, "abc");
367     }
368
369     // Generates test cases for bad index operations.
370     //
371     // This generates `should_panic` test cases for Index/IndexMut
372     // and `None` test cases for get/get_mut.
373     macro_rules! panic_cases {
374         ($(
375             in mod $case_name:ident {
376                 data: $data:expr;
377
378                 // optional:
379                 //
380                 // a similar input for which DATA[input] succeeds, and the corresponding
381                 // output str. This helps validate "critical points" where an input range
382                 // straddles the boundary between valid and invalid.
383                 // (such as the input `len..len`, which is just barely valid)
384                 $(
385                     good: data[$good:expr] == $output:expr;
386                 )*
387
388                 bad: data[$bad:expr];
389                 message: $expect_msg:expr; // must be a literal
390             }
391         )*) => {$(
392             mod $case_name {
393                 #[test]
394                 fn pass() {
395                     let mut v: String = $data.into();
396
397                     $( assert_range_eq!(v, $good, $output); )*
398
399                     {
400                         let v: &str = &v;
401                         assert_eq!(v.get($bad), None, "(in None assertion for get)");
402                     }
403
404                     {
405                         let v: &mut str = &mut v;
406                         assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)");
407                     }
408                 }
409
410                 #[test]
411                 #[should_panic(expected = $expect_msg)]
412                 #[cfg(not(miri))] // Miri does not support panics
413                 fn index_fail() {
414                     let v: String = $data.into();
415                     let v: &str = &v;
416                     let _v = &v[$bad];
417                 }
418
419                 #[test]
420                 #[should_panic(expected = $expect_msg)]
421                 #[cfg(not(miri))] // Miri does not support panics
422                 fn index_mut_fail() {
423                     let mut v: String = $data.into();
424                     let v: &mut str = &mut v;
425                     let _v = &mut v[$bad];
426                 }
427             }
428         )*};
429     }
430
431     #[test]
432     fn simple_ascii() {
433         assert_range_eq!("abc", .., "abc");
434
435         assert_range_eq!("abc", 0..2, "ab");
436         assert_range_eq!("abc", 0..=1, "ab");
437         assert_range_eq!("abc", ..2, "ab");
438         assert_range_eq!("abc", ..=1, "ab");
439
440         assert_range_eq!("abc", 1..3, "bc");
441         assert_range_eq!("abc", 1..=2, "bc");
442         assert_range_eq!("abc", 1..1, "");
443         assert_range_eq!("abc", 1..=0, "");
444     }
445
446     #[test]
447     fn simple_unicode() {
448         // 日本
449         assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}");
450
451         assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}");
452         assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}");
453         assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}");
454         assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}");
455
456         assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}");
457         assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}");
458         assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}");
459
460         let data = "ประเทศไทย中华";
461         assert_range_eq!(data, 0..3, "ป");
462         assert_range_eq!(data, 3..6, "ร");
463         assert_range_eq!(data, 3..3, "");
464         assert_range_eq!(data, 30..33, "华");
465
466         /*0: 中
467           3: 华
468           6: V
469           7: i
470           8: ệ
471          11: t
472          12:
473          13: N
474          14: a
475          15: m */
476         let ss = "中华Việt Nam";
477         assert_range_eq!(ss, 3..6, "华");
478         assert_range_eq!(ss, 6..16, "Việt Nam");
479         assert_range_eq!(ss, 6..=15, "Việt Nam");
480         assert_range_eq!(ss, 6.., "Việt Nam");
481
482         assert_range_eq!(ss, 0..3, "中");
483         assert_range_eq!(ss, 3..7, "华V");
484         assert_range_eq!(ss, 3..=6, "华V");
485         assert_range_eq!(ss, 3..3, "");
486         assert_range_eq!(ss, 3..=2, "");
487     }
488
489     #[test]
490     #[cfg(not(target_arch = "asmjs"))] // hits an OOM
491     #[cfg(not(miri))] // Miri is too slow
492     fn simple_big() {
493         fn a_million_letter_x() -> String {
494             let mut i = 0;
495             let mut rs = String::new();
496             while i < 100000 {
497                 rs.push_str("华华华华华华华华华华");
498                 i += 1;
499             }
500             rs
501         }
502         fn half_a_million_letter_x() -> String {
503             let mut i = 0;
504             let mut rs = String::new();
505             while i < 100000 {
506                 rs.push_str("华华华华华");
507                 i += 1;
508             }
509             rs
510         }
511         let letters = a_million_letter_x();
512         assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x());
513     }
514
515     #[test]
516     #[should_panic]
517     #[cfg(not(miri))] // Miri does not support panics
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     #[cfg(not(miri))] // Miri does not support panics
670     fn test_slice_fail_truncated_1() {
671         &LOREM_PARAGRAPH[..1024];
672     }
673     // check the truncation in the panic message
674     #[test]
675     #[should_panic(expected="luctus, im`[...]")]
676     #[cfg(not(miri))] // Miri does not support panics
677     fn test_slice_fail_truncated_2() {
678         &LOREM_PARAGRAPH[..1024];
679     }
680 }
681
682 #[test]
683 fn test_str_slice_rangetoinclusive_ok() {
684     let s = "abcαβγ";
685     assert_eq!(&s[..=2], "abc");
686     assert_eq!(&s[..=4], "abcα");
687 }
688
689 #[test]
690 #[should_panic]
691 #[cfg(not(miri))] // Miri does not support panics
692 fn test_str_slice_rangetoinclusive_notok() {
693     let s = "abcαβγ";
694     &s[..=3];
695 }
696
697 #[test]
698 fn test_str_slicemut_rangetoinclusive_ok() {
699     let mut s = "abcαβγ".to_owned();
700     let s: &mut str = &mut s;
701     assert_eq!(&mut s[..=2], "abc");
702     assert_eq!(&mut s[..=4], "abcα");
703 }
704
705 #[test]
706 #[should_panic]
707 #[cfg(not(miri))] // Miri does not support panics
708 fn test_str_slicemut_rangetoinclusive_notok() {
709     let mut s = "abcαβγ".to_owned();
710     let s: &mut str = &mut s;
711     &mut s[..=3];
712 }
713
714 #[test]
715 fn test_is_char_boundary() {
716     let s = "ศไทย中华Việt Nam β-release 🐱123";
717     assert!(s.is_char_boundary(0));
718     assert!(s.is_char_boundary(s.len()));
719     assert!(!s.is_char_boundary(s.len() + 1));
720     for (i, ch) in s.char_indices() {
721         // ensure character locations are boundaries and continuation bytes are not
722         assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
723         for j in 1..ch.len_utf8() {
724             assert!(!s.is_char_boundary(i + j),
725                     "{} should not be a char boundary in {:?}", i + j, s);
726         }
727     }
728 }
729
730 #[test]
731 fn test_trim_start_matches() {
732     let v: &[char] = &[];
733     assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** ");
734     let chars: &[char] = &['*', ' '];
735     assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** ");
736     assert_eq!(" ***  *** ".trim_start_matches(chars), "");
737     assert_eq!("foo *** ".trim_start_matches(chars), "foo *** ");
738
739     assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11");
740     let chars: &[char] = &['1', '2'];
741     assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12");
742     assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123");
743 }
744
745 #[test]
746 fn test_trim_end_matches() {
747     let v: &[char] = &[];
748     assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** ");
749     let chars: &[char] = &['*', ' '];
750     assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo");
751     assert_eq!(" ***  *** ".trim_end_matches(chars), "");
752     assert_eq!(" *** foo".trim_end_matches(chars), " *** foo");
753
754     assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar");
755     let chars: &[char] = &['1', '2'];
756     assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar");
757     assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar");
758 }
759
760 #[test]
761 fn test_trim_matches() {
762     let v: &[char] = &[];
763     assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
764     let chars: &[char] = &['*', ' '];
765     assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
766     assert_eq!(" ***  *** ".trim_matches(chars), "");
767     assert_eq!("foo".trim_matches(chars), "foo");
768
769     assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
770     let chars: &[char] = &['1', '2'];
771     assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
772     assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
773 }
774
775 #[test]
776 fn test_trim_start() {
777     assert_eq!("".trim_start(), "");
778     assert_eq!("a".trim_start(), "a");
779     assert_eq!("    ".trim_start(), "");
780     assert_eq!("     blah".trim_start(), "blah");
781     assert_eq!("   \u{3000}  wut".trim_start(), "wut");
782     assert_eq!("hey ".trim_start(), "hey ");
783 }
784
785 #[test]
786 fn test_trim_end() {
787     assert_eq!("".trim_end(), "");
788     assert_eq!("a".trim_end(), "a");
789     assert_eq!("    ".trim_end(), "");
790     assert_eq!("blah     ".trim_end(), "blah");
791     assert_eq!("wut   \u{3000}  ".trim_end(), "wut");
792     assert_eq!(" hey".trim_end(), " hey");
793 }
794
795 #[test]
796 fn test_trim() {
797     assert_eq!("".trim(), "");
798     assert_eq!("a".trim(), "a");
799     assert_eq!("    ".trim(), "");
800     assert_eq!("    blah     ".trim(), "blah");
801     assert_eq!("\nwut   \u{3000}  ".trim(), "wut");
802     assert_eq!(" hey dude ".trim(), "hey dude");
803 }
804
805 #[test]
806 fn test_is_whitespace() {
807     assert!("".chars().all(|c| c.is_whitespace()));
808     assert!(" ".chars().all(|c| c.is_whitespace()));
809     assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
810     assert!("  \n\t   ".chars().all(|c| c.is_whitespace()));
811     assert!(!"   _   ".chars().all(|c| c.is_whitespace()));
812 }
813
814 #[test]
815 fn test_is_utf8() {
816     // deny overlong encodings
817     assert!(from_utf8(&[0xc0, 0x80]).is_err());
818     assert!(from_utf8(&[0xc0, 0xae]).is_err());
819     assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
820     assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
821     assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
822     assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
823     assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
824
825     // deny surrogates
826     assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
827     assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
828
829     assert!(from_utf8(&[0xC2, 0x80]).is_ok());
830     assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
831     assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
832     assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
833     assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
834     assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
835     assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
836     assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
837 }
838
839 #[test]
840 fn from_utf8_mostly_ascii() {
841     // deny invalid bytes embedded in long stretches of ascii
842     for i in 32..64 {
843         let mut data = [0; 128];
844         data[i] = 0xC0;
845         assert!(from_utf8(&data).is_err());
846         data[i] = 0xC2;
847         assert!(from_utf8(&data).is_err());
848     }
849 }
850
851 #[test]
852 fn from_utf8_error() {
853     macro_rules! test {
854         ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
855             let error = from_utf8($input).unwrap_err();
856             assert_eq!(error.valid_up_to(), $expected_valid_up_to);
857             assert_eq!(error.error_len(), $expected_error_len);
858         }
859     }
860     test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
861     test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
862     test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
863     test!(b"A\xC3\xA9 \xC1", 4, Some(1));
864     test!(b"A\xC3\xA9 \xC2", 4, None);
865     test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
866     test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
867     test!(b"A\xC3\xA9 \xE0", 4, None);
868     test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
869     test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
870     test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
871     test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
872     test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
873     test!(b"A\xC3\xA9 \xF1", 4, None);
874     test!(b"A\xC3\xA9 \xF1\x80", 4, None);
875     test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
876     test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
877     test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
878     test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
879 }
880
881 #[test]
882 fn test_as_bytes() {
883     // no null
884     let v = [
885         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
886         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
887         109
888     ];
889     let b: &[u8] = &[];
890     assert_eq!("".as_bytes(), b);
891     assert_eq!("abc".as_bytes(), b"abc");
892     assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
893 }
894
895 #[test]
896 #[should_panic]
897 #[cfg(not(miri))] // Miri does not support panics
898 fn test_as_bytes_fail() {
899     // Don't double free. (I'm not sure if this exercises the
900     // original problem code path anymore.)
901     let s = String::from("");
902     let _bytes = s.as_bytes();
903     panic!();
904 }
905
906 #[test]
907 fn test_as_ptr() {
908     let buf = "hello".as_ptr();
909     unsafe {
910         assert_eq!(*buf.offset(0), b'h');
911         assert_eq!(*buf.offset(1), b'e');
912         assert_eq!(*buf.offset(2), b'l');
913         assert_eq!(*buf.offset(3), b'l');
914         assert_eq!(*buf.offset(4), b'o');
915     }
916 }
917
918 #[test]
919 fn vec_str_conversions() {
920     let s1: String = String::from("All mimsy were the borogoves");
921
922     let v: Vec<u8> = s1.as_bytes().to_vec();
923     let s2: String = String::from(from_utf8(&v).unwrap());
924     let mut i = 0;
925     let n1 = s1.len();
926     let n2 = v.len();
927     assert_eq!(n1, n2);
928     while i < n1 {
929         let a: u8 = s1.as_bytes()[i];
930         let b: u8 = s2.as_bytes()[i];
931         assert_eq!(a, b);
932         i += 1;
933     }
934 }
935
936 #[test]
937 fn test_contains() {
938     assert!("abcde".contains("bcd"));
939     assert!("abcde".contains("abcd"));
940     assert!("abcde".contains("bcde"));
941     assert!("abcde".contains(""));
942     assert!("".contains(""));
943     assert!(!"abcde".contains("def"));
944     assert!(!"".contains("a"));
945
946     let data = "ประเทศไทย中华Việt Nam";
947     assert!(data.contains("ประเ"));
948     assert!(data.contains("ะเ"));
949     assert!(data.contains("中华"));
950     assert!(!data.contains("ไท华"));
951 }
952
953 #[test]
954 fn test_contains_char() {
955     assert!("abc".contains('b'));
956     assert!("a".contains('a'));
957     assert!(!"abc".contains('d'));
958     assert!(!"".contains('a'));
959 }
960
961 #[test]
962 fn test_split_at() {
963     let s = "ศไทย中华Việt Nam";
964     for (index, _) in s.char_indices() {
965         let (a, b) = s.split_at(index);
966         assert_eq!(&s[..a.len()], a);
967         assert_eq!(&s[a.len()..], b);
968     }
969     let (a, b) = s.split_at(s.len());
970     assert_eq!(a, s);
971     assert_eq!(b, "");
972 }
973
974 #[test]
975 fn test_split_at_mut() {
976     let mut s = "Hello World".to_string();
977     {
978         let (a, b) = s.split_at_mut(5);
979         a.make_ascii_uppercase();
980         b.make_ascii_lowercase();
981     }
982     assert_eq!(s, "HELLO world");
983 }
984
985 #[test]
986 #[should_panic]
987 #[cfg(not(miri))] // Miri does not support panics
988 fn test_split_at_boundscheck() {
989     let s = "ศไทย中华Việt Nam";
990     s.split_at(1);
991 }
992
993 #[test]
994 fn test_escape_unicode() {
995     assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}");
996     assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}");
997     assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}");
998     assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}");
999     assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
1000     assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}");
1001     assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}");
1002     assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}");
1003     assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}");
1004 }
1005
1006 #[test]
1007 fn test_escape_debug() {
1008     // Note that there are subtleties with the number of backslashes
1009     // on the left- and right-hand sides. In particular, Unicode code points
1010     // are usually escaped with two backslashes on the right-hand side, as
1011     // they are escaped. However, when the character is unescaped (e.g., for
1012     // printable characters), only a single backslash appears (as the character
1013     // itself appears in the debug string).
1014     assert_eq!("abc".escape_debug().to_string(), "abc");
1015     assert_eq!("a c".escape_debug().to_string(), "a c");
1016     assert_eq!("éèê".escape_debug().to_string(), "éèê");
1017     assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t");
1018     assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\");
1019     assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}");
1020     assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}");
1021     assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}");
1022     assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}");
1023     assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r");
1024     assert_eq!("\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(),
1025                "\\u{301}a\u{301}bé\\u{e000}");
1026 }
1027
1028 #[test]
1029 fn test_escape_default() {
1030     assert_eq!("abc".escape_default().to_string(), "abc");
1031     assert_eq!("a c".escape_default().to_string(), "a c");
1032     assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}");
1033     assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t");
1034     assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\");
1035     assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}");
1036     assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}");
1037     assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}");
1038     assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}");
1039     assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r");
1040 }
1041
1042 #[test]
1043 fn test_total_ord() {
1044     assert_eq!("1234".cmp("123"), Greater);
1045     assert_eq!("123".cmp("1234"), Less);
1046     assert_eq!("1234".cmp("1234"), Equal);
1047     assert_eq!("12345555".cmp("123456"), Less);
1048     assert_eq!("22".cmp("1234"), Greater);
1049 }
1050
1051 #[test]
1052 fn test_iterator() {
1053     let s = "ศไทย中华Việt Nam";
1054     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1055
1056     let mut pos = 0;
1057     let it = s.chars();
1058
1059     for c in it {
1060         assert_eq!(c, v[pos]);
1061         pos += 1;
1062     }
1063     assert_eq!(pos, v.len());
1064     assert_eq!(s.chars().count(), v.len());
1065 }
1066
1067 #[test]
1068 fn test_rev_iterator() {
1069     let s = "ศไทย中华Việt Nam";
1070     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1071
1072     let mut pos = 0;
1073     let it = s.chars().rev();
1074
1075     for c in it {
1076         assert_eq!(c, v[pos]);
1077         pos += 1;
1078     }
1079     assert_eq!(pos, v.len());
1080 }
1081
1082 #[test]
1083 #[cfg(not(miri))] // Miri is too slow
1084 fn test_chars_decoding() {
1085     let mut bytes = [0; 4];
1086     for c in (0..0x110000).filter_map(std::char::from_u32) {
1087         let s = c.encode_utf8(&mut bytes);
1088         if Some(c) != s.chars().next() {
1089             panic!("character {:x}={} does not decode correctly", c as u32, c);
1090         }
1091     }
1092 }
1093
1094 #[test]
1095 #[cfg(not(miri))] // Miri is too slow
1096 fn test_chars_rev_decoding() {
1097     let mut bytes = [0; 4];
1098     for c in (0..0x110000).filter_map(std::char::from_u32) {
1099         let s = c.encode_utf8(&mut bytes);
1100         if Some(c) != s.chars().rev().next() {
1101             panic!("character {:x}={} does not decode correctly", c as u32, c);
1102         }
1103     }
1104 }
1105
1106 #[test]
1107 fn test_iterator_clone() {
1108     let s = "ศไทย中华Việt Nam";
1109     let mut it = s.chars();
1110     it.next();
1111     assert!(it.clone().zip(it).all(|(x,y)| x == y));
1112 }
1113
1114 #[test]
1115 fn test_iterator_last() {
1116     let s = "ศไทย中华Việt Nam";
1117     let mut it = s.chars();
1118     it.next();
1119     assert_eq!(it.last(), Some('m'));
1120 }
1121
1122 #[test]
1123 fn test_bytesator() {
1124     let s = "ศไทย中华Việt Nam";
1125     let v = [
1126         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1127         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1128         109
1129     ];
1130     let mut pos = 0;
1131
1132     for b in s.bytes() {
1133         assert_eq!(b, v[pos]);
1134         pos += 1;
1135     }
1136 }
1137
1138 #[test]
1139 fn test_bytes_revator() {
1140     let s = "ศไทย中华Việt Nam";
1141     let v = [
1142         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1143         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1144         109
1145     ];
1146     let mut pos = v.len();
1147
1148     for b in s.bytes().rev() {
1149         pos -= 1;
1150         assert_eq!(b, v[pos]);
1151     }
1152 }
1153
1154 #[test]
1155 fn test_bytesator_nth() {
1156     let s = "ศไทย中华Việt Nam";
1157     let v = [
1158         224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
1159         184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
1160         109
1161     ];
1162
1163     let mut b = s.bytes();
1164     assert_eq!(b.nth(2).unwrap(), v[2]);
1165     assert_eq!(b.nth(10).unwrap(), v[10]);
1166     assert_eq!(b.nth(200), None);
1167 }
1168
1169 #[test]
1170 fn test_bytesator_count() {
1171     let s = "ศไทย中华Việt Nam";
1172
1173     let b = s.bytes();
1174     assert_eq!(b.count(), 28)
1175 }
1176
1177 #[test]
1178 fn test_bytesator_last() {
1179     let s = "ศไทย中华Việt Nam";
1180
1181     let b = s.bytes();
1182     assert_eq!(b.last().unwrap(), 109)
1183 }
1184
1185 #[test]
1186 fn test_char_indicesator() {
1187     let s = "ศไทย中华Việt Nam";
1188     let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
1189     let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
1190
1191     let mut pos = 0;
1192     let it = s.char_indices();
1193
1194     for c in it {
1195         assert_eq!(c, (p[pos], v[pos]));
1196         pos += 1;
1197     }
1198     assert_eq!(pos, v.len());
1199     assert_eq!(pos, p.len());
1200 }
1201
1202 #[test]
1203 fn test_char_indices_revator() {
1204     let s = "ศไทย中华Việt Nam";
1205     let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
1206     let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
1207
1208     let mut pos = 0;
1209     let it = s.char_indices().rev();
1210
1211     for c in it {
1212         assert_eq!(c, (p[pos], v[pos]));
1213         pos += 1;
1214     }
1215     assert_eq!(pos, v.len());
1216     assert_eq!(pos, p.len());
1217 }
1218
1219 #[test]
1220 fn test_char_indices_last() {
1221     let s = "ศไทย中华Việt Nam";
1222     let mut it = s.char_indices();
1223     it.next();
1224     assert_eq!(it.last(), Some((27, 'm')));
1225 }
1226
1227 #[test]
1228 fn test_splitn_char_iterator() {
1229     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1230
1231     let split: Vec<&str> = data.splitn(4, ' ').collect();
1232     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1233
1234     let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
1235     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
1236
1237     // Unicode
1238     let split: Vec<&str> = data.splitn(4, 'ä').collect();
1239     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1240
1241     let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
1242     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
1243 }
1244
1245 #[test]
1246 fn test_split_char_iterator_no_trailing() {
1247     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1248
1249     let split: Vec<&str> = data.split('\n').collect();
1250     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1251
1252     let split: Vec<&str> = data.split_terminator('\n').collect();
1253     assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1254 }
1255
1256 #[test]
1257 fn test_rsplit() {
1258     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1259
1260     let split: Vec<&str> = data.rsplit(' ').collect();
1261     assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
1262
1263     let split: Vec<&str> = data.rsplit("lämb").collect();
1264     assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
1265
1266     let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
1267     assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
1268 }
1269
1270 #[test]
1271 fn test_rsplitn() {
1272     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1273
1274     let split: Vec<&str> = data.rsplitn(2, ' ').collect();
1275     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
1276
1277     let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1278     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1279
1280     let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1281     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1282 }
1283
1284 #[test]
1285 fn test_split_whitespace() {
1286     let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
1287     let words: Vec<&str> = data.split_whitespace().collect();
1288     assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1289 }
1290
1291 #[test]
1292 fn test_lines() {
1293     let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1294     let lines: Vec<&str> = data.lines().collect();
1295     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1296
1297     let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1298     let lines: Vec<&str> = data.lines().collect();
1299     assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1300 }
1301
1302 #[test]
1303 fn test_splitator() {
1304     fn t(s: &str, sep: &str, u: &[&str]) {
1305         let v: Vec<&str> = s.split(sep).collect();
1306         assert_eq!(v, u);
1307     }
1308     t("--1233345--", "12345", &["--1233345--"]);
1309     t("abc::hello::there", "::", &["abc", "hello", "there"]);
1310     t("::hello::there", "::", &["", "hello", "there"]);
1311     t("hello::there::", "::", &["hello", "there", ""]);
1312     t("::hello::there::", "::", &["", "hello", "there", ""]);
1313     t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1314     t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1315     t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1316     t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1317     t("", ".", &[""]);
1318     t("zz", "zz", &["",""]);
1319     t("ok", "z", &["ok"]);
1320     t("zzz", "zz", &["","z"]);
1321     t("zzzzz", "zz", &["","","z"]);
1322 }
1323
1324 #[test]
1325 fn test_str_default() {
1326     use std::default::Default;
1327
1328     fn t<S: Default + AsRef<str>>() {
1329         let s: S = Default::default();
1330         assert_eq!(s.as_ref(), "");
1331     }
1332
1333     t::<&str>();
1334     t::<String>();
1335     t::<&mut str>();
1336 }
1337
1338 #[test]
1339 fn test_str_container() {
1340     fn sum_len(v: &[&str]) -> usize {
1341         v.iter().map(|x| x.len()).sum()
1342     }
1343
1344     let s = "01234";
1345     assert_eq!(5, sum_len(&["012", "", "34"]));
1346     assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1347     assert_eq!(5, sum_len(&[s]));
1348 }
1349
1350 #[test]
1351 fn test_str_from_utf8() {
1352     let xs = b"hello";
1353     assert_eq!(from_utf8(xs), Ok("hello"));
1354
1355     let xs = "ศไทย中华Việt Nam".as_bytes();
1356     assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1357
1358     let xs = b"hello\xFF";
1359     assert!(from_utf8(xs).is_err());
1360 }
1361
1362 #[test]
1363 fn test_pattern_deref_forward() {
1364     let data = "aabcdaa";
1365     assert!(data.contains("bcd"));
1366     assert!(data.contains(&"bcd"));
1367     assert!(data.contains(&"bcd".to_string()));
1368 }
1369
1370 #[test]
1371 fn test_empty_match_indices() {
1372     let data = "aä中!";
1373     let vec: Vec<_> = data.match_indices("").collect();
1374     assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1375 }
1376
1377 #[test]
1378 fn test_bool_from_str() {
1379     assert_eq!("true".parse().ok(), Some(true));
1380     assert_eq!("false".parse().ok(), Some(false));
1381     assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1382 }
1383
1384 #[cfg(not(miri))] // Miri is too slow
1385 fn check_contains_all_substrings(s: &str) {
1386     assert!(s.contains(""));
1387     for i in 0..s.len() {
1388         for j in i+1..=s.len() {
1389             assert!(s.contains(&s[i..j]));
1390         }
1391     }
1392 }
1393
1394 #[test]
1395 #[cfg(not(miri))] // Miri is too slow
1396 fn strslice_issue_16589() {
1397     assert!("bananas".contains("nana"));
1398
1399     // prior to the fix for #16589, x.contains("abcdabcd") returned false
1400     // test all substrings for good measure
1401     check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1402 }
1403
1404 #[test]
1405 fn strslice_issue_16878() {
1406     assert!(!"1234567ah012345678901ah".contains("hah"));
1407     assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1408 }
1409
1410
1411 #[test]
1412 #[cfg(not(miri))] // Miri is too slow
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     assert_eq!("".to_lowercase(), "");
1551     assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1552
1553     // https://github.com/rust-lang/rust/issues/26035
1554     assert_eq!("ΑΣ".to_lowercase(), "ας");
1555     assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1556     assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1557
1558     assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1559     assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1560     assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1561
1562     assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1563     assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1564
1565     assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1566     assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1567
1568     assert_eq!("Α Σ".to_lowercase(), "α σ");
1569     assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1570     assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1571
1572     assert_eq!("Σ".to_lowercase(), "σ");
1573     assert_eq!("'Σ".to_lowercase(), "'σ");
1574     assert_eq!("''Σ".to_lowercase(), "''σ");
1575
1576     assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1577     assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1578     assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1579 }
1580
1581 #[test]
1582 fn to_uppercase() {
1583     assert_eq!("".to_uppercase(), "");
1584     assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1585 }
1586
1587 #[test]
1588 fn test_into_string() {
1589     // The only way to acquire a Box<str> in the first place is through a String, so just
1590     // test that we can round-trip between Box<str> and String.
1591     let string = String::from("Some text goes here");
1592     assert_eq!(string.clone().into_boxed_str().into_string(), string);
1593 }
1594
1595 #[test]
1596 fn test_box_slice_clone() {
1597     let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1598     let data2 = data.clone().into_boxed_str().clone().into_string();
1599
1600     assert_eq!(data, data2);
1601 }
1602
1603 #[test]
1604 fn test_cow_from() {
1605     let borrowed = "borrowed";
1606     let owned = String::from("owned");
1607     match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1608         (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1609         _ => panic!("invalid `Cow::from`"),
1610     }
1611 }
1612
1613 #[test]
1614 fn test_repeat() {
1615     assert_eq!("".repeat(3), "");
1616     assert_eq!("abc".repeat(0), "");
1617     assert_eq!("α".repeat(3), "ααα");
1618 }
1619
1620 mod pattern {
1621     use std::str::pattern::{Pattern, Searcher, ReverseSearcher};
1622     use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1623
1624     macro_rules! make_test {
1625         ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1626             #[allow(unused_imports)]
1627             mod $name {
1628                 use std::str::pattern::SearchStep::{Match, Reject};
1629                 use super::{cmp_search_to_vec};
1630                 #[test]
1631                 fn fwd() {
1632                     cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1633                 }
1634                 #[test]
1635                 fn bwd() {
1636                     cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1637                 }
1638             }
1639         }
1640     }
1641
1642     fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1643                                              right: Vec<SearchStep>)
1644     where P::Searcher: ReverseSearcher<'a>
1645     {
1646         let mut searcher = pat.into_searcher(haystack);
1647         let mut v = vec![];
1648         loop {
1649             match if !rev {searcher.next()} else {searcher.next_back()} {
1650                 Match(a, b) => v.push(Match(a, b)),
1651                 Reject(a, b) => v.push(Reject(a, b)),
1652                 Done => break,
1653             }
1654         }
1655         if rev {
1656             v.reverse();
1657         }
1658
1659         let mut first_index = 0;
1660         let mut err = None;
1661
1662         for (i, e) in right.iter().enumerate() {
1663             match *e {
1664                 Match(a, b) | Reject(a, b)
1665                 if a <= b && a == first_index => {
1666                     first_index = b;
1667                 }
1668                 _ => {
1669                     err = Some(i);
1670                     break;
1671                 }
1672             }
1673         }
1674
1675         if let Some(err) = err {
1676             panic!("Input skipped range at {}", err);
1677         }
1678
1679         if first_index != haystack.len() {
1680             panic!("Did not cover whole input");
1681         }
1682
1683         assert_eq!(v, right);
1684     }
1685
1686     make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1687         Reject(0, 1),
1688         Match (1, 3),
1689         Reject(3, 4),
1690         Match (4, 6),
1691         Reject(6, 7),
1692     ]);
1693     make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1694         Reject(0, 1),
1695         Match (1, 3),
1696         Reject(3, 4),
1697         Match (4, 6),
1698         Match (6, 8),
1699         Reject(8, 9),
1700     ]);
1701     make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1702         Match (0, 0),
1703         Reject(0, 1),
1704         Match (1, 1),
1705         Reject(1, 2),
1706         Match (2, 2),
1707         Reject(2, 3),
1708         Match (3, 3),
1709         Reject(3, 4),
1710         Match (4, 4),
1711         Reject(4, 5),
1712         Match (5, 5),
1713         Reject(5, 6),
1714         Match (6, 6),
1715         Reject(6, 7),
1716         Match (7, 7),
1717     ]);
1718     make_test!(str_searcher_multibyte_haystack, " ", "├──", [
1719         Reject(0, 3),
1720         Reject(3, 6),
1721         Reject(6, 9),
1722     ]);
1723     make_test!(str_searcher_empty_needle_multibyte_haystack, "", "├──", [
1724         Match (0, 0),
1725         Reject(0, 3),
1726         Match (3, 3),
1727         Reject(3, 6),
1728         Match (6, 6),
1729         Reject(6, 9),
1730         Match (9, 9),
1731     ]);
1732     make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1733         Match(0, 0),
1734     ]);
1735     make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1736     ]);
1737     make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1738         Reject(0, 1),
1739         Match (1, 2),
1740         Match (2, 3),
1741         Reject(3, 4),
1742         Match (4, 5),
1743         Match (5, 6),
1744         Reject(6, 7),
1745     ]);
1746     make_test!(char_searcher_multibyte_haystack, ' ', "├──", [
1747         Reject(0, 3),
1748         Reject(3, 6),
1749         Reject(6, 9),
1750     ]);
1751     make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1752         Reject(0, 1),
1753         Reject(1, 2),
1754         Reject(2, 3),
1755     ]);
1756
1757 }
1758
1759 macro_rules! generate_iterator_test {
1760     {
1761         $name:ident {
1762             $(
1763                 ($($arg:expr),*) -> [$($t:tt)*];
1764             )*
1765         }
1766         with $fwd:expr, $bwd:expr;
1767     } => {
1768         #[test]
1769         fn $name() {
1770             $(
1771                 {
1772                     let res = vec![$($t)*];
1773
1774                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1775                     assert_eq!(fwd_vec, res);
1776
1777                     let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1778                     bwd_vec.reverse();
1779                     assert_eq!(bwd_vec, res);
1780                 }
1781             )*
1782         }
1783     };
1784     {
1785         $name:ident {
1786             $(
1787                 ($($arg:expr),*) -> [$($t:tt)*];
1788             )*
1789         }
1790         with $fwd:expr;
1791     } => {
1792         #[test]
1793         fn $name() {
1794             $(
1795                 {
1796                     let res = vec![$($t)*];
1797
1798                     let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1799                     assert_eq!(fwd_vec, res);
1800                 }
1801             )*
1802         }
1803     }
1804 }
1805
1806 generate_iterator_test! {
1807     double_ended_split {
1808         ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1809         ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1810     }
1811     with str::split, str::rsplit;
1812 }
1813
1814 generate_iterator_test! {
1815     double_ended_split_terminator {
1816         ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1817     }
1818     with str::split_terminator, str::rsplit_terminator;
1819 }
1820
1821 generate_iterator_test! {
1822     double_ended_matches {
1823         ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1824     }
1825     with str::matches, str::rmatches;
1826 }
1827
1828 generate_iterator_test! {
1829     double_ended_match_indices {
1830         ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1831     }
1832     with str::match_indices, str::rmatch_indices;
1833 }
1834
1835 generate_iterator_test! {
1836     not_double_ended_splitn {
1837         ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1838     }
1839     with str::splitn;
1840 }
1841
1842 generate_iterator_test! {
1843     not_double_ended_rsplitn {
1844         ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1845     }
1846     with str::rsplitn;
1847 }
1848
1849 #[test]
1850 fn different_str_pattern_forwarding_lifetimes() {
1851     use std::str::pattern::Pattern;
1852
1853     fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
1854         for _ in 0..3 {
1855             "asdf".find(&p);
1856         }
1857     }
1858
1859     foo::<&str>("x");
1860 }