]> git.proxmox.com Git - rustc.git/blob - src/libcollectionstest/str.rs
Imported Upstream version 1.4.0+dfsg1
[rustc.git] / src / libcollectionstest / str.rs
1 // Copyright 2012-2015 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::cmp::Ordering::{Equal, Greater, Less};
12 use std::str::from_utf8;
13
14 #[test]
15 fn test_le() {
16 assert!("" <= "");
17 assert!("" <= "foo");
18 assert!("foo" <= "foo");
19 assert!("foo" != "bar");
20 }
21
22 #[test]
23 fn test_find() {
24 assert_eq!("hello".find('l'), Some(2));
25 assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
26 assert!("hello".find('x').is_none());
27 assert!("hello".find(|c:char| c == 'x').is_none());
28 assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
29 assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
30 }
31
32 #[test]
33 fn test_rfind() {
34 assert_eq!("hello".rfind('l'), Some(3));
35 assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
36 assert!("hello".rfind('x').is_none());
37 assert!("hello".rfind(|c:char| c == 'x').is_none());
38 assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
39 assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
40 }
41
42 #[test]
43 fn test_collect() {
44 let empty = String::from("");
45 let s: String = empty.chars().collect();
46 assert_eq!(empty, s);
47 let data = String::from("ประเทศไทย中");
48 let s: String = data.chars().collect();
49 assert_eq!(data, s);
50 }
51
52 #[test]
53 fn test_into_bytes() {
54 let data = String::from("asdf");
55 let buf = data.into_bytes();
56 assert_eq!(buf, b"asdf");
57 }
58
59 #[test]
60 fn test_find_str() {
61 // byte positions
62 assert_eq!("".find(""), Some(0));
63 assert!("banana".find("apple pie").is_none());
64
65 let data = "abcabc";
66 assert_eq!(data[0..6].find("ab"), Some(0));
67 assert_eq!(data[2..6].find("ab"), Some(3 - 2));
68 assert!(data[2..4].find("ab").is_none());
69
70 let string = "ประเทศไทย中华Việt Nam";
71 let mut data = String::from(string);
72 data.push_str(string);
73 assert!(data.find("ไท华").is_none());
74 assert_eq!(data[0..43].find(""), Some(0));
75 assert_eq!(data[6..43].find(""), Some(6 - 6));
76
77 assert_eq!(data[0..43].find("ประ"), Some( 0));
78 assert_eq!(data[0..43].find("ทศไ"), Some(12));
79 assert_eq!(data[0..43].find("ย中"), Some(24));
80 assert_eq!(data[0..43].find("iệt"), Some(34));
81 assert_eq!(data[0..43].find("Nam"), Some(40));
82
83 assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
84 assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
85 assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
86 assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
87 assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
88
89 // find every substring -- assert that it finds it, or an earlier occurence.
90 let string = "Việt Namacbaabcaabaaba";
91 for (i, ci) in string.char_indices() {
92 let ip = i + ci.len_utf8();
93 for j in string[ip..].char_indices()
94 .map(|(i, _)| i)
95 .chain(Some(string.len() - ip))
96 {
97 let pat = &string[i..ip + j];
98 assert!(match string.find(pat) {
99 None => false,
100 Some(x) => x <= i,
101 });
102 assert!(match string.rfind(pat) {
103 None => false,
104 Some(x) => x >= i,
105 });
106 }
107 }
108 }
109
110 fn s(x: &str) -> String { x.to_string() }
111
112 macro_rules! test_concat {
113 ($expected: expr, $string: expr) => {
114 {
115 let s: String = $string.concat();
116 assert_eq!($expected, s);
117 }
118 }
119 }
120
121 #[test]
122 fn test_concat_for_different_types() {
123 test_concat!("ab", vec![s("a"), s("b")]);
124 test_concat!("ab", vec!["a", "b"]);
125 test_concat!("ab", vec!["a", "b"]);
126 test_concat!("ab", vec![s("a"), s("b")]);
127 }
128
129 #[test]
130 fn test_concat_for_different_lengths() {
131 let empty: &[&str] = &[];
132 test_concat!("", empty);
133 test_concat!("a", ["a"]);
134 test_concat!("ab", ["a", "b"]);
135 test_concat!("abc", ["", "a", "bc"]);
136 }
137
138 macro_rules! test_join {
139 ($expected: expr, $string: expr, $delim: expr) => {
140 {
141 let s = $string.join($delim);
142 assert_eq!($expected, s);
143 }
144 }
145 }
146
147 #[test]
148 fn test_join_for_different_types() {
149 test_join!("a-b", ["a", "b"], "-");
150 let hyphen = "-".to_string();
151 test_join!("a-b", [s("a"), s("b")], &*hyphen);
152 test_join!("a-b", vec!["a", "b"], &*hyphen);
153 test_join!("a-b", &*vec!["a", "b"], "-");
154 test_join!("a-b", vec![s("a"), s("b")], "-");
155 }
156
157 #[test]
158 fn test_join_for_different_lengths() {
159 let empty: &[&str] = &[];
160 test_join!("", empty, "-");
161 test_join!("a", ["a"], "-");
162 test_join!("a-b", ["a", "b"], "-");
163 test_join!("-a-bc", ["", "a", "bc"], "-");
164 }
165
166 #[test]
167 fn test_unsafe_slice() {
168 assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)});
169 assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)});
170 assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)});
171 fn a_million_letter_a() -> String {
172 let mut i = 0;
173 let mut rs = String::new();
174 while i < 100000 {
175 rs.push_str("aaaaaaaaaa");
176 i += 1;
177 }
178 rs
179 }
180 fn half_a_million_letter_a() -> String {
181 let mut i = 0;
182 let mut rs = String::new();
183 while i < 100000 {
184 rs.push_str("aaaaa");
185 i += 1;
186 }
187 rs
188 }
189 let letters = a_million_letter_a();
190 assert!(half_a_million_letter_a() ==
191 unsafe {String::from(letters.slice_unchecked(
192 0,
193 500000))});
194 }
195
196 #[test]
197 fn test_starts_with() {
198 assert!(("".starts_with("")));
199 assert!(("abc".starts_with("")));
200 assert!(("abc".starts_with("a")));
201 assert!((!"a".starts_with("abc")));
202 assert!((!"".starts_with("abc")));
203 assert!((!"ödd".starts_with("-")));
204 assert!(("ödd".starts_with("öd")));
205 }
206
207 #[test]
208 fn test_ends_with() {
209 assert!(("".ends_with("")));
210 assert!(("abc".ends_with("")));
211 assert!(("abc".ends_with("c")));
212 assert!((!"a".ends_with("abc")));
213 assert!((!"".ends_with("abc")));
214 assert!((!"ddö".ends_with("-")));
215 assert!(("ddö".ends_with("dö")));
216 }
217
218 #[test]
219 fn test_is_empty() {
220 assert!("".is_empty());
221 assert!(!"a".is_empty());
222 }
223
224 #[test]
225 fn test_replace() {
226 let a = "a";
227 assert_eq!("".replace(a, "b"), String::from(""));
228 assert_eq!("a".replace(a, "b"), String::from("b"));
229 assert_eq!("ab".replace(a, "b"), String::from("bb"));
230 let test = "test";
231 assert!(" test test ".replace(test, "toast") ==
232 String::from(" toast toast "));
233 assert_eq!(" test test ".replace(test, ""), String::from(" "));
234 }
235
236 #[test]
237 fn test_replace_2a() {
238 let data = "ประเทศไทย中华";
239 let repl = "دولة الكويت";
240
241 let a = "ประเ";
242 let a2 = "دولة الكويتทศไทย中华";
243 assert_eq!(data.replace(a, repl), a2);
244 }
245
246 #[test]
247 fn test_replace_2b() {
248 let data = "ประเทศไทย中华";
249 let repl = "دولة الكويت";
250
251 let b = "ะเ";
252 let b2 = "ปรدولة الكويتทศไทย中华";
253 assert_eq!(data.replace(b, repl), b2);
254 }
255
256 #[test]
257 fn test_replace_2c() {
258 let data = "ประเทศไทย中华";
259 let repl = "دولة الكويت";
260
261 let c = "中华";
262 let c2 = "ประเทศไทยدولة الكويت";
263 assert_eq!(data.replace(c, repl), c2);
264 }
265
266 #[test]
267 fn test_replace_2d() {
268 let data = "ประเทศไทย中华";
269 let repl = "دولة الكويت";
270
271 let d = "ไท华";
272 assert_eq!(data.replace(d, repl), data);
273 }
274
275 #[test]
276 fn test_slice() {
277 assert_eq!("ab", &"abc"[0..2]);
278 assert_eq!("bc", &"abc"[1..3]);
279 assert_eq!("", &"abc"[1..1]);
280 assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]);
281
282 let data = "ประเทศไทย中华";
283 assert_eq!("ป", &data[0..3]);
284 assert_eq!("ร", &data[3..6]);
285 assert_eq!("", &data[3..3]);
286 assert_eq!("华", &data[30..33]);
287
288 fn a_million_letter_x() -> String {
289 let mut i = 0;
290 let mut rs = String::new();
291 while i < 100000 {
292 rs.push_str("华华华华华华华华华华");
293 i += 1;
294 }
295 rs
296 }
297 fn half_a_million_letter_x() -> String {
298 let mut i = 0;
299 let mut rs = String::new();
300 while i < 100000 {
301 rs.push_str("华华华华华");
302 i += 1;
303 }
304 rs
305 }
306 let letters = a_million_letter_x();
307 assert!(half_a_million_letter_x() ==
308 String::from(&letters[0..3 * 500000]));
309 }
310
311 #[test]
312 fn test_slice_2() {
313 let ss = "中华Việt Nam";
314
315 assert_eq!("华", &ss[3..6]);
316 assert_eq!("Việt Nam", &ss[6..16]);
317
318 assert_eq!("ab", &"abc"[0..2]);
319 assert_eq!("bc", &"abc"[1..3]);
320 assert_eq!("", &"abc"[1..1]);
321
322 assert_eq!("中", &ss[0..3]);
323 assert_eq!("华V", &ss[3..7]);
324 assert_eq!("", &ss[3..3]);
325 /*0: 中
326 3: 华
327 6: V
328 7: i
329 8: ệ
330 11: t
331 12:
332 13: N
333 14: a
334 15: m */
335 }
336
337 #[test]
338 #[should_panic]
339 fn test_slice_fail() {
340 &"中华Việt Nam"[0..2];
341 }
342
343 #[test]
344 fn test_slice_from() {
345 assert_eq!(&"abcd"[0..], "abcd");
346 assert_eq!(&"abcd"[2..], "cd");
347 assert_eq!(&"abcd"[4..], "");
348 }
349 #[test]
350 fn test_slice_to() {
351 assert_eq!(&"abcd"[..0], "");
352 assert_eq!(&"abcd"[..2], "ab");
353 assert_eq!(&"abcd"[..4], "abcd");
354 }
355
356 #[test]
357 fn test_trim_left_matches() {
358 let v: &[char] = &[];
359 assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** ");
360 let chars: &[char] = &['*', ' '];
361 assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** ");
362 assert_eq!(" *** *** ".trim_left_matches(chars), "");
363 assert_eq!("foo *** ".trim_left_matches(chars), "foo *** ");
364
365 assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
366 let chars: &[char] = &['1', '2'];
367 assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12");
368 assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
369 }
370
371 #[test]
372 fn test_trim_right_matches() {
373 let v: &[char] = &[];
374 assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** ");
375 let chars: &[char] = &['*', ' '];
376 assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo");
377 assert_eq!(" *** *** ".trim_right_matches(chars), "");
378 assert_eq!(" *** foo".trim_right_matches(chars), " *** foo");
379
380 assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
381 let chars: &[char] = &['1', '2'];
382 assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar");
383 assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
384 }
385
386 #[test]
387 fn test_trim_matches() {
388 let v: &[char] = &[];
389 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
390 let chars: &[char] = &['*', ' '];
391 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
392 assert_eq!(" *** *** ".trim_matches(chars), "");
393 assert_eq!("foo".trim_matches(chars), "foo");
394
395 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
396 let chars: &[char] = &['1', '2'];
397 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
398 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
399 }
400
401 #[test]
402 fn test_trim_left() {
403 assert_eq!("".trim_left(), "");
404 assert_eq!("a".trim_left(), "a");
405 assert_eq!(" ".trim_left(), "");
406 assert_eq!(" blah".trim_left(), "blah");
407 assert_eq!(" \u{3000} wut".trim_left(), "wut");
408 assert_eq!("hey ".trim_left(), "hey ");
409 }
410
411 #[test]
412 fn test_trim_right() {
413 assert_eq!("".trim_right(), "");
414 assert_eq!("a".trim_right(), "a");
415 assert_eq!(" ".trim_right(), "");
416 assert_eq!("blah ".trim_right(), "blah");
417 assert_eq!("wut \u{3000} ".trim_right(), "wut");
418 assert_eq!(" hey".trim_right(), " hey");
419 }
420
421 #[test]
422 fn test_trim() {
423 assert_eq!("".trim(), "");
424 assert_eq!("a".trim(), "a");
425 assert_eq!(" ".trim(), "");
426 assert_eq!(" blah ".trim(), "blah");
427 assert_eq!("\nwut \u{3000} ".trim(), "wut");
428 assert_eq!(" hey dude ".trim(), "hey dude");
429 }
430
431 #[test]
432 fn test_is_whitespace() {
433 assert!("".chars().all(|c| c.is_whitespace()));
434 assert!(" ".chars().all(|c| c.is_whitespace()));
435 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
436 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
437 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
438 }
439
440 #[test]
441 fn test_slice_shift_char() {
442 let data = "ประเทศไทย中";
443 assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中")));
444 }
445
446 #[test]
447 fn test_slice_shift_char_2() {
448 let empty = "";
449 assert_eq!(empty.slice_shift_char(), None);
450 }
451
452 #[test]
453 fn test_is_utf8() {
454 // deny overlong encodings
455 assert!(from_utf8(&[0xc0, 0x80]).is_err());
456 assert!(from_utf8(&[0xc0, 0xae]).is_err());
457 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
458 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
459 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
460 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
461 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
462
463 // deny surrogates
464 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
465 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
466
467 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
468 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
469 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
470 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
471 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
472 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
473 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
474 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
475 }
476
477 #[test]
478 fn test_is_utf16() {
479 use rustc_unicode::str::is_utf16;
480
481 macro_rules! pos {
482 ($($e:expr),*) => { { $(assert!(is_utf16($e));)* } }
483 }
484
485 // non-surrogates
486 pos!(&[0x0000],
487 &[0x0001, 0x0002],
488 &[0xD7FF],
489 &[0xE000]);
490
491 // surrogate pairs (randomly generated with Python 3's
492 // .encode('utf-16be'))
493 pos!(&[0xdb54, 0xdf16, 0xd880, 0xdee0, 0xdb6a, 0xdd45],
494 &[0xd91f, 0xdeb1, 0xdb31, 0xdd84, 0xd8e2, 0xde14],
495 &[0xdb9f, 0xdc26, 0xdb6f, 0xde58, 0xd850, 0xdfae]);
496
497 // mixtures (also random)
498 pos!(&[0xd921, 0xdcc2, 0x002d, 0x004d, 0xdb32, 0xdf65],
499 &[0xdb45, 0xdd2d, 0x006a, 0xdacd, 0xddfe, 0x0006],
500 &[0x0067, 0xd8ff, 0xddb7, 0x000f, 0xd900, 0xdc80]);
501
502 // negative tests
503 macro_rules! neg {
504 ($($e:expr),*) => { { $(assert!(!is_utf16($e));)* } }
505 }
506
507 neg!(
508 // surrogate + regular unit
509 &[0xdb45, 0x0000],
510 // surrogate + lead surrogate
511 &[0xd900, 0xd900],
512 // unterminated surrogate
513 &[0xd8ff],
514 // trail surrogate without a lead
515 &[0xddb7]);
516
517 // random byte sequences that Python 3's .decode('utf-16be')
518 // failed on
519 neg!(&[0x5b3d, 0x0141, 0xde9e, 0x8fdc, 0xc6e7],
520 &[0xdf5a, 0x82a5, 0x62b9, 0xb447, 0x92f3],
521 &[0xda4e, 0x42bc, 0x4462, 0xee98, 0xc2ca],
522 &[0xbe00, 0xb04a, 0x6ecb, 0xdd89, 0xe278],
523 &[0x0465, 0xab56, 0xdbb6, 0xa893, 0x665e],
524 &[0x6b7f, 0x0a19, 0x40f4, 0xa657, 0xdcc5],
525 &[0x9b50, 0xda5e, 0x24ec, 0x03ad, 0x6dee],
526 &[0x8d17, 0xcaa7, 0xf4ae, 0xdf6e, 0xbed7],
527 &[0xdaee, 0x2584, 0x7d30, 0xa626, 0x121a],
528 &[0xd956, 0x4b43, 0x7570, 0xccd6, 0x4f4a],
529 &[0x9dcf, 0x1b49, 0x4ba5, 0xfce9, 0xdffe],
530 &[0x6572, 0xce53, 0xb05a, 0xf6af, 0xdacf],
531 &[0x1b90, 0x728c, 0x9906, 0xdb68, 0xf46e],
532 &[0x1606, 0xbeca, 0xbe76, 0x860f, 0xdfa5],
533 &[0x8b4f, 0xde7a, 0xd220, 0x9fac, 0x2b6f],
534 &[0xb8fe, 0xebbe, 0xda32, 0x1a5f, 0x8b8b],
535 &[0x934b, 0x8956, 0xc434, 0x1881, 0xddf7],
536 &[0x5a95, 0x13fc, 0xf116, 0xd89b, 0x93f9],
537 &[0xd640, 0x71f1, 0xdd7d, 0x77eb, 0x1cd8],
538 &[0x348b, 0xaef0, 0xdb2c, 0xebf1, 0x1282],
539 &[0x50d7, 0xd824, 0x5010, 0xb369, 0x22ea]);
540 }
541
542 #[test]
543 fn test_as_bytes() {
544 // no null
545 let v = [
546 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
547 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
548 109
549 ];
550 let b: &[u8] = &[];
551 assert_eq!("".as_bytes(), b);
552 assert_eq!("abc".as_bytes(), b"abc");
553 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
554 }
555
556 #[test]
557 #[should_panic]
558 fn test_as_bytes_fail() {
559 // Don't double free. (I'm not sure if this exercises the
560 // original problem code path anymore.)
561 let s = String::from("");
562 let _bytes = s.as_bytes();
563 panic!();
564 }
565
566 #[test]
567 fn test_as_ptr() {
568 let buf = "hello".as_ptr();
569 unsafe {
570 assert_eq!(*buf.offset(0), b'h');
571 assert_eq!(*buf.offset(1), b'e');
572 assert_eq!(*buf.offset(2), b'l');
573 assert_eq!(*buf.offset(3), b'l');
574 assert_eq!(*buf.offset(4), b'o');
575 }
576 }
577
578 #[test]
579 fn vec_str_conversions() {
580 let s1: String = String::from("All mimsy were the borogoves");
581
582 let v: Vec<u8> = s1.as_bytes().to_vec();
583 let s2: String = String::from(from_utf8(&v).unwrap());
584 let mut i = 0;
585 let n1 = s1.len();
586 let n2 = v.len();
587 assert_eq!(n1, n2);
588 while i < n1 {
589 let a: u8 = s1.as_bytes()[i];
590 let b: u8 = s2.as_bytes()[i];
591 debug!("{}", a);
592 debug!("{}", b);
593 assert_eq!(a, b);
594 i += 1;
595 }
596 }
597
598 #[test]
599 fn test_contains() {
600 assert!("abcde".contains("bcd"));
601 assert!("abcde".contains("abcd"));
602 assert!("abcde".contains("bcde"));
603 assert!("abcde".contains(""));
604 assert!("".contains(""));
605 assert!(!"abcde".contains("def"));
606 assert!(!"".contains("a"));
607
608 let data = "ประเทศไทย中华Việt Nam";
609 assert!(data.contains("ประเ"));
610 assert!(data.contains("ะเ"));
611 assert!(data.contains("中华"));
612 assert!(!data.contains("ไท华"));
613 }
614
615 #[test]
616 fn test_contains_char() {
617 assert!("abc".contains('b'));
618 assert!("a".contains('a'));
619 assert!(!"abc".contains('d'));
620 assert!(!"".contains('a'));
621 }
622
623 #[test]
624 fn test_char_at() {
625 let s = "ศไทย中华Việt Nam";
626 let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
627 let mut pos = 0;
628 for ch in &v {
629 assert!(s.char_at(pos) == *ch);
630 pos += ch.to_string().len();
631 }
632 }
633
634 #[test]
635 fn test_char_at_reverse() {
636 let s = "ศไทย中华Việt Nam";
637 let v = vec!['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
638 let mut pos = s.len();
639 for ch in v.iter().rev() {
640 assert!(s.char_at_reverse(pos) == *ch);
641 pos -= ch.to_string().len();
642 }
643 }
644
645 #[test]
646 fn test_split_at() {
647 let s = "ศไทย中华Việt Nam";
648 for (index, _) in s.char_indices() {
649 let (a, b) = s.split_at(index);
650 assert_eq!(&s[..a.len()], a);
651 assert_eq!(&s[a.len()..], b);
652 }
653 let (a, b) = s.split_at(s.len());
654 assert_eq!(a, s);
655 assert_eq!(b, "");
656 }
657
658 #[test]
659 fn test_split_at_mut() {
660 use std::ascii::AsciiExt;
661 let mut s = "Hello World".to_string();
662 {
663 let (a, b) = s.split_at_mut(5);
664 a.make_ascii_uppercase();
665 b.make_ascii_lowercase();
666 }
667 assert_eq!(s, "HELLO world");
668 }
669
670 #[test]
671 #[should_panic]
672 fn test_split_at_boundscheck() {
673 let s = "ศไทย中华Việt Nam";
674 s.split_at(1);
675 }
676
677 #[test]
678 fn test_escape_unicode() {
679 assert_eq!("abc".escape_unicode(),
680 String::from("\\u{61}\\u{62}\\u{63}"));
681 assert_eq!("a c".escape_unicode(),
682 String::from("\\u{61}\\u{20}\\u{63}"));
683 assert_eq!("\r\n\t".escape_unicode(),
684 String::from("\\u{d}\\u{a}\\u{9}"));
685 assert_eq!("'\"\\".escape_unicode(),
686 String::from("\\u{27}\\u{22}\\u{5c}"));
687 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(),
688 String::from("\\u{0}\\u{1}\\u{fe}\\u{ff}"));
689 assert_eq!("\u{100}\u{ffff}".escape_unicode(),
690 String::from("\\u{100}\\u{ffff}"));
691 assert_eq!("\u{10000}\u{10ffff}".escape_unicode(),
692 String::from("\\u{10000}\\u{10ffff}"));
693 assert_eq!("ab\u{fb00}".escape_unicode(),
694 String::from("\\u{61}\\u{62}\\u{fb00}"));
695 assert_eq!("\u{1d4ea}\r".escape_unicode(),
696 String::from("\\u{1d4ea}\\u{d}"));
697 }
698
699 #[test]
700 fn test_escape_default() {
701 assert_eq!("abc".escape_default(), String::from("abc"));
702 assert_eq!("a c".escape_default(), String::from("a c"));
703 assert_eq!("\r\n\t".escape_default(), String::from("\\r\\n\\t"));
704 assert_eq!("'\"\\".escape_default(), String::from("\\'\\\"\\\\"));
705 assert_eq!("\u{100}\u{ffff}".escape_default(),
706 String::from("\\u{100}\\u{ffff}"));
707 assert_eq!("\u{10000}\u{10ffff}".escape_default(),
708 String::from("\\u{10000}\\u{10ffff}"));
709 assert_eq!("ab\u{fb00}".escape_default(),
710 String::from("ab\\u{fb00}"));
711 assert_eq!("\u{1d4ea}\r".escape_default(),
712 String::from("\\u{1d4ea}\\r"));
713 }
714
715 #[test]
716 fn test_total_ord() {
717 "1234".cmp("123") == Greater;
718 "123".cmp("1234") == Less;
719 "1234".cmp("1234") == Equal;
720 "12345555".cmp("123456") == Less;
721 "22".cmp("1234") == Greater;
722 }
723
724 #[test]
725 fn test_char_range_at() {
726 let data = "b¢€𤭢𤭢€¢b";
727 assert_eq!('b', data.char_range_at(0).ch);
728 assert_eq!('¢', data.char_range_at(1).ch);
729 assert_eq!('€', data.char_range_at(3).ch);
730 assert_eq!('𤭢', data.char_range_at(6).ch);
731 assert_eq!('𤭢', data.char_range_at(10).ch);
732 assert_eq!('€', data.char_range_at(14).ch);
733 assert_eq!('¢', data.char_range_at(17).ch);
734 assert_eq!('b', data.char_range_at(19).ch);
735 }
736
737 #[test]
738 fn test_char_range_at_reverse_underflow() {
739 assert_eq!("abc".char_range_at_reverse(0).next, 0);
740 }
741
742 #[test]
743 fn test_iterator() {
744 let s = "ศไทย中华Việt Nam";
745 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
746
747 let mut pos = 0;
748 let it = s.chars();
749
750 for c in it {
751 assert_eq!(c, v[pos]);
752 pos += 1;
753 }
754 assert_eq!(pos, v.len());
755 }
756
757 #[test]
758 fn test_rev_iterator() {
759 let s = "ศไทย中华Việt Nam";
760 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
761
762 let mut pos = 0;
763 let it = s.chars().rev();
764
765 for c in it {
766 assert_eq!(c, v[pos]);
767 pos += 1;
768 }
769 assert_eq!(pos, v.len());
770 }
771
772 #[test]
773 fn test_chars_decoding() {
774 let mut bytes = [0; 4];
775 for c in (0..0x110000).filter_map(::std::char::from_u32) {
776 let len = c.encode_utf8(&mut bytes).unwrap_or(0);
777 let s = ::std::str::from_utf8(&bytes[..len]).unwrap();
778 if Some(c) != s.chars().next() {
779 panic!("character {:x}={} does not decode correctly", c as u32, c);
780 }
781 }
782 }
783
784 #[test]
785 fn test_chars_rev_decoding() {
786 let mut bytes = [0; 4];
787 for c in (0..0x110000).filter_map(::std::char::from_u32) {
788 let len = c.encode_utf8(&mut bytes).unwrap_or(0);
789 let s = ::std::str::from_utf8(&bytes[..len]).unwrap();
790 if Some(c) != s.chars().rev().next() {
791 panic!("character {:x}={} does not decode correctly", c as u32, c);
792 }
793 }
794 }
795
796 #[test]
797 fn test_iterator_clone() {
798 let s = "ศไทย中华Việt Nam";
799 let mut it = s.chars();
800 it.next();
801 assert!(it.clone().zip(it).all(|(x,y)| x == y));
802 }
803
804 #[test]
805 fn test_bytesator() {
806 let s = "ศไทย中华Việt Nam";
807 let v = [
808 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
809 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
810 109
811 ];
812 let mut pos = 0;
813
814 for b in s.bytes() {
815 assert_eq!(b, v[pos]);
816 pos += 1;
817 }
818 }
819
820 #[test]
821 fn test_bytes_revator() {
822 let s = "ศไทย中华Việt Nam";
823 let v = [
824 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
825 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
826 109
827 ];
828 let mut pos = v.len();
829
830 for b in s.bytes().rev() {
831 pos -= 1;
832 assert_eq!(b, v[pos]);
833 }
834 }
835
836 #[test]
837 fn test_bytesator_nth() {
838 let s = "ศไทย中华Việt Nam";
839 let v = [
840 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
841 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
842 109
843 ];
844
845 let mut b = s.bytes();
846 assert_eq!(b.nth(2).unwrap(), v[2]);
847 assert_eq!(b.nth(10).unwrap(), v[10]);
848 assert_eq!(b.nth(200), None);
849 }
850
851 #[test]
852 fn test_bytesator_count() {
853 let s = "ศไทย中华Việt Nam";
854
855 let b = s.bytes();
856 assert_eq!(b.count(), 28)
857 }
858
859 #[test]
860 fn test_bytesator_last() {
861 let s = "ศไทย中华Việt Nam";
862
863 let b = s.bytes();
864 assert_eq!(b.last().unwrap(), 109)
865 }
866
867 #[test]
868 fn test_char_indicesator() {
869 let s = "ศไทย中华Việt Nam";
870 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
871 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
872
873 let mut pos = 0;
874 let it = s.char_indices();
875
876 for c in it {
877 assert_eq!(c, (p[pos], v[pos]));
878 pos += 1;
879 }
880 assert_eq!(pos, v.len());
881 assert_eq!(pos, p.len());
882 }
883
884 #[test]
885 fn test_char_indices_revator() {
886 let s = "ศไทย中华Việt Nam";
887 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
888 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
889
890 let mut pos = 0;
891 let it = s.char_indices().rev();
892
893 for c in it {
894 assert_eq!(c, (p[pos], v[pos]));
895 pos += 1;
896 }
897 assert_eq!(pos, v.len());
898 assert_eq!(pos, p.len());
899 }
900
901 #[test]
902 fn test_splitn_char_iterator() {
903 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
904
905 let split: Vec<&str> = data.splitn(4, ' ').collect();
906 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
907
908 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
909 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
910
911 // Unicode
912 let split: Vec<&str> = data.splitn(4, 'ä').collect();
913 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
914
915 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
916 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
917 }
918
919 #[test]
920 fn test_split_char_iterator_no_trailing() {
921 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
922
923 let split: Vec<&str> = data.split('\n').collect();
924 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
925
926 let split: Vec<&str> = data.split_terminator('\n').collect();
927 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
928 }
929
930 #[test]
931 fn test_rsplit() {
932 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
933
934 let split: Vec<&str> = data.rsplit(' ').collect();
935 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
936
937 let split: Vec<&str> = data.rsplit("lämb").collect();
938 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
939
940 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
941 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
942 }
943
944 #[test]
945 fn test_rsplitn() {
946 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
947
948 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
949 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
950
951 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
952 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
953
954 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
955 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
956 }
957
958 #[test]
959 fn test_split_whitespace() {
960 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
961 let words: Vec<&str> = data.split_whitespace().collect();
962 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
963 }
964
965 #[test]
966 fn test_lines() {
967 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
968 let lines: Vec<&str> = data.lines().collect();
969 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
970
971 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
972 let lines: Vec<&str> = data.lines().collect();
973 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
974 }
975
976 #[test]
977 fn test_splitator() {
978 fn t(s: &str, sep: &str, u: &[&str]) {
979 let v: Vec<&str> = s.split(sep).collect();
980 assert_eq!(v, u);
981 }
982 t("--1233345--", "12345", &["--1233345--"]);
983 t("abc::hello::there", "::", &["abc", "hello", "there"]);
984 t("::hello::there", "::", &["", "hello", "there"]);
985 t("hello::there::", "::", &["hello", "there", ""]);
986 t("::hello::there::", "::", &["", "hello", "there", ""]);
987 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
988 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
989 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
990 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
991 t("", ".", &[""]);
992 t("zz", "zz", &["",""]);
993 t("ok", "z", &["ok"]);
994 t("zzz", "zz", &["","z"]);
995 t("zzzzz", "zz", &["","","z"]);
996 }
997
998 #[test]
999 fn test_str_default() {
1000 use std::default::Default;
1001
1002 fn t<S: Default + AsRef<str>>() {
1003 let s: S = Default::default();
1004 assert_eq!(s.as_ref(), "");
1005 }
1006
1007 t::<&str>();
1008 t::<String>();
1009 }
1010
1011 #[test]
1012 fn test_str_container() {
1013 fn sum_len(v: &[&str]) -> usize {
1014 v.iter().map(|x| x.len()).sum()
1015 }
1016
1017 let s = String::from("01234");
1018 assert_eq!(5, sum_len(&["012", "", "34"]));
1019 assert_eq!(5, sum_len(&[&String::from("01"),
1020 &String::from("2"),
1021 &String::from("34"),
1022 &String::from("")]));
1023 assert_eq!(5, sum_len(&[&s]));
1024 }
1025
1026 #[test]
1027 fn test_str_from_utf8() {
1028 let xs = b"hello";
1029 assert_eq!(from_utf8(xs), Ok("hello"));
1030
1031 let xs = "ศไทย中华Việt Nam".as_bytes();
1032 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1033
1034 let xs = b"hello\xFF";
1035 assert!(from_utf8(xs).is_err());
1036 }
1037
1038 #[test]
1039 fn test_pattern_deref_forward() {
1040 let data = "aabcdaa";
1041 assert!(data.contains("bcd"));
1042 assert!(data.contains(&"bcd"));
1043 assert!(data.contains(&"bcd".to_string()));
1044 }
1045
1046 #[test]
1047 fn test_empty_match_indices() {
1048 let data = "aä中!";
1049 let vec: Vec<_> = data.match_indices("").collect();
1050 assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
1051 }
1052
1053 #[test]
1054 fn test_bool_from_str() {
1055 assert_eq!("true".parse().ok(), Some(true));
1056 assert_eq!("false".parse().ok(), Some(false));
1057 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1058 }
1059
1060 fn check_contains_all_substrings(s: &str) {
1061 assert!(s.contains(""));
1062 for i in 0..s.len() {
1063 for j in i+1..s.len() + 1 {
1064 assert!(s.contains(&s[i..j]));
1065 }
1066 }
1067 }
1068
1069 #[test]
1070 fn strslice_issue_16589() {
1071 assert!("bananas".contains("nana"));
1072
1073 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1074 // test all substrings for good measure
1075 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1076 }
1077
1078 #[test]
1079 fn strslice_issue_16878() {
1080 assert!(!"1234567ah012345678901ah".contains("hah"));
1081 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1082 }
1083
1084
1085 #[test]
1086 fn test_strslice_contains() {
1087 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1088 check_contains_all_substrings(x);
1089 }
1090
1091 #[test]
1092 fn test_rsplitn_char_iterator() {
1093 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1094
1095 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1096 split.reverse();
1097 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1098
1099 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1100 split.reverse();
1101 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1102
1103 // Unicode
1104 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1105 split.reverse();
1106 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1107
1108 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1109 split.reverse();
1110 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1111 }
1112
1113 #[test]
1114 fn test_split_char_iterator() {
1115 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1116
1117 let split: Vec<&str> = data.split(' ').collect();
1118 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1119
1120 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1121 rsplit.reverse();
1122 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1123
1124 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1125 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1126
1127 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1128 rsplit.reverse();
1129 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1130
1131 // Unicode
1132 let split: Vec<&str> = data.split('ä').collect();
1133 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1134
1135 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1136 rsplit.reverse();
1137 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1138
1139 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1140 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1141
1142 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1143 rsplit.reverse();
1144 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1145 }
1146
1147 #[test]
1148 fn test_rev_split_char_iterator_no_trailing() {
1149 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1150
1151 let mut split: Vec<&str> = data.split('\n').rev().collect();
1152 split.reverse();
1153 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1154
1155 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1156 split.reverse();
1157 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1158 }
1159
1160 #[test]
1161 fn test_utf16_code_units() {
1162 use rustc_unicode::str::Utf16Encoder;
1163 assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
1164 [0xE9, 0xD83D, 0xDCA9])
1165 }
1166
1167 #[test]
1168 fn starts_with_in_unicode() {
1169 assert!(!"├── Cargo.toml".starts_with("# "));
1170 }
1171
1172 #[test]
1173 fn starts_short_long() {
1174 assert!(!"".starts_with("##"));
1175 assert!(!"##".starts_with("####"));
1176 assert!("####".starts_with("##"));
1177 assert!(!"##ä".starts_with("####"));
1178 assert!("####ä".starts_with("##"));
1179 assert!(!"##".starts_with("####ä"));
1180 assert!("##ä##".starts_with("##ä"));
1181
1182 assert!("".starts_with(""));
1183 assert!("ä".starts_with(""));
1184 assert!("#ä".starts_with(""));
1185 assert!("##ä".starts_with(""));
1186 assert!("ä###".starts_with(""));
1187 assert!("#ä##".starts_with(""));
1188 assert!("##ä#".starts_with(""));
1189 }
1190
1191 #[test]
1192 fn contains_weird_cases() {
1193 assert!("* \t".contains(' '));
1194 assert!(!"* \t".contains('?'));
1195 assert!(!"* \t".contains('\u{1F4A9}'));
1196 }
1197
1198 #[test]
1199 fn trim_ws() {
1200 assert_eq!(" \t a \t ".trim_left_matches(|c: char| c.is_whitespace()),
1201 "a \t ");
1202 assert_eq!(" \t a \t ".trim_right_matches(|c: char| c.is_whitespace()),
1203 " \t a");
1204 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
1205 "a");
1206 assert_eq!(" \t \t ".trim_left_matches(|c: char| c.is_whitespace()),
1207 "");
1208 assert_eq!(" \t \t ".trim_right_matches(|c: char| c.is_whitespace()),
1209 "");
1210 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
1211 "");
1212 }
1213
1214 #[test]
1215 fn to_lowercase() {
1216 assert_eq!("".to_lowercase(), "");
1217 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1218
1219 // https://github.com/rust-lang/rust/issues/26035
1220 assert_eq!("ΑΣ".to_lowercase(), "ας");
1221 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1222 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1223
1224 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1225 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1226 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1227
1228 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1229 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1230
1231 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1232 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1233
1234 assert_eq!("Α Σ".to_lowercase(), "α σ");
1235 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1236 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1237
1238 assert_eq!("Σ".to_lowercase(), "σ");
1239 assert_eq!("'Σ".to_lowercase(), "'σ");
1240 assert_eq!("''Σ".to_lowercase(), "''σ");
1241
1242 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1243 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1244 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1245 }
1246
1247 #[test]
1248 fn to_uppercase() {
1249 assert_eq!("".to_uppercase(), "");
1250 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1251 }
1252
1253 #[test]
1254 fn test_into_string() {
1255 // The only way to acquire a Box<str> in the first place is through a String, so just
1256 // test that we can round-trip between Box<str> and String.
1257 let string = String::from("Some text goes here");
1258 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1259 }
1260
1261 #[test]
1262 fn test_box_slice_clone() {
1263 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1264 let data2 = data.clone().into_boxed_str().clone().into_string();
1265
1266 assert_eq!(data, data2);
1267 }
1268
1269 mod pattern {
1270 use std::str::pattern::Pattern;
1271 use std::str::pattern::{Searcher, ReverseSearcher};
1272 use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1273
1274 macro_rules! make_test {
1275 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1276 #[allow(unused_imports)]
1277 mod $name {
1278 use std::str::pattern::SearchStep::{Match, Reject};
1279 use super::{cmp_search_to_vec};
1280 #[test]
1281 fn fwd() {
1282 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1283 }
1284 #[test]
1285 fn bwd() {
1286 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1287 }
1288 }
1289 }
1290 }
1291
1292 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1293 right: Vec<SearchStep>)
1294 where P::Searcher: ReverseSearcher<'a>
1295 {
1296 let mut searcher = pat.into_searcher(haystack);
1297 let mut v = vec![];
1298 loop {
1299 match if !rev {searcher.next()} else {searcher.next_back()} {
1300 Match(a, b) => v.push(Match(a, b)),
1301 Reject(a, b) => v.push(Reject(a, b)),
1302 Done => break,
1303 }
1304 }
1305 if rev {
1306 v.reverse();
1307 }
1308
1309 let mut first_index = 0;
1310 let mut err = None;
1311
1312 for (i, e) in right.iter().enumerate() {
1313 match *e {
1314 Match(a, b) | Reject(a, b)
1315 if a <= b && a == first_index => {
1316 first_index = b;
1317 }
1318 _ => {
1319 err = Some(i);
1320 break;
1321 }
1322 }
1323 }
1324
1325 if let Some(err) = err {
1326 panic!("Input skipped range at {}", err);
1327 }
1328
1329 if first_index != haystack.len() {
1330 panic!("Did not cover whole input");
1331 }
1332
1333 assert_eq!(v, right);
1334 }
1335
1336 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1337 Reject(0, 1),
1338 Match (1, 3),
1339 Reject(3, 4),
1340 Match (4, 6),
1341 Reject(6, 7),
1342 ]);
1343 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1344 Reject(0, 1),
1345 Match (1, 3),
1346 Reject(3, 4),
1347 Match (4, 6),
1348 Match (6, 8),
1349 Reject(8, 9),
1350 ]);
1351 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1352 Match (0, 0),
1353 Reject(0, 1),
1354 Match (1, 1),
1355 Reject(1, 2),
1356 Match (2, 2),
1357 Reject(2, 3),
1358 Match (3, 3),
1359 Reject(3, 4),
1360 Match (4, 4),
1361 Reject(4, 5),
1362 Match (5, 5),
1363 Reject(5, 6),
1364 Match (6, 6),
1365 Reject(6, 7),
1366 Match (7, 7),
1367 ]);
1368 make_test!(str_searcher_mulibyte_haystack, " ", "├──", [
1369 Reject(0, 3),
1370 Reject(3, 6),
1371 Reject(6, 9),
1372 ]);
1373 make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [
1374 Match (0, 0),
1375 Reject(0, 3),
1376 Match (3, 3),
1377 Reject(3, 6),
1378 Match (6, 6),
1379 Reject(6, 9),
1380 Match (9, 9),
1381 ]);
1382 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1383 Match(0, 0),
1384 ]);
1385 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1386 ]);
1387 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1388 Reject(0, 1),
1389 Match (1, 2),
1390 Match (2, 3),
1391 Reject(3, 4),
1392 Match (4, 5),
1393 Match (5, 6),
1394 Reject(6, 7),
1395 ]);
1396 make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [
1397 Reject(0, 3),
1398 Reject(3, 6),
1399 Reject(6, 9),
1400 ]);
1401 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1402 Reject(0, 1),
1403 Reject(1, 2),
1404 Reject(2, 3),
1405 ]);
1406
1407 }
1408
1409 macro_rules! generate_iterator_test {
1410 {
1411 $name:ident {
1412 $(
1413 ($($arg:expr),*) -> [$($t:tt)*];
1414 )*
1415 }
1416 with $fwd:expr, $bwd:expr;
1417 } => {
1418 #[test]
1419 fn $name() {
1420 $(
1421 {
1422 let res = vec![$($t)*];
1423
1424 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1425 assert_eq!(fwd_vec, res);
1426
1427 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1428 bwd_vec.reverse();
1429 assert_eq!(bwd_vec, res);
1430 }
1431 )*
1432 }
1433 };
1434 {
1435 $name:ident {
1436 $(
1437 ($($arg:expr),*) -> [$($t:tt)*];
1438 )*
1439 }
1440 with $fwd:expr;
1441 } => {
1442 #[test]
1443 fn $name() {
1444 $(
1445 {
1446 let res = vec![$($t)*];
1447
1448 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1449 assert_eq!(fwd_vec, res);
1450 }
1451 )*
1452 }
1453 }
1454 }
1455
1456 generate_iterator_test! {
1457 double_ended_split {
1458 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1459 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1460 }
1461 with str::split, str::rsplit;
1462 }
1463
1464 generate_iterator_test! {
1465 double_ended_split_terminator {
1466 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1467 }
1468 with str::split_terminator, str::rsplit_terminator;
1469 }
1470
1471 generate_iterator_test! {
1472 double_ended_matches {
1473 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1474 }
1475 with str::matches, str::rmatches;
1476 }
1477
1478 generate_iterator_test! {
1479 double_ended_match_indices {
1480 ("a1b2c3", char::is_numeric) -> [(1, 2), (3, 4), (5, 6)];
1481 }
1482 with str::match_indices, str::rmatch_indices;
1483 }
1484
1485 generate_iterator_test! {
1486 not_double_ended_splitn {
1487 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1488 }
1489 with str::splitn;
1490 }
1491
1492 generate_iterator_test! {
1493 not_double_ended_rsplitn {
1494 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1495 }
1496 with str::rsplitn;
1497 }
1498
1499 mod bench {
1500 use test::{Bencher, black_box};
1501
1502 #[bench]
1503 fn char_iterator(b: &mut Bencher) {
1504 let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1505
1506 b.iter(|| s.chars().count());
1507 }
1508
1509 #[bench]
1510 fn char_iterator_for(b: &mut Bencher) {
1511 let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1512
1513 b.iter(|| {
1514 for ch in s.chars() { black_box(ch); }
1515 });
1516 }
1517
1518 #[bench]
1519 fn char_iterator_ascii(b: &mut Bencher) {
1520 let s = "Mary had a little lamb, Little lamb
1521 Mary had a little lamb, Little lamb
1522 Mary had a little lamb, Little lamb
1523 Mary had a little lamb, Little lamb
1524 Mary had a little lamb, Little lamb
1525 Mary had a little lamb, Little lamb";
1526
1527 b.iter(|| s.chars().count());
1528 }
1529
1530 #[bench]
1531 fn char_iterator_rev(b: &mut Bencher) {
1532 let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1533
1534 b.iter(|| s.chars().rev().count());
1535 }
1536
1537 #[bench]
1538 fn char_iterator_rev_for(b: &mut Bencher) {
1539 let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1540
1541 b.iter(|| {
1542 for ch in s.chars().rev() { black_box(ch); }
1543 });
1544 }
1545
1546 #[bench]
1547 fn char_indicesator(b: &mut Bencher) {
1548 let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1549 let len = s.chars().count();
1550
1551 b.iter(|| assert_eq!(s.char_indices().count(), len));
1552 }
1553
1554 #[bench]
1555 fn char_indicesator_rev(b: &mut Bencher) {
1556 let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1557 let len = s.chars().count();
1558
1559 b.iter(|| assert_eq!(s.char_indices().rev().count(), len));
1560 }
1561
1562 #[bench]
1563 fn split_unicode_ascii(b: &mut Bencher) {
1564 let s = "ประเทศไทย中华Việt Namประเทศไทย中华Việt Nam";
1565
1566 b.iter(|| assert_eq!(s.split('V').count(), 3));
1567 }
1568
1569 #[bench]
1570 fn split_ascii(b: &mut Bencher) {
1571 let s = "Mary had a little lamb, Little lamb, little-lamb.";
1572 let len = s.split(' ').count();
1573
1574 b.iter(|| assert_eq!(s.split(' ').count(), len));
1575 }
1576
1577 #[bench]
1578 fn split_extern_fn(b: &mut Bencher) {
1579 let s = "Mary had a little lamb, Little lamb, little-lamb.";
1580 let len = s.split(' ').count();
1581 fn pred(c: char) -> bool { c == ' ' }
1582
1583 b.iter(|| assert_eq!(s.split(pred).count(), len));
1584 }
1585
1586 #[bench]
1587 fn split_closure(b: &mut Bencher) {
1588 let s = "Mary had a little lamb, Little lamb, little-lamb.";
1589 let len = s.split(' ').count();
1590
1591 b.iter(|| assert_eq!(s.split(|c: char| c == ' ').count(), len));
1592 }
1593
1594 #[bench]
1595 fn split_slice(b: &mut Bencher) {
1596 let s = "Mary had a little lamb, Little lamb, little-lamb.";
1597 let len = s.split(' ').count();
1598
1599 let c: &[char] = &[' '];
1600 b.iter(|| assert_eq!(s.split(c).count(), len));
1601 }
1602
1603 #[bench]
1604 fn bench_join(b: &mut Bencher) {
1605 let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
1606 let sep = "→";
1607 let v = vec![s, s, s, s, s, s, s, s, s, s];
1608 b.iter(|| {
1609 assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9);
1610 })
1611 }
1612
1613 #[bench]
1614 fn bench_contains_short_short(b: &mut Bencher) {
1615 let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
1616 let needle = "sit";
1617
1618 b.iter(|| {
1619 assert!(haystack.contains(needle));
1620 })
1621 }
1622
1623 #[bench]
1624 fn bench_contains_short_long(b: &mut Bencher) {
1625 let haystack = "\
1626 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
1627 ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
1628 eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
1629 sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
1630 tempus vel, gravida nec quam.
1631
1632 In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
1633 sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
1634 diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
1635 lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
1636 eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
1637 interdum. Curabitur ut nisi justo.
1638
1639 Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
1640 mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
1641 lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
1642 est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
1643 felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
1644 ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
1645 feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
1646 Aliquam sit amet placerat lorem.
1647
1648 Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
1649 mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
1650 Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
1651 lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
1652 suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
1653 cursus accumsan.
1654
1655 Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
1656 feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
1657 vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
1658 leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
1659 malesuada sollicitudin quam eu fermentum.";
1660 let needle = "english";
1661
1662 b.iter(|| {
1663 assert!(!haystack.contains(needle));
1664 })
1665 }
1666
1667 #[bench]
1668 fn bench_contains_bad_naive(b: &mut Bencher) {
1669 let haystack = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
1670 let needle = "aaaaaaaab";
1671
1672 b.iter(|| {
1673 assert!(!haystack.contains(needle));
1674 })
1675 }
1676
1677 #[bench]
1678 fn bench_contains_equal(b: &mut Bencher) {
1679 let haystack = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
1680 let needle = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
1681
1682 b.iter(|| {
1683 assert!(haystack.contains(needle));
1684 })
1685 }
1686
1687 macro_rules! make_test_inner {
1688 ($s:ident, $code:expr, $name:ident, $str:expr) => {
1689 #[bench]
1690 fn $name(bencher: &mut Bencher) {
1691 let mut $s = $str;
1692 black_box(&mut $s);
1693 bencher.iter(|| $code);
1694 }
1695 }
1696 }
1697
1698 macro_rules! make_test {
1699 ($name:ident, $s:ident, $code:expr) => {
1700 mod $name {
1701 use test::Bencher;
1702 use test::black_box;
1703
1704 // Short strings: 65 bytes each
1705 make_test_inner!($s, $code, short_ascii,
1706 "Mary had a little lamb, Little lamb Mary had a littl lamb, lamb!");
1707 make_test_inner!($s, $code, short_mixed,
1708 "ศไทย中华Việt Nam; Mary had a little lamb, Little lam!");
1709 make_test_inner!($s, $code, short_pile_of_poo,
1710 "💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩!");
1711 make_test_inner!($s, $code, long_lorem_ipsum,"\
1712 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
1713 ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
1714 eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
1715 sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
1716 tempus vel, gravida nec quam.
1717
1718 In est dui, tincidunt sed tempus interdum, adipiscing laoreet ante. Etiam tempor, tellus quis \
1719 sagittis interdum, nulla purus mattis sem, quis auctor erat odio ac tellus. In nec nunc sit amet \
1720 diam volutpat molestie at sed ipsum. Vestibulum laoreet consequat vulputate. Integer accumsan \
1721 lorem ac dignissim placerat. Suspendisse convallis faucibus lorem. Aliquam erat volutpat. In vel \
1722 eleifend felis. Sed suscipit nulla lorem, sed mollis est sollicitudin et. Nam fermentum egestas \
1723 interdum. Curabitur ut nisi justo.
1724
1725 Sed sollicitudin ipsum tellus, ut condimentum leo eleifend nec. Cras ut velit ante. Phasellus nec \
1726 mollis odio. Mauris molestie erat in arcu mattis, at aliquet dolor vehicula. Quisque malesuada \
1727 lectus sit amet nisi pretium, a condimentum ipsum porta. Morbi at dapibus diam. Praesent egestas \
1728 est sed risus elementum, eu rutrum metus ultrices. Etiam fermentum consectetur magna, id rutrum \
1729 felis accumsan a. Aliquam ut pellentesque libero. Sed mi nulla, lobortis eu tortor id, suscipit \
1730 ultricies neque. Morbi iaculis sit amet risus at iaculis. Praesent eget ligula quis turpis \
1731 feugiat suscipit vel non arcu. Interdum et malesuada fames ac ante ipsum primis in faucibus. \
1732 Aliquam sit amet placerat lorem.
1733
1734 Cras a lacus vel ante posuere elementum. Nunc est leo, bibendum ut facilisis vel, bibendum at \
1735 mauris. Nullam adipiscing diam vel odio ornare, luctus adipiscing mi luctus. Nulla facilisi. \
1736 Mauris adipiscing bibendum neque, quis adipiscing lectus tempus et. Sed feugiat erat et nisl \
1737 lobortis pharetra. Donec vitae erat enim. Nullam sit amet felis et quam lacinia tincidunt. Aliquam \
1738 suscipit dapibus urna. Sed volutpat urna in magna pulvinar volutpat. Phasellus nec tellus ac diam \
1739 cursus accumsan.
1740
1741 Nam lectus enim, dapibus non nisi tempor, consectetur convallis massa. Maecenas eleifend dictum \
1742 feugiat. Etiam quis mauris vel risus luctus mattis a a nunc. Nullam orci quam, imperdiet id \
1743 vehicula in, porttitor ut nibh. Duis sagittis adipiscing nisl vitae congue. Donec mollis risus eu \
1744 leo suscipit, varius porttitor nulla porta. Pellentesque ut sem nec nisi euismod vehicula. Nulla \
1745 malesuada sollicitudin quam eu fermentum!");
1746 }
1747 }
1748 }
1749
1750 make_test!(chars_count, s, s.chars().count());
1751
1752 make_test!(contains_bang_str, s, s.contains("!"));
1753 make_test!(contains_bang_char, s, s.contains('!'));
1754
1755 make_test!(match_indices_a_str, s, s.match_indices("a").count());
1756
1757 make_test!(split_a_str, s, s.split("a").count());
1758
1759 make_test!(trim_ascii_char, s, {
1760 use std::ascii::AsciiExt;
1761 s.trim_matches(|c: char| c.is_ascii())
1762 });
1763 make_test!(trim_left_ascii_char, s, {
1764 use std::ascii::AsciiExt;
1765 s.trim_left_matches(|c: char| c.is_ascii())
1766 });
1767 make_test!(trim_right_ascii_char, s, {
1768 use std::ascii::AsciiExt;
1769 s.trim_right_matches(|c: char| c.is_ascii())
1770 });
1771
1772 make_test!(find_underscore_char, s, s.find('_'));
1773 make_test!(rfind_underscore_char, s, s.rfind('_'));
1774 make_test!(find_underscore_str, s, s.find("_"));
1775
1776 make_test!(find_zzz_char, s, s.find('\u{1F4A4}'));
1777 make_test!(rfind_zzz_char, s, s.rfind('\u{1F4A4}'));
1778 make_test!(find_zzz_str, s, s.find("\u{1F4A4}"));
1779
1780 make_test!(split_space_char, s, s.split(' ').count());
1781 make_test!(split_terminator_space_char, s, s.split_terminator(' ').count());
1782
1783 make_test!(splitn_space_char, s, s.splitn(10, ' ').count());
1784 make_test!(rsplitn_space_char, s, s.rsplitn(10, ' ').count());
1785
1786 make_test!(split_space_str, s, s.split(" ").count());
1787 make_test!(split_ad_str, s, s.split("ad").count());
1788 }