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