]> git.lizzy.rs Git - rust.git/blob - library/alloc/tests/string.rs
Auto merge of #75148 - joechrisellis:master, r=Amanieu
[rust.git] / library / alloc / tests / string.rs
1 use std::borrow::Cow;
2 use std::collections::TryReserveError::*;
3 use std::mem::size_of;
4
5 pub trait IntoCow<'a, B: ?Sized>
6 where
7     B: ToOwned,
8 {
9     fn into_cow(self) -> Cow<'a, B>;
10 }
11
12 impl<'a> IntoCow<'a, str> for String {
13     fn into_cow(self) -> Cow<'a, str> {
14         Cow::Owned(self)
15     }
16 }
17
18 impl<'a> IntoCow<'a, str> for &'a str {
19     fn into_cow(self) -> Cow<'a, str> {
20         Cow::Borrowed(self)
21     }
22 }
23
24 #[test]
25 fn test_from_str() {
26     let owned: Option<std::string::String> = "string".parse().ok();
27     assert_eq!(owned.as_ref().map(|s| &**s), Some("string"));
28 }
29
30 #[test]
31 fn test_from_cow_str() {
32     assert_eq!(String::from(Cow::Borrowed("string")), "string");
33     assert_eq!(String::from(Cow::Owned(String::from("string"))), "string");
34 }
35
36 #[test]
37 fn test_unsized_to_string() {
38     let s: &str = "abc";
39     let _: String = (*s).to_string();
40 }
41
42 #[test]
43 fn test_from_utf8() {
44     let xs = b"hello".to_vec();
45     assert_eq!(String::from_utf8(xs).unwrap(), String::from("hello"));
46
47     let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
48     assert_eq!(String::from_utf8(xs).unwrap(), String::from("ศไทย中华Việt Nam"));
49
50     let xs = b"hello\xFF".to_vec();
51     let err = String::from_utf8(xs).unwrap_err();
52     assert_eq!(err.as_bytes(), b"hello\xff");
53     let err_clone = err.clone();
54     assert_eq!(err, err_clone);
55     assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
56     assert_eq!(err_clone.utf8_error().valid_up_to(), 5);
57 }
58
59 #[test]
60 fn test_from_utf8_lossy() {
61     let xs = b"hello";
62     let ys: Cow<'_, str> = "hello".into_cow();
63     assert_eq!(String::from_utf8_lossy(xs), ys);
64
65     let xs = "ศไทย中华Việt Nam".as_bytes();
66     let ys: Cow<'_, str> = "ศไทย中华Việt Nam".into_cow();
67     assert_eq!(String::from_utf8_lossy(xs), ys);
68
69     let xs = b"Hello\xC2 There\xFF Goodbye";
70     assert_eq!(
71         String::from_utf8_lossy(xs),
72         String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow()
73     );
74
75     let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
76     assert_eq!(
77         String::from_utf8_lossy(xs),
78         String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow()
79     );
80
81     let xs = b"\xF5foo\xF5\x80bar";
82     assert_eq!(
83         String::from_utf8_lossy(xs),
84         String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow()
85     );
86
87     let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
88     assert_eq!(
89         String::from_utf8_lossy(xs),
90         String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow()
91     );
92
93     let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
94     assert_eq!(
95         String::from_utf8_lossy(xs),
96         String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow()
97     );
98
99     let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
100     assert_eq!(
101         String::from_utf8_lossy(xs),
102         String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar").into_cow()
103     );
104
105     // surrogates
106     let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
107     assert_eq!(
108         String::from_utf8_lossy(xs),
109         String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow()
110     );
111 }
112
113 #[test]
114 fn test_from_utf16() {
115     let pairs = [
116         (
117             String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
118             vec![
119                 0xd800, 0xdf45, 0xd800, 0xdf3f, 0xd800, 0xdf3b, 0xd800, 0xdf46, 0xd800, 0xdf39,
120                 0xd800, 0xdf3b, 0xd800, 0xdf30, 0x000a,
121             ],
122         ),
123         (
124             String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
125             vec![
126                 0xd801, 0xdc12, 0xd801, 0xdc49, 0xd801, 0xdc2e, 0xd801, 0xdc40, 0xd801, 0xdc32,
127                 0xd801, 0xdc4b, 0x0020, 0xd801, 0xdc0f, 0xd801, 0xdc32, 0xd801, 0xdc4d, 0x000a,
128             ],
129         ),
130         (
131             String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
132             vec![
133                 0xd800, 0xdf00, 0xd800, 0xdf16, 0xd800, 0xdf0b, 0xd800, 0xdf04, 0xd800, 0xdf11,
134                 0xd800, 0xdf09, 0x00b7, 0xd800, 0xdf0c, 0xd800, 0xdf04, 0xd800, 0xdf15, 0xd800,
135                 0xdf04, 0xd800, 0xdf0b, 0xd800, 0xdf09, 0xd800, 0xdf11, 0x000a,
136             ],
137         ),
138         (
139             String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
140             vec![
141                 0xd801, 0xdc8b, 0xd801, 0xdc98, 0xd801, 0xdc88, 0xd801, 0xdc91, 0xd801, 0xdc9b,
142                 0xd801, 0xdc92, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc93, 0x0020, 0xd801, 0xdc88,
143                 0xd801, 0xdc9a, 0xd801, 0xdc8d, 0x0020, 0xd801, 0xdc8f, 0xd801, 0xdc9c, 0xd801,
144                 0xdc92, 0xd801, 0xdc96, 0xd801, 0xdc86, 0x0020, 0xd801, 0xdc95, 0xd801, 0xdc86,
145                 0x000a,
146             ],
147         ),
148         // Issue #12318, even-numbered non-BMP planes
149         (String::from("\u{20000}"), vec![0xD840, 0xDC00]),
150     ];
151
152     for p in &pairs {
153         let (s, u) = (*p).clone();
154         let s_as_utf16 = s.encode_utf16().collect::<Vec<u16>>();
155         let u_as_string = String::from_utf16(&u).unwrap();
156
157         assert!(core::char::decode_utf16(u.iter().cloned()).all(|r| r.is_ok()));
158         assert_eq!(s_as_utf16, u);
159
160         assert_eq!(u_as_string, s);
161         assert_eq!(String::from_utf16_lossy(&u), s);
162
163         assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s);
164         assert_eq!(u_as_string.encode_utf16().collect::<Vec<u16>>(), u);
165     }
166 }
167
168 #[test]
169 fn test_utf16_invalid() {
170     // completely positive cases tested above.
171     // lead + eof
172     assert!(String::from_utf16(&[0xD800]).is_err());
173     // lead + lead
174     assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
175
176     // isolated trail
177     assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
178
179     // general
180     assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
181 }
182
183 #[test]
184 fn test_from_utf16_lossy() {
185     // completely positive cases tested above.
186     // lead + eof
187     assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}"));
188     // lead + lead
189     assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]), String::from("\u{FFFD}\u{FFFD}"));
190
191     // isolated trail
192     assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}"));
193
194     // general
195     assert_eq!(
196         String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
197         String::from("\u{FFFD}𐒋\u{FFFD}")
198     );
199 }
200
201 #[test]
202 fn test_push_bytes() {
203     let mut s = String::from("ABC");
204     unsafe {
205         let mv = s.as_mut_vec();
206         mv.extend_from_slice(&[b'D']);
207     }
208     assert_eq!(s, "ABCD");
209 }
210
211 #[test]
212 fn test_push_str() {
213     let mut s = String::new();
214     s.push_str("");
215     assert_eq!(&s[0..], "");
216     s.push_str("abc");
217     assert_eq!(&s[0..], "abc");
218     s.push_str("ประเทศไทย中华Việt Nam");
219     assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
220 }
221
222 #[test]
223 fn test_add_assign() {
224     let mut s = String::new();
225     s += "";
226     assert_eq!(s.as_str(), "");
227     s += "abc";
228     assert_eq!(s.as_str(), "abc");
229     s += "ประเทศไทย中华Việt Nam";
230     assert_eq!(s.as_str(), "abcประเทศไทย中华Việt Nam");
231 }
232
233 #[test]
234 fn test_push() {
235     let mut data = String::from("ประเทศไทย中");
236     data.push('华');
237     data.push('b'); // 1 byte
238     data.push('¢'); // 2 byte
239     data.push('€'); // 3 byte
240     data.push('𤭢'); // 4 byte
241     assert_eq!(data, "ประเทศไทย中华b¢€𤭢");
242 }
243
244 #[test]
245 fn test_pop() {
246     let mut data = String::from("ประเทศไทย中华b¢€𤭢");
247     assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes
248     assert_eq!(data.pop().unwrap(), '€'); // 3 bytes
249     assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes
250     assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes
251     assert_eq!(data.pop().unwrap(), '华');
252     assert_eq!(data, "ประเทศไทย中");
253 }
254
255 #[test]
256 fn test_split_off_empty() {
257     let orig = "Hello, world!";
258     let mut split = String::from(orig);
259     let empty: String = split.split_off(orig.len());
260     assert!(empty.is_empty());
261 }
262
263 #[test]
264 #[should_panic]
265 fn test_split_off_past_end() {
266     let orig = "Hello, world!";
267     let mut split = String::from(orig);
268     let _ = split.split_off(orig.len() + 1);
269 }
270
271 #[test]
272 #[should_panic]
273 fn test_split_off_mid_char() {
274     let mut orig = String::from("山");
275     let _ = orig.split_off(1);
276 }
277
278 #[test]
279 fn test_split_off_ascii() {
280     let mut ab = String::from("ABCD");
281     let orig_capacity = ab.capacity();
282     let cd = ab.split_off(2);
283     assert_eq!(ab, "AB");
284     assert_eq!(cd, "CD");
285     assert_eq!(ab.capacity(), orig_capacity);
286 }
287
288 #[test]
289 fn test_split_off_unicode() {
290     let mut nihon = String::from("日本語");
291     let orig_capacity = nihon.capacity();
292     let go = nihon.split_off("日本".len());
293     assert_eq!(nihon, "日本");
294     assert_eq!(go, "語");
295     assert_eq!(nihon.capacity(), orig_capacity);
296 }
297
298 #[test]
299 fn test_str_truncate() {
300     let mut s = String::from("12345");
301     s.truncate(5);
302     assert_eq!(s, "12345");
303     s.truncate(3);
304     assert_eq!(s, "123");
305     s.truncate(0);
306     assert_eq!(s, "");
307
308     let mut s = String::from("12345");
309     let p = s.as_ptr();
310     s.truncate(3);
311     s.push_str("6");
312     let p_ = s.as_ptr();
313     assert_eq!(p_, p);
314 }
315
316 #[test]
317 fn test_str_truncate_invalid_len() {
318     let mut s = String::from("12345");
319     s.truncate(6);
320     assert_eq!(s, "12345");
321 }
322
323 #[test]
324 #[should_panic]
325 fn test_str_truncate_split_codepoint() {
326     let mut s = String::from("\u{FC}"); // ü
327     s.truncate(1);
328 }
329
330 #[test]
331 fn test_str_clear() {
332     let mut s = String::from("12345");
333     s.clear();
334     assert_eq!(s.len(), 0);
335     assert_eq!(s, "");
336 }
337
338 #[test]
339 fn test_str_add() {
340     let a = String::from("12345");
341     let b = a + "2";
342     let b = b + "2";
343     assert_eq!(b.len(), 7);
344     assert_eq!(b, "1234522");
345 }
346
347 #[test]
348 fn remove() {
349     let mut s = "ศไทย中华Việt Nam; foobar".to_string();
350     assert_eq!(s.remove(0), 'ศ');
351     assert_eq!(s.len(), 33);
352     assert_eq!(s, "ไทย中华Việt Nam; foobar");
353     assert_eq!(s.remove(17), 'ệ');
354     assert_eq!(s, "ไทย中华Vit Nam; foobar");
355 }
356
357 #[test]
358 #[should_panic]
359 fn remove_bad() {
360     "ศ".to_string().remove(1);
361 }
362
363 #[test]
364 fn test_retain() {
365     let mut s = String::from("α_β_γ");
366
367     s.retain(|_| true);
368     assert_eq!(s, "α_β_γ");
369
370     s.retain(|c| c != '_');
371     assert_eq!(s, "αβγ");
372
373     s.retain(|c| c != 'β');
374     assert_eq!(s, "αγ");
375
376     s.retain(|c| c == 'α');
377     assert_eq!(s, "α");
378
379     s.retain(|_| false);
380     assert_eq!(s, "");
381 }
382
383 #[test]
384 fn insert() {
385     let mut s = "foobar".to_string();
386     s.insert(0, 'ệ');
387     assert_eq!(s, "ệfoobar");
388     s.insert(6, 'ย');
389     assert_eq!(s, "ệfooยbar");
390 }
391
392 #[test]
393 #[should_panic]
394 fn insert_bad1() {
395     "".to_string().insert(1, 't');
396 }
397 #[test]
398 #[should_panic]
399 fn insert_bad2() {
400     "ệ".to_string().insert(1, 't');
401 }
402
403 #[test]
404 fn test_slicing() {
405     let s = "foobar".to_string();
406     assert_eq!("foobar", &s[..]);
407     assert_eq!("foo", &s[..3]);
408     assert_eq!("bar", &s[3..]);
409     assert_eq!("oob", &s[1..4]);
410 }
411
412 #[test]
413 fn test_simple_types() {
414     assert_eq!(1.to_string(), "1");
415     assert_eq!((-1).to_string(), "-1");
416     assert_eq!(200.to_string(), "200");
417     assert_eq!(2.to_string(), "2");
418     assert_eq!(true.to_string(), "true");
419     assert_eq!(false.to_string(), "false");
420     assert_eq!(("hi".to_string()).to_string(), "hi");
421 }
422
423 #[test]
424 fn test_vectors() {
425     let x: Vec<i32> = vec![];
426     assert_eq!(format!("{:?}", x), "[]");
427     assert_eq!(format!("{:?}", vec![1]), "[1]");
428     assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]");
429     assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) == "[[], [1], [1, 1]]");
430 }
431
432 #[test]
433 fn test_from_iterator() {
434     let s = "ศไทย中华Việt Nam".to_string();
435     let t = "ศไทย中华";
436     let u = "Việt Nam";
437
438     let a: String = s.chars().collect();
439     assert_eq!(s, a);
440
441     let mut b = t.to_string();
442     b.extend(u.chars());
443     assert_eq!(s, b);
444
445     let c: String = vec![t, u].into_iter().collect();
446     assert_eq!(s, c);
447
448     let mut d = t.to_string();
449     d.extend(vec![u]);
450     assert_eq!(s, d);
451 }
452
453 #[test]
454 fn test_drain() {
455     let mut s = String::from("αβγ");
456     assert_eq!(s.drain(2..4).collect::<String>(), "β");
457     assert_eq!(s, "αγ");
458
459     let mut t = String::from("abcd");
460     t.drain(..0);
461     assert_eq!(t, "abcd");
462     t.drain(..1);
463     assert_eq!(t, "bcd");
464     t.drain(3..);
465     assert_eq!(t, "bcd");
466     t.drain(..);
467     assert_eq!(t, "");
468 }
469
470 #[test]
471 fn test_replace_range() {
472     let mut s = "Hello, world!".to_owned();
473     s.replace_range(7..12, "世界");
474     assert_eq!(s, "Hello, 世界!");
475 }
476
477 #[test]
478 #[should_panic]
479 fn test_replace_range_char_boundary() {
480     let mut s = "Hello, 世界!".to_owned();
481     s.replace_range(..8, "");
482 }
483
484 #[test]
485 fn test_replace_range_inclusive_range() {
486     let mut v = String::from("12345");
487     v.replace_range(2..=3, "789");
488     assert_eq!(v, "127895");
489     v.replace_range(1..=2, "A");
490     assert_eq!(v, "1A895");
491 }
492
493 #[test]
494 #[should_panic]
495 fn test_replace_range_out_of_bounds() {
496     let mut s = String::from("12345");
497     s.replace_range(5..6, "789");
498 }
499
500 #[test]
501 #[should_panic]
502 fn test_replace_range_inclusive_out_of_bounds() {
503     let mut s = String::from("12345");
504     s.replace_range(5..=5, "789");
505 }
506
507 #[test]
508 fn test_replace_range_empty() {
509     let mut s = String::from("12345");
510     s.replace_range(1..2, "");
511     assert_eq!(s, "1345");
512 }
513
514 #[test]
515 fn test_replace_range_unbounded() {
516     let mut s = String::from("12345");
517     s.replace_range(.., "");
518     assert_eq!(s, "");
519 }
520
521 #[test]
522 fn test_extend_ref() {
523     let mut a = "foo".to_string();
524     a.extend(&['b', 'a', 'r']);
525
526     assert_eq!(&a, "foobar");
527 }
528
529 #[test]
530 fn test_into_boxed_str() {
531     let xs = String::from("hello my name is bob");
532     let ys = xs.into_boxed_str();
533     assert_eq!(&*ys, "hello my name is bob");
534 }
535
536 #[test]
537 fn test_reserve_exact() {
538     // This is all the same as test_reserve
539
540     let mut s = String::new();
541     assert_eq!(s.capacity(), 0);
542
543     s.reserve_exact(2);
544     assert!(s.capacity() >= 2);
545
546     for _i in 0..16 {
547         s.push('0');
548     }
549
550     assert!(s.capacity() >= 16);
551     s.reserve_exact(16);
552     assert!(s.capacity() >= 32);
553
554     s.push('0');
555
556     s.reserve_exact(16);
557     assert!(s.capacity() >= 33)
558 }
559
560 #[test]
561 #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
562 #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc
563 fn test_try_reserve() {
564     // These are the interesting cases:
565     // * exactly isize::MAX should never trigger a CapacityOverflow (can be OOM)
566     // * > isize::MAX should always fail
567     //    * On 16/32-bit should CapacityOverflow
568     //    * On 64-bit should OOM
569     // * overflow may trigger when adding `len` to `cap` (in number of elements)
570     // * overflow may trigger when multiplying `new_cap` by size_of::<T> (to get bytes)
571
572     const MAX_CAP: usize = isize::MAX as usize;
573     const MAX_USIZE: usize = usize::MAX;
574
575     // On 16/32-bit, we check that allocations don't exceed isize::MAX,
576     // on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
577     // Any platform that succeeds for these requests is technically broken with
578     // ptr::offset because LLVM is the worst.
579     let guards_against_isize = size_of::<usize>() < 8;
580
581     {
582         // Note: basic stuff is checked by test_reserve
583         let mut empty_string: String = String::new();
584
585         // Check isize::MAX doesn't count as an overflow
586         if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) {
587             panic!("isize::MAX shouldn't trigger an overflow!");
588         }
589         // Play it again, frank! (just to be sure)
590         if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP) {
591             panic!("isize::MAX shouldn't trigger an overflow!");
592         }
593
594         if guards_against_isize {
595             // Check isize::MAX + 1 does count as overflow
596             if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_CAP + 1) {
597             } else {
598                 panic!("isize::MAX + 1 should trigger an overflow!")
599             }
600
601             // Check usize::MAX does count as overflow
602             if let Err(CapacityOverflow) = empty_string.try_reserve(MAX_USIZE) {
603             } else {
604                 panic!("usize::MAX should trigger an overflow!")
605             }
606         } else {
607             // Check isize::MAX + 1 is an OOM
608             if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_CAP + 1) {
609             } else {
610                 panic!("isize::MAX + 1 should trigger an OOM!")
611             }
612
613             // Check usize::MAX is an OOM
614             if let Err(AllocError { .. }) = empty_string.try_reserve(MAX_USIZE) {
615             } else {
616                 panic!("usize::MAX should trigger an OOM!")
617             }
618         }
619     }
620
621     {
622         // Same basic idea, but with non-zero len
623         let mut ten_bytes: String = String::from("0123456789");
624
625         if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
626             panic!("isize::MAX shouldn't trigger an overflow!");
627         }
628         if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 10) {
629             panic!("isize::MAX shouldn't trigger an overflow!");
630         }
631         if guards_against_isize {
632             if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_CAP - 9) {
633             } else {
634                 panic!("isize::MAX + 1 should trigger an overflow!");
635             }
636         } else {
637             if let Err(AllocError { .. }) = ten_bytes.try_reserve(MAX_CAP - 9) {
638             } else {
639                 panic!("isize::MAX + 1 should trigger an OOM!")
640             }
641         }
642         // Should always overflow in the add-to-len
643         if let Err(CapacityOverflow) = ten_bytes.try_reserve(MAX_USIZE) {
644         } else {
645             panic!("usize::MAX should trigger an overflow!")
646         }
647     }
648 }
649
650 #[test]
651 #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
652 #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc
653 fn test_try_reserve_exact() {
654     // This is exactly the same as test_try_reserve with the method changed.
655     // See that test for comments.
656
657     const MAX_CAP: usize = isize::MAX as usize;
658     const MAX_USIZE: usize = usize::MAX;
659
660     let guards_against_isize = size_of::<usize>() < 8;
661
662     {
663         let mut empty_string: String = String::new();
664
665         if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) {
666             panic!("isize::MAX shouldn't trigger an overflow!");
667         }
668         if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP) {
669             panic!("isize::MAX shouldn't trigger an overflow!");
670         }
671
672         if guards_against_isize {
673             if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_CAP + 1) {
674             } else {
675                 panic!("isize::MAX + 1 should trigger an overflow!")
676             }
677
678             if let Err(CapacityOverflow) = empty_string.try_reserve_exact(MAX_USIZE) {
679             } else {
680                 panic!("usize::MAX should trigger an overflow!")
681             }
682         } else {
683             if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_CAP + 1) {
684             } else {
685                 panic!("isize::MAX + 1 should trigger an OOM!")
686             }
687
688             if let Err(AllocError { .. }) = empty_string.try_reserve_exact(MAX_USIZE) {
689             } else {
690                 panic!("usize::MAX should trigger an OOM!")
691             }
692         }
693     }
694
695     {
696         let mut ten_bytes: String = String::from("0123456789");
697
698         if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
699             panic!("isize::MAX shouldn't trigger an overflow!");
700         }
701         if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 10) {
702             panic!("isize::MAX shouldn't trigger an overflow!");
703         }
704         if guards_against_isize {
705             if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
706             } else {
707                 panic!("isize::MAX + 1 should trigger an overflow!");
708             }
709         } else {
710             if let Err(AllocError { .. }) = ten_bytes.try_reserve_exact(MAX_CAP - 9) {
711             } else {
712                 panic!("isize::MAX + 1 should trigger an OOM!")
713             }
714         }
715         if let Err(CapacityOverflow) = ten_bytes.try_reserve_exact(MAX_USIZE) {
716         } else {
717             panic!("usize::MAX should trigger an overflow!")
718         }
719     }
720 }
721
722 #[test]
723 fn test_from_char() {
724     assert_eq!(String::from('a'), 'a'.to_string());
725     let s: String = 'x'.into();
726     assert_eq!(s, 'x'.to_string());
727 }
728
729 #[test]
730 fn test_str_concat() {
731     let a: String = "hello".to_string();
732     let b: String = "world".to_string();
733     let s: String = format!("{}{}", a, b);
734     assert_eq!(s.as_bytes()[9], 'd' as u8);
735 }