1 use std::assert_matches::assert_matches;
4 use std::collections::TryReserveErrorKind::*;
6 use std::ops::Bound::*;
7 use std::ops::RangeBounds;
11 pub trait IntoCow<'a, B: ?Sized>
15 fn into_cow(self) -> Cow<'a, B>;
18 impl<'a> IntoCow<'a, str> for String {
19 fn into_cow(self) -> Cow<'a, str> {
24 impl<'a> IntoCow<'a, str> for &'a str {
25 fn into_cow(self) -> Cow<'a, str> {
32 let owned: Option<std::string::String> = "string".parse().ok();
33 assert_eq!(owned.as_ref().map(|s| &**s), Some("string"));
37 fn test_from_cow_str() {
38 assert_eq!(String::from(Cow::Borrowed("string")), "string");
39 assert_eq!(String::from(Cow::Owned(String::from("string"))), "string");
43 fn test_unsized_to_string() {
45 let _: String = (*s).to_string();
50 let xs = b"hello".to_vec();
51 assert_eq!(String::from_utf8(xs).unwrap(), String::from("hello"));
53 let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
54 assert_eq!(String::from_utf8(xs).unwrap(), String::from("ศไทย中华Việt Nam"));
56 let xs = b"hello\xFF".to_vec();
57 let err = String::from_utf8(xs).unwrap_err();
58 assert_eq!(err.as_bytes(), b"hello\xff");
59 let err_clone = err.clone();
60 assert_eq!(err, err_clone);
61 assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
62 assert_eq!(err_clone.utf8_error().valid_up_to(), 5);
66 fn test_from_utf8_lossy() {
68 let ys: Cow<'_, str> = "hello".into_cow();
69 assert_eq!(String::from_utf8_lossy(xs), ys);
71 let xs = "ศไทย中华Việt Nam".as_bytes();
72 let ys: Cow<'_, str> = "ศไทย中华Việt Nam".into_cow();
73 assert_eq!(String::from_utf8_lossy(xs), ys);
75 let xs = b"Hello\xC2 There\xFF Goodbye";
77 String::from_utf8_lossy(xs),
78 String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow()
81 let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
83 String::from_utf8_lossy(xs),
84 String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow()
87 let xs = b"\xF5foo\xF5\x80bar";
89 String::from_utf8_lossy(xs),
90 String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow()
93 let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
95 String::from_utf8_lossy(xs),
96 String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow()
99 let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
101 String::from_utf8_lossy(xs),
102 String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()
105 let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
107 String::from_utf8_lossy(xs),
108 String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow()
112 let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
114 String::from_utf8_lossy(xs),
115 String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()
120 fn test_from_utf16() {
123 String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
125 0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800, 0xdf39,
126 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a,
130 String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
132 0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801, 0xdc32,
133 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801, 0xdc4d, 0x000a,
137 String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
139 0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800, 0xdf11,
140 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800, 0xdf15, 0xd800,
141 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11, 0x000a,
145 String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
147 0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801, 0xdc9b,
148 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020, 0xd801, 0xdc88,
149 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f, 0xd801, 0xdc9c, 0xd801,
150 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc86,
154 // Issue #12318, even-numbered non-BMP planes
155 (String::from("\u{20000}"), vec![0xD840, 0xDC00]),
159 let (s, u) = (*p).clone();
160 let s_as_utf16 = s.encode_utf16().collect::<Vec<u16>>();
161 let u_as_string = String::from_utf16(&u).unwrap();
163 assert!(core::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok()));
164 assert_eq!(s_as_utf16, u);
166 assert_eq!(u_as_string, s);
167 assert_eq!(String::from_utf16_lossy(&u), s);
169 assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s);
170 assert_eq!(u_as_string.encode_utf16().collect::<Vec<u16>>(), u);
175 fn test_utf16_invalid() {
176 // completely positive cases tested above.
178 assert!(String::from_utf16(&[0xD800]).is_err());
180 assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
183 assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
186 assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
190 fn test_from_utf16_lossy() {
191 // completely positive cases tested above.
193 assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}"));
195 assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), String::from("\u{FFFD}\u{FFFD}"));
198 assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}"));
202 String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
203 String::from("\u{FFFD}𐒋\u{FFFD}")
208 fn test_push_bytes() {
209 let mut s = String::from("ABC");
211 let mv = s.as_mut_vec();
212 mv.extend_from_slice(&[b'D']);
214 assert_eq!(s, "ABCD");
219 let mut s = String::new();
221 assert_eq!(&s[0..], "");
223 assert_eq!(&s[0..], "abc");
224 s.push_str("ประเทศไทย中华Việt Nam");
225 assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
229 fn test_add_assign() {
230 let mut s = String::new();
232 assert_eq!(s.as_str(), "");
234 assert_eq!(s.as_str(), "abc");
235 s += "ประเทศไทย中华Việt Nam";
236 assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam");
241 let mut data = String::from("ประเทศไทย中");
243 data.push('b'); // 1 byte
244 data.push('¢'); // 2 byte
245 data.push('€'); // 3 byte
246 data.push('𤭢'); // 4 byte
247 assert_eq!(data, "ประเทศไทย中华b¢€𤭢");
252 let mut data = String::from("ประเทศไทย中华b¢€𤭢");
253 assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes
254 assert_eq!(data.pop().unwrap(), '€'); // 3 bytes
255 assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes
256 assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes
257 assert_eq!(data.pop().unwrap(), '华');
258 assert_eq!(data, "ประเทศไทย中");
262 fn test_split_off_empty() {
263 let orig = "Hello, world!";
264 let mut split = String::from(orig);
265 let empty: String = split.split_off(orig.len());
266 assert!(empty.is_empty());
271 fn test_split_off_past_end() {
272 let orig = "Hello, world!";
273 let mut split = String::from(orig);
274 let _ = split.split_off(orig.len() + 1);
279 fn test_split_off_mid_char() {
280 let mut shan = String::from("山");
281 let _broken_mountain = shan.split_off(1);
285 fn test_split_off_ascii() {
286 let mut ab = String::from("ABCD");
287 let orig_capacity = ab.capacity();
288 let cd = ab.split_off(2);
289 assert_eq!(ab, "AB");
290 assert_eq!(cd, "CD");
291 assert_eq!(ab.capacity(), orig_capacity);
295 fn test_split_off_unicode() {
296 let mut nihon = String::from("日本語");
297 let orig_capacity = nihon.capacity();
298 let go = nihon.split_off("日本".len());
299 assert_eq!(nihon, "日本");
301 assert_eq!(nihon.capacity(), orig_capacity);
305 fn test_str_truncate() {
306 let mut s = String::from("12345");
308 assert_eq!(s, "12345");
310 assert_eq!(s, "123");
314 let mut s = String::from("12345");
323 fn test_str_truncate_invalid_len() {
324 let mut s = String::from("12345");
326 assert_eq!(s, "12345");
331 fn test_str_truncate_split_codepoint() {
332 let mut s = String::from("\u{FC}"); // ü
337 fn test_str_clear() {
338 let mut s = String::from("12345");
340 assert_eq!(s.len(), 0);
346 let a = String::from("12345");
349 assert_eq!(b.len(), 7);
350 assert_eq!(b, "1234522");
355 let mut s = "ศไทย中华Việt Nam; foobar".to_string();
356 assert_eq!(s.remove(0), 'ศ');
357 assert_eq!(s.len(), 33);
358 assert_eq!(s, "ไทย中华Việt Nam; foobar");
359 assert_eq!(s.remove(17), 'ệ');
360 assert_eq!(s, "ไทย中华Vit Nam; foobar");
366 "ศ".to_string().remove(1);
370 fn test_remove_matches() {
371 let mut s = "abc".to_string();
373 s.remove_matches('b');
375 s.remove_matches('b');
378 let mut s = "abcb".to_string();
380 s.remove_matches('b');
383 let mut s = "ศไทย中华Việt Nam; foobarศ".to_string();
384 s.remove_matches('ศ');
385 assert_eq!(s, "ไทย中华Việt Nam; foobar");
387 let mut s = "".to_string();
388 s.remove_matches("");
391 let mut s = "aaaaa".to_string();
392 s.remove_matches('a');
398 let mut s = String::from("α_β_γ");
401 assert_eq!(s, "α_β_γ");
403 s.retain(|c| c != '_');
404 assert_eq!(s, "αβγ");
406 s.retain(|c| c != 'β');
409 s.retain(|c| c == 'α');
415 let mut s = String::from("0è0");
416 let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| {
427 assert!(std::str::from_utf8(s.as_bytes()).is_ok());
432 let mut s = "foobar".to_string();
434 assert_eq!(s, "ệfoobar");
436 assert_eq!(s, "ệfooยbar");
442 "".to_string().insert(1, 't');
447 "ệ".to_string().insert(1, 't');
452 let s = "foobar".to_string();
453 assert_eq!("foobar", &s[..]);
454 assert_eq!("foo", &s[..3]);
455 assert_eq!("bar", &s[3..]);
456 assert_eq!("oob", &s[1..4]);
460 fn test_simple_types() {
461 assert_eq!(1.to_string(), "1");
462 assert_eq!((-1).to_string(), "-1");
463 assert_eq!(200.to_string(), "200");
464 assert_eq!(2.to_string(), "2");
465 assert_eq!(true.to_string(), "true");
466 assert_eq!(false.to_string(), "false");
467 assert_eq!(("hi".to_string()).to_string(), "hi");
472 let x: Vec<i32> = vec![];
473 assert_eq!(format!("{x:?}"), "[]");
474 assert_eq!(format!("{:?}", vec![1]), "[1]");
475 assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]");
476 assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == "[[], [1], [1, 1]]");
480 fn test_from_iterator() {
481 let s = "ศไทย中华Việt Nam".to_string();
485 let a: String = s.chars().collect();
488 let mut b = t.to_string();
492 let c: String = [t, u].into_iter().collect();
495 let mut d = t.to_string();
502 let mut s = String::from("αβγ");
503 assert_eq!(s.drain(2..4).collect::<String>(), "β");
506 let mut t = String::from("abcd");
508 assert_eq!(t, "abcd");
510 assert_eq!(t, "bcd");
512 assert_eq!(t, "bcd");
519 fn test_drain_start_overflow() {
520 let mut s = String::from("abc");
521 s.drain((Excluded(usize::MAX), Included(0)));
526 fn test_drain_end_overflow() {
527 let mut s = String::from("abc");
528 s.drain((Included(0), Included(usize::MAX)));
532 fn test_replace_range() {
533 let mut s = "Hello, world!".to_owned();
534 s.replace_range(7..12, "世界");
535 assert_eq!(s, "Hello, 世界!");
540 fn test_replace_range_char_boundary() {
541 let mut s = "Hello, 世界!".to_owned();
542 s.replace_range(..8, "");
546 fn test_replace_range_inclusive_range() {
547 let mut v = String::from("12345");
548 v.replace_range(2..=3, "789");
549 assert_eq!(v, "127895");
550 v.replace_range(1..=2, "A");
551 assert_eq!(v, "1A895");
556 fn test_replace_range_out_of_bounds() {
557 let mut s = String::from("12345");
558 s.replace_range(5..6, "789");
563 fn test_replace_range_inclusive_out_of_bounds() {
564 let mut s = String::from("12345");
565 s.replace_range(5..=5, "789");
570 fn test_replace_range_start_overflow() {
571 let mut s = String::from("123");
572 s.replace_range((Excluded(usize::MAX), Included(0)), "");
577 fn test_replace_range_end_overflow() {
578 let mut s = String::from("456");
579 s.replace_range((Included(0), Included(usize::MAX)), "");
583 fn test_replace_range_empty() {
584 let mut s = String::from("12345");
585 s.replace_range(1..2, "");
586 assert_eq!(s, "1345");
590 fn test_replace_range_unbounded() {
591 let mut s = String::from("12345");
592 s.replace_range(.., "");
597 fn test_replace_range_evil_start_bound() {
598 struct EvilRange(Cell<bool>);
600 impl RangeBounds<usize> for EvilRange {
601 fn start_bound(&self) -> Bound<&usize> {
602 Bound::Included(if self.0.get() {
609 fn end_bound(&self) -> Bound<&usize> {
614 let mut s = String::from("🦀");
615 s.replace_range(EvilRange(Cell::new(false)), "");
616 assert_eq!(Ok(""), str::from_utf8(s.as_bytes()));
620 fn test_replace_range_evil_end_bound() {
621 struct EvilRange(Cell<bool>);
623 impl RangeBounds<usize> for EvilRange {
624 fn start_bound(&self) -> Bound<&usize> {
627 fn end_bound(&self) -> Bound<&usize> {
628 Bound::Excluded(if self.0.get() {
637 let mut s = String::from("🦀");
638 s.replace_range(EvilRange(Cell::new(false)), "");
639 assert_eq!(Ok(""), str::from_utf8(s.as_bytes()));
643 fn test_extend_ref() {
644 let mut a = "foo".to_string();
645 a.extend(&['b', 'a', 'r']);
647 assert_eq!(&a, "foobar");
651 fn test_into_boxed_str() {
652 let xs = String::from("hello my name is bob");
653 let ys = xs.into_boxed_str();
654 assert_eq!(&*ys, "hello my name is bob");
658 fn test_reserve_exact() {
659 // This is all the same as test_reserve
661 let mut s = String::new();
662 assert_eq!(s.capacity(), 0);
665 assert!(s.capacity() >= 2);
671 assert!(s.capacity() >= 16);
673 assert!(s.capacity() >= 32);
678 assert!(s.capacity() >= 33)
682 #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
683 #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc
684 fn test_try_reserve() {
685 // These are the interesting cases:
686 // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
687 // * > isize::MAX should always fail
688 // * On 16/32-bit should CapacityOverflow
689 // * On 64-bit should OOM
690 // * overflow may trigger when adding `len` to `cap` (in number of elements)
691 // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes)
693 const MAX_CAP: usize = isize::MAX as usize;
694 const MAX_USIZE: usize = usize::MAX;
697 // Note: basic stuff is checked by test_reserve
698 let mut empty_string: String = String::new();
700 // Check isize::MAX doesn't count as an overflow
701 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP).map_err(|e| e.kind()) {
702 panic!("isize::MAX shouldn't trigger an overflow!");
704 // Play it again, frank! (just to be sure)
705 if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP).map_err(|e| e.kind()) {
706 panic!("isize::MAX shouldn't trigger an overflow!");
709 // Check isize::MAX + 1 does count as overflow
711 empty_string.try_reserve(MAX_CAP + 1).map_err(|e| e.kind()),
712 Err(CapacityOverflow),
713 "isize::MAX + 1 should trigger an overflow!"
716 // Check usize::MAX does count as overflow
718 empty_string.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
719 Err(CapacityOverflow),
720 "usize::MAX should trigger an overflow!"
725 // Same basic idea, but with non-zero len
726 let mut ten_bytes: String = String::from("0123456789");
728 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) {
729 panic!("isize::MAX shouldn't trigger an overflow!");
731 if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10).map_err(|e| e.kind()) {
732 panic!("isize::MAX shouldn't trigger an overflow!");
736 ten_bytes.try_reserve(MAX_CAP - 9).map_err(|e| e.kind()),
737 Err(CapacityOverflow),
738 "isize::MAX + 1 should trigger an overflow!"
741 // Should always overflow in the add-to-len
743 ten_bytes.try_reserve(MAX_USIZE).map_err(|e| e.kind()),
744 Err(CapacityOverflow),
745 "usize::MAX should trigger an overflow!"
751 #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
752 #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc
753 fn test_try_reserve_exact() {
754 // This is exactly the same as test_try_reserve with the method changed.
755 // See that test for comments.
757 const MAX_CAP: usize = isize::MAX as usize;
758 const MAX_USIZE: usize = usize::MAX;
761 let mut empty_string: String = String::new();
763 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP).map_err(|e| e.kind())
765 panic!("isize::MAX shouldn't trigger an overflow!");
767 if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP).map_err(|e| e.kind())
769 panic!("isize::MAX shouldn't trigger an overflow!");
773 empty_string.try_reserve_exact(MAX_CAP + 1).map_err(|e| e.kind()),
774 Err(CapacityOverflow),
775 "isize::MAX + 1 should trigger an overflow!"
779 empty_string.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
780 Err(CapacityOverflow),
781 "usize::MAX should trigger an overflow!"
786 let mut ten_bytes: String = String::from("0123456789");
788 if let Err(CapacityOverflow) =
789 ten_bytes.try_reserve_exact(MAX_CAP - 10).map_err(|e| e.kind())
791 panic!("isize::MAX shouldn't trigger an overflow!");
793 if let Err(CapacityOverflow) =
794 ten_bytes.try_reserve_exact(MAX_CAP - 10).map_err(|e| e.kind())
796 panic!("isize::MAX shouldn't trigger an overflow!");
800 ten_bytes.try_reserve_exact(MAX_CAP - 9).map_err(|e| e.kind()),
801 Err(CapacityOverflow),
802 "isize::MAX + 1 should trigger an overflow!"
806 ten_bytes.try_reserve_exact(MAX_USIZE).map_err(|e| e.kind()),
807 Err(CapacityOverflow),
808 "usize::MAX should trigger an overflow!"
814 fn test_from_char() {
815 assert_eq!(String::from('a'), 'a'.to_string());
816 let s: String = 'x'.into();
817 assert_eq!(s, 'x'.to_string());
821 fn test_str_concat() {
822 let a: String = "hello".to_string();
823 let b: String = "world".to_string();
824 let s: String = format!("{a}{b}");
825 assert_eq!(s.as_bytes()[9], 'd' as u8);