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