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