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