]> git.lizzy.rs Git - rust.git/blob - src/libcollectionstest/string.rs
Auto merge of #29303 - petrochenkov:unistrimp, r=eddyb
[rust.git] / src / libcollectionstest / string.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use std::borrow::{IntoCow, Cow};
12 use std::iter::repeat;
13
14 use test::Bencher;
15
16 #[test]
17 fn test_from_str() {
18   let owned: Option<::std::string::String> = "string".parse().ok();
19   assert_eq!(owned.as_ref().map(|s| &**s), Some("string"));
20 }
21
22 #[test]
23 fn test_unsized_to_string() {
24     let s: &str = "abc";
25     let _: String = (*s).to_string();
26 }
27
28 #[test]
29 fn test_from_utf8() {
30     let xs = b"hello".to_vec();
31     assert_eq!(String::from_utf8(xs).unwrap(),
32                String::from("hello"));
33
34     let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
35     assert_eq!(String::from_utf8(xs).unwrap(),
36                String::from("ศไทย中华Việt Nam"));
37
38     let xs = b"hello\xFF".to_vec();
39     let err = String::from_utf8(xs).err().unwrap();
40     assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
41 }
42
43 #[test]
44 fn test_from_utf8_lossy() {
45     let xs = b"hello";
46     let ys: Cow<str> = "hello".into_cow();
47     assert_eq!(String::from_utf8_lossy(xs), ys);
48
49     let xs = "ศไทย中华Việt Nam".as_bytes();
50     let ys: Cow<str> = "ศไทย中华Việt Nam".into_cow();
51     assert_eq!(String::from_utf8_lossy(xs), ys);
52
53     let xs = b"Hello\xC2 There\xFF Goodbye";
54     assert_eq!(String::from_utf8_lossy(xs),
55                String::from("Hello\u{FFFD} There\u{FFFD} Goodbye").into_cow());
56
57     let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
58     assert_eq!(String::from_utf8_lossy(xs),
59                String::from("Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye").into_cow());
60
61     let xs = b"\xF5foo\xF5\x80bar";
62     assert_eq!(String::from_utf8_lossy(xs),
63                String::from("\u{FFFD}foo\u{FFFD}\u{FFFD}bar").into_cow());
64
65     let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
66     assert_eq!(String::from_utf8_lossy(xs),
67                String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz").into_cow());
68
69     let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
70     assert_eq!(String::from_utf8_lossy(xs),
71                String::from("\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz").into_cow());
72
73     let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
74     assert_eq!(String::from_utf8_lossy(xs), String::from("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}\
75                                            foo\u{10000}bar").into_cow());
76
77     // surrogates
78     let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
79     assert_eq!(String::from_utf8_lossy(xs), String::from("\u{FFFD}\u{FFFD}\u{FFFD}foo\
80                                            \u{FFFD}\u{FFFD}\u{FFFD}bar").into_cow());
81 }
82
83 #[test]
84 fn test_from_utf16() {
85     let pairs =
86         [(String::from("𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n"),
87           vec![0xd800, 0xdf45, 0xd800, 0xdf3f,
88             0xd800, 0xdf3b, 0xd800, 0xdf46,
89             0xd800, 0xdf39, 0xd800, 0xdf3b,
90             0xd800, 0xdf30, 0x000a]),
91
92          (String::from("𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n"),
93           vec![0xd801, 0xdc12, 0xd801,
94             0xdc49, 0xd801, 0xdc2e, 0xd801,
95             0xdc40, 0xd801, 0xdc32, 0xd801,
96             0xdc4b, 0x0020, 0xd801, 0xdc0f,
97             0xd801, 0xdc32, 0xd801, 0xdc4d,
98             0x000a]),
99
100          (String::from("𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n"),
101           vec![0xd800, 0xdf00, 0xd800, 0xdf16,
102             0xd800, 0xdf0b, 0xd800, 0xdf04,
103             0xd800, 0xdf11, 0xd800, 0xdf09,
104             0x00b7, 0xd800, 0xdf0c, 0xd800,
105             0xdf04, 0xd800, 0xdf15, 0xd800,
106             0xdf04, 0xd800, 0xdf0b, 0xd800,
107             0xdf09, 0xd800, 0xdf11, 0x000a ]),
108
109          (String::from("𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n"),
110           vec![0xd801, 0xdc8b, 0xd801, 0xdc98,
111             0xd801, 0xdc88, 0xd801, 0xdc91,
112             0xd801, 0xdc9b, 0xd801, 0xdc92,
113             0x0020, 0xd801, 0xdc95, 0xd801,
114             0xdc93, 0x0020, 0xd801, 0xdc88,
115             0xd801, 0xdc9a, 0xd801, 0xdc8d,
116             0x0020, 0xd801, 0xdc8f, 0xd801,
117             0xdc9c, 0xd801, 0xdc92, 0xd801,
118             0xdc96, 0xd801, 0xdc86, 0x0020,
119             0xd801, 0xdc95, 0xd801, 0xdc86,
120             0x000a ]),
121          // Issue #12318, even-numbered non-BMP planes
122          (String::from("\u{20000}"),
123           vec![0xD840, 0xDC00])];
124
125     for p in &pairs {
126         let (s, u) = (*p).clone();
127         let s_as_utf16 = s.utf16_units().collect::<Vec<u16>>();
128         let u_as_string = String::from_utf16(&u).unwrap();
129
130         assert!(::rustc_unicode::str::is_utf16(&u));
131         assert_eq!(s_as_utf16, u);
132
133         assert_eq!(u_as_string, s);
134         assert_eq!(String::from_utf16_lossy(&u), s);
135
136         assert_eq!(String::from_utf16(&s_as_utf16).unwrap(), s);
137         assert_eq!(u_as_string.utf16_units().collect::<Vec<u16>>(), u);
138     }
139 }
140
141 #[test]
142 fn test_utf16_invalid() {
143     // completely positive cases tested above.
144     // lead + eof
145     assert!(String::from_utf16(&[0xD800]).is_err());
146     // lead + lead
147     assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
148
149     // isolated trail
150     assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
151
152     // general
153     assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
154 }
155
156 #[test]
157 fn test_from_utf16_lossy() {
158     // completely positive cases tested above.
159     // lead + eof
160     assert_eq!(String::from_utf16_lossy(&[0xD800]), String::from("\u{FFFD}"));
161     // lead + lead
162     assert_eq!(String::from_utf16_lossy(&[0xD800, 0xD800]),
163                String::from("\u{FFFD}\u{FFFD}"));
164
165     // isolated trail
166     assert_eq!(String::from_utf16_lossy(&[0x0061, 0xDC00]), String::from("a\u{FFFD}"));
167
168     // general
169     assert_eq!(String::from_utf16_lossy(&[0xD800, 0xd801, 0xdc8b, 0xD800]),
170                String::from("\u{FFFD}𐒋\u{FFFD}"));
171 }
172
173 #[test]
174 fn test_push_bytes() {
175     let mut s = String::from("ABC");
176     unsafe {
177         let mv = s.as_mut_vec();
178         mv.push_all(&[b'D']);
179     }
180     assert_eq!(s, "ABCD");
181 }
182
183 #[test]
184 fn test_push_str() {
185     let mut s = String::new();
186     s.push_str("");
187     assert_eq!(&s[0..], "");
188     s.push_str("abc");
189     assert_eq!(&s[0..], "abc");
190     s.push_str("ประเทศไทย中华Việt Nam");
191     assert_eq!(&s[0..], "abcประเทศไทย中华Việt Nam");
192 }
193
194 #[test]
195 fn test_push() {
196     let mut data = String::from("ประเทศไทย中");
197     data.push('华');
198     data.push('b'); // 1 byte
199     data.push('¢'); // 2 byte
200     data.push('€'); // 3 byte
201     data.push('𤭢'); // 4 byte
202     assert_eq!(data, "ประเทศไทย中华b¢€𤭢");
203 }
204
205 #[test]
206 fn test_pop() {
207     let mut data = String::from("ประเทศไทย中华b¢€𤭢");
208     assert_eq!(data.pop().unwrap(), '𤭢'); // 4 bytes
209     assert_eq!(data.pop().unwrap(), '€'); // 3 bytes
210     assert_eq!(data.pop().unwrap(), '¢'); // 2 bytes
211     assert_eq!(data.pop().unwrap(), 'b'); // 1 bytes
212     assert_eq!(data.pop().unwrap(), '华');
213     assert_eq!(data, "ประเทศไทย中");
214 }
215
216 #[test]
217 fn test_str_truncate() {
218     let mut s = String::from("12345");
219     s.truncate(5);
220     assert_eq!(s, "12345");
221     s.truncate(3);
222     assert_eq!(s, "123");
223     s.truncate(0);
224     assert_eq!(s, "");
225
226     let mut s = String::from("12345");
227     let p = s.as_ptr();
228     s.truncate(3);
229     s.push_str("6");
230     let p_ = s.as_ptr();
231     assert_eq!(p_, p);
232 }
233
234 #[test]
235 #[should_panic]
236 fn test_str_truncate_invalid_len() {
237     let mut s = String::from("12345");
238     s.truncate(6);
239 }
240
241 #[test]
242 #[should_panic]
243 fn test_str_truncate_split_codepoint() {
244     let mut s = String::from("\u{FC}"); // ü
245     s.truncate(1);
246 }
247
248 #[test]
249 fn test_str_clear() {
250     let mut s = String::from("12345");
251     s.clear();
252     assert_eq!(s.len(), 0);
253     assert_eq!(s, "");
254 }
255
256 #[test]
257 fn test_str_add() {
258     let a = String::from("12345");
259     let b = a + "2";
260     let b = b + "2";
261     assert_eq!(b.len(), 7);
262     assert_eq!(b, "1234522");
263 }
264
265 #[test]
266 fn remove() {
267     let mut s = "ศไทย中华Việt Nam; foobar".to_string();
268     assert_eq!(s.remove(0), 'ศ');
269     assert_eq!(s.len(), 33);
270     assert_eq!(s, "ไทย中华Việt Nam; foobar");
271     assert_eq!(s.remove(17), 'ệ');
272     assert_eq!(s, "ไทย中华Vit Nam; foobar");
273 }
274
275 #[test] #[should_panic]
276 fn remove_bad() {
277     "ศ".to_string().remove(1);
278 }
279
280 #[test]
281 fn insert() {
282     let mut s = "foobar".to_string();
283     s.insert(0, 'ệ');
284     assert_eq!(s, "ệfoobar");
285     s.insert(6, 'ย');
286     assert_eq!(s, "ệfooยbar");
287 }
288
289 #[test] #[should_panic] fn insert_bad1() { "".to_string().insert(1, 't'); }
290 #[test] #[should_panic] fn insert_bad2() { "ệ".to_string().insert(1, 't'); }
291
292 #[test]
293 fn test_slicing() {
294     let s = "foobar".to_string();
295     assert_eq!("foobar", &s[..]);
296     assert_eq!("foo", &s[..3]);
297     assert_eq!("bar", &s[3..]);
298     assert_eq!("oob", &s[1..4]);
299 }
300
301 #[test]
302 fn test_simple_types() {
303     assert_eq!(1.to_string(), "1");
304     assert_eq!((-1).to_string(), "-1");
305     assert_eq!(200.to_string(), "200");
306     assert_eq!(2.to_string(), "2");
307     assert_eq!(true.to_string(), "true");
308     assert_eq!(false.to_string(), "false");
309     assert_eq!(("hi".to_string()).to_string(), "hi");
310 }
311
312 #[test]
313 fn test_vectors() {
314     let x: Vec<i32> = vec![];
315     assert_eq!(format!("{:?}", x), "[]");
316     assert_eq!(format!("{:?}", vec![1]), "[1]");
317     assert_eq!(format!("{:?}", vec![1, 2, 3]), "[1, 2, 3]");
318     assert!(format!("{:?}", vec![vec![], vec![1], vec![1, 1]]) ==
319            "[[], [1], [1, 1]]");
320 }
321
322 #[test]
323 fn test_from_iterator() {
324     let s = "ศไทย中华Việt Nam".to_string();
325     let t = "ศไทย中华";
326     let u = "Việt Nam";
327
328     let a: String = s.chars().collect();
329     assert_eq!(s, a);
330
331     let mut b = t.to_string();
332     b.extend(u.chars());
333     assert_eq!(s, b);
334
335     let c: String = vec![t, u].into_iter().collect();
336     assert_eq!(s, c);
337
338     let mut d = t.to_string();
339     d.extend(vec![u]);
340     assert_eq!(s, d);
341 }
342
343 #[test]
344 fn test_drain() {
345     let mut s = String::from("αβγ");
346     assert_eq!(s.drain(2..4).collect::<String>(), "β");
347     assert_eq!(s, "αγ");
348
349     let mut t = String::from("abcd");
350     t.drain(..0);
351     assert_eq!(t, "abcd");
352     t.drain(..1);
353     assert_eq!(t, "bcd");
354     t.drain(3..);
355     assert_eq!(t, "bcd");
356     t.drain(..);
357     assert_eq!(t, "");
358 }
359
360 #[test]
361 fn test_extend_ref() {
362     let mut a = "foo".to_string();
363     a.extend(&['b', 'a', 'r']);
364
365     assert_eq!(&a, "foobar");
366 }
367
368 #[test]
369 fn test_into_boxed_str() {
370     let xs = String::from("hello my name is bob");
371     let ys = xs.into_boxed_str();
372     assert_eq!(&*ys, "hello my name is bob");
373 }
374
375 #[bench]
376 fn bench_with_capacity(b: &mut Bencher) {
377     b.iter(|| {
378         String::with_capacity(100)
379     });
380 }
381
382 #[bench]
383 fn bench_push_str(b: &mut Bencher) {
384     let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
385     b.iter(|| {
386         let mut r = String::new();
387         r.push_str(s);
388     });
389 }
390
391 const REPETITIONS: u64 = 10_000;
392
393 #[bench]
394 fn bench_push_str_one_byte(b: &mut Bencher) {
395     b.bytes = REPETITIONS;
396     b.iter(|| {
397         let mut r = String::new();
398         for _ in 0..REPETITIONS {
399             r.push_str("a")
400         }
401     });
402 }
403
404 #[bench]
405 fn bench_push_char_one_byte(b: &mut Bencher) {
406     b.bytes = REPETITIONS;
407     b.iter(|| {
408         let mut r = String::new();
409         for _ in 0..REPETITIONS {
410             r.push('a')
411         }
412     });
413 }
414
415 #[bench]
416 fn bench_push_char_two_bytes(b: &mut Bencher) {
417     b.bytes = REPETITIONS * 2;
418     b.iter(|| {
419         let mut r = String::new();
420         for _ in 0..REPETITIONS {
421             r.push('â')
422         }
423     });
424 }
425
426 #[bench]
427 fn from_utf8_lossy_100_ascii(b: &mut Bencher) {
428     let s = b"Hello there, the quick brown fox jumped over the lazy dog! \
429               Lorem ipsum dolor sit amet, consectetur. ";
430
431     assert_eq!(100, s.len());
432     b.iter(|| {
433         let _ = String::from_utf8_lossy(s);
434     });
435 }
436
437 #[bench]
438 fn from_utf8_lossy_100_multibyte(b: &mut Bencher) {
439     let s = "𐌀𐌖𐌋𐌄𐌑𐌉ปรدولة الكويتทศไทย中华𐍅𐌿𐌻𐍆𐌹𐌻𐌰".as_bytes();
440     assert_eq!(100, s.len());
441     b.iter(|| {
442         let _ = String::from_utf8_lossy(s);
443     });
444 }
445
446 #[bench]
447 fn from_utf8_lossy_invalid(b: &mut Bencher) {
448     let s = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
449     b.iter(|| {
450         let _ = String::from_utf8_lossy(s);
451     });
452 }
453
454 #[bench]
455 fn from_utf8_lossy_100_invalid(b: &mut Bencher) {
456     let s = repeat(0xf5).take(100).collect::<Vec<_>>();
457     b.iter(|| {
458         let _ = String::from_utf8_lossy(&s);
459     });
460 }
461
462 #[bench]
463 fn bench_exact_size_shrink_to_fit(b: &mut Bencher) {
464     let s = "Hello there, the quick brown fox jumped over the lazy dog! \
465              Lorem ipsum dolor sit amet, consectetur. ";
466     // ensure our operation produces an exact-size string before we benchmark it
467     let mut r = String::with_capacity(s.len());
468     r.push_str(s);
469     assert_eq!(r.len(), r.capacity());
470     b.iter(|| {
471         let mut r = String::with_capacity(s.len());
472         r.push_str(s);
473         r.shrink_to_fit();
474         r
475     });
476 }
477
478 #[bench]
479 fn bench_from_str(b: &mut Bencher) {
480     let s = "Hello there, the quick brown fox jumped over the lazy dog! \
481              Lorem ipsum dolor sit amet, consectetur. ";
482     b.iter(|| {
483         String::from(s)
484     })
485 }
486
487 #[bench]
488 fn bench_from(b: &mut Bencher) {
489     let s = "Hello there, the quick brown fox jumped over the lazy dog! \
490              Lorem ipsum dolor sit amet, consectetur. ";
491     b.iter(|| {
492         String::from(s)
493     })
494 }
495
496 #[bench]
497 fn bench_to_string(b: &mut Bencher) {
498     let s = "Hello there, the quick brown fox jumped over the lazy dog! \
499              Lorem ipsum dolor sit amet, consectetur. ";
500     b.iter(|| {
501         s.to_string()
502     })
503 }