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