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