]> git.proxmox.com Git - rustc.git/blob - src/liballoc/tests/str.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / liballoc / tests / 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::borrow::Cow;
12 use std::cmp::Ordering::{Equal, Greater, Less};
13 use std::str::from_utf8;
14
15 #[test]
16 fn test_le() {
17 assert!("" <= "");
18 assert!("" <= "foo");
19 assert!("foo" <= "foo");
20 assert!("foo" != "bar");
21 }
22
23 #[test]
24 fn test_find() {
25 assert_eq!("hello".find('l'), Some(2));
26 assert_eq!("hello".find(|c:char| c == 'o'), Some(4));
27 assert!("hello".find('x').is_none());
28 assert!("hello".find(|c:char| c == 'x').is_none());
29 assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30));
30 assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30));
31 }
32
33 #[test]
34 fn test_rfind() {
35 assert_eq!("hello".rfind('l'), Some(3));
36 assert_eq!("hello".rfind(|c:char| c == 'o'), Some(4));
37 assert!("hello".rfind('x').is_none());
38 assert!("hello".rfind(|c:char| c == 'x').is_none());
39 assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30));
40 assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30));
41 }
42
43 #[test]
44 fn test_collect() {
45 let empty = "";
46 let s: String = empty.chars().collect();
47 assert_eq!(empty, s);
48 let data = "ประเทศไทย中";
49 let s: String = data.chars().collect();
50 assert_eq!(data, s);
51 }
52
53 #[test]
54 fn test_into_bytes() {
55 let data = String::from("asdf");
56 let buf = data.into_bytes();
57 assert_eq!(buf, b"asdf");
58 }
59
60 #[test]
61 fn test_find_str() {
62 // byte positions
63 assert_eq!("".find(""), Some(0));
64 assert!("banana".find("apple pie").is_none());
65
66 let data = "abcabc";
67 assert_eq!(data[0..6].find("ab"), Some(0));
68 assert_eq!(data[2..6].find("ab"), Some(3 - 2));
69 assert!(data[2..4].find("ab").is_none());
70
71 let string = "ประเทศไทย中华Việt Nam";
72 let mut data = String::from(string);
73 data.push_str(string);
74 assert!(data.find("ไท华").is_none());
75 assert_eq!(data[0..43].find(""), Some(0));
76 assert_eq!(data[6..43].find(""), Some(6 - 6));
77
78 assert_eq!(data[0..43].find("ประ"), Some( 0));
79 assert_eq!(data[0..43].find("ทศไ"), Some(12));
80 assert_eq!(data[0..43].find("ย中"), Some(24));
81 assert_eq!(data[0..43].find("iệt"), Some(34));
82 assert_eq!(data[0..43].find("Nam"), Some(40));
83
84 assert_eq!(data[43..86].find("ประ"), Some(43 - 43));
85 assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43));
86 assert_eq!(data[43..86].find("ย中"), Some(67 - 43));
87 assert_eq!(data[43..86].find("iệt"), Some(77 - 43));
88 assert_eq!(data[43..86].find("Nam"), Some(83 - 43));
89
90 // find every substring -- assert that it finds it, or an earlier occurrence.
91 let string = "Việt Namacbaabcaabaaba";
92 for (i, ci) in string.char_indices() {
93 let ip = i + ci.len_utf8();
94 for j in string[ip..].char_indices()
95 .map(|(i, _)| i)
96 .chain(Some(string.len() - ip))
97 {
98 let pat = &string[i..ip + j];
99 assert!(match string.find(pat) {
100 None => false,
101 Some(x) => x <= i,
102 });
103 assert!(match string.rfind(pat) {
104 None => false,
105 Some(x) => x >= i,
106 });
107 }
108 }
109 }
110
111 fn s(x: &str) -> String { x.to_string() }
112
113 macro_rules! test_concat {
114 ($expected: expr, $string: expr) => {
115 {
116 let s: String = $string.concat();
117 assert_eq!($expected, s);
118 }
119 }
120 }
121
122 #[test]
123 fn test_concat_for_different_types() {
124 test_concat!("ab", vec![s("a"), s("b")]);
125 test_concat!("ab", vec!["a", "b"]);
126 }
127
128 #[test]
129 fn test_concat_for_different_lengths() {
130 let empty: &[&str] = &[];
131 test_concat!("", empty);
132 test_concat!("a", ["a"]);
133 test_concat!("ab", ["a", "b"]);
134 test_concat!("abc", ["", "a", "bc"]);
135 }
136
137 macro_rules! test_join {
138 ($expected: expr, $string: expr, $delim: expr) => {
139 {
140 let s = $string.join($delim);
141 assert_eq!($expected, s);
142 }
143 }
144 }
145
146 #[test]
147 fn test_join_for_different_types() {
148 test_join!("a-b", ["a", "b"], "-");
149 let hyphen = "-".to_string();
150 test_join!("a-b", [s("a"), s("b")], &*hyphen);
151 test_join!("a-b", vec!["a", "b"], &*hyphen);
152 test_join!("a-b", &*vec!["a", "b"], "-");
153 test_join!("a-b", vec![s("a"), s("b")], "-");
154 }
155
156 #[test]
157 fn test_join_for_different_lengths() {
158 let empty: &[&str] = &[];
159 test_join!("", empty, "-");
160 test_join!("a", ["a"], "-");
161 test_join!("a-b", ["a", "b"], "-");
162 test_join!("-a-bc", ["", "a", "bc"], "-");
163 }
164
165 #[test]
166 fn test_unsafe_slice() {
167 assert_eq!("ab", unsafe {"abc".slice_unchecked(0, 2)});
168 assert_eq!("bc", unsafe {"abc".slice_unchecked(1, 3)});
169 assert_eq!("", unsafe {"abc".slice_unchecked(1, 1)});
170 fn a_million_letter_a() -> String {
171 let mut i = 0;
172 let mut rs = String::new();
173 while i < 100000 {
174 rs.push_str("aaaaaaaaaa");
175 i += 1;
176 }
177 rs
178 }
179 fn half_a_million_letter_a() -> String {
180 let mut i = 0;
181 let mut rs = String::new();
182 while i < 100000 {
183 rs.push_str("aaaaa");
184 i += 1;
185 }
186 rs
187 }
188 let letters = a_million_letter_a();
189 assert_eq!(half_a_million_letter_a(),
190 unsafe { letters.slice_unchecked(0, 500000)});
191 }
192
193 #[test]
194 fn test_starts_with() {
195 assert!("".starts_with(""));
196 assert!("abc".starts_with(""));
197 assert!("abc".starts_with("a"));
198 assert!(!"a".starts_with("abc"));
199 assert!(!"".starts_with("abc"));
200 assert!(!"ödd".starts_with("-"));
201 assert!("ödd".starts_with("öd"));
202 }
203
204 #[test]
205 fn test_ends_with() {
206 assert!("".ends_with(""));
207 assert!("abc".ends_with(""));
208 assert!("abc".ends_with("c"));
209 assert!(!"a".ends_with("abc"));
210 assert!(!"".ends_with("abc"));
211 assert!(!"ddö".ends_with("-"));
212 assert!("ddö".ends_with("dö"));
213 }
214
215 #[test]
216 fn test_is_empty() {
217 assert!("".is_empty());
218 assert!(!"a".is_empty());
219 }
220
221 #[test]
222 fn test_replacen() {
223 assert_eq!("".replacen('a', "b", 5), "");
224 assert_eq!("acaaa".replacen("a", "b", 3), "bcbba");
225 assert_eq!("aaaa".replacen("a", "b", 0), "aaaa");
226
227 let test = "test";
228 assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast ");
229 assert_eq!(" test test ".replacen(test, "toast", 0), " test test ");
230 assert_eq!(" test test ".replacen(test, "", 5), " ");
231
232 assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789");
233 }
234
235 #[test]
236 fn test_replace() {
237 let a = "a";
238 assert_eq!("".replace(a, "b"), "");
239 assert_eq!("a".replace(a, "b"), "b");
240 assert_eq!("ab".replace(a, "b"), "bb");
241 let test = "test";
242 assert_eq!(" test test ".replace(test, "toast"), " toast toast ");
243 assert_eq!(" test test ".replace(test, ""), " ");
244 }
245
246 #[test]
247 fn test_replace_2a() {
248 let data = "ประเทศไทย中华";
249 let repl = "دولة الكويت";
250
251 let a = "ประเ";
252 let a2 = "دولة الكويتทศไทย中华";
253 assert_eq!(data.replace(a, repl), a2);
254 }
255
256 #[test]
257 fn test_replace_2b() {
258 let data = "ประเทศไทย中华";
259 let repl = "دولة الكويت";
260
261 let b = "ะเ";
262 let b2 = "ปรدولة الكويتทศไทย中华";
263 assert_eq!(data.replace(b, repl), b2);
264 }
265
266 #[test]
267 fn test_replace_2c() {
268 let data = "ประเทศไทย中华";
269 let repl = "دولة الكويت";
270
271 let c = "中华";
272 let c2 = "ประเทศไทยدولة الكويت";
273 assert_eq!(data.replace(c, repl), c2);
274 }
275
276 #[test]
277 fn test_replace_2d() {
278 let data = "ประเทศไทย中华";
279 let repl = "دولة الكويت";
280
281 let d = "ไท华";
282 assert_eq!(data.replace(d, repl), data);
283 }
284
285 #[test]
286 fn test_replace_pattern() {
287 let data = "abcdαβγδabcdαβγδ";
288 assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ");
289 assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
290 assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ");
291 assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ");
292 }
293
294 #[test]
295 fn test_slice() {
296 assert_eq!("ab", &"abc"[0..2]);
297 assert_eq!("bc", &"abc"[1..3]);
298 assert_eq!("", &"abc"[1..1]);
299 assert_eq!("\u{65e5}", &"\u{65e5}\u{672c}"[0..3]);
300
301 let data = "ประเทศไทย中华";
302 assert_eq!("ป", &data[0..3]);
303 assert_eq!("ร", &data[3..6]);
304 assert_eq!("", &data[3..3]);
305 assert_eq!("华", &data[30..33]);
306
307 fn a_million_letter_x() -> String {
308 let mut i = 0;
309 let mut rs = String::new();
310 while i < 100000 {
311 rs.push_str("华华华华华华华华华华");
312 i += 1;
313 }
314 rs
315 }
316 fn half_a_million_letter_x() -> String {
317 let mut i = 0;
318 let mut rs = String::new();
319 while i < 100000 {
320 rs.push_str("华华华华华");
321 i += 1;
322 }
323 rs
324 }
325 let letters = a_million_letter_x();
326 assert_eq!(half_a_million_letter_x(), &letters[0..3 * 500000]);
327 }
328
329 #[test]
330 fn test_slice_2() {
331 let ss = "中华Việt Nam";
332
333 assert_eq!("华", &ss[3..6]);
334 assert_eq!("Việt Nam", &ss[6..16]);
335
336 assert_eq!("ab", &"abc"[0..2]);
337 assert_eq!("bc", &"abc"[1..3]);
338 assert_eq!("", &"abc"[1..1]);
339
340 assert_eq!("中", &ss[0..3]);
341 assert_eq!("华V", &ss[3..7]);
342 assert_eq!("", &ss[3..3]);
343 /*0: 中
344 3: 华
345 6: V
346 7: i
347 8: ệ
348 11: t
349 12:
350 13: N
351 14: a
352 15: m */
353 }
354
355 #[test]
356 #[should_panic]
357 fn test_slice_fail() {
358 &"中华Việt Nam"[0..2];
359 }
360
361 #[test]
362 #[should_panic]
363 fn test_str_slice_rangetoinclusive_max_panics() {
364 &"hello"[..=usize::max_value()];
365 }
366
367 #[test]
368 #[should_panic]
369 fn test_str_slice_rangeinclusive_max_panics() {
370 &"hello"[1..=usize::max_value()];
371 }
372
373 #[test]
374 #[should_panic]
375 fn test_str_slicemut_rangetoinclusive_max_panics() {
376 let mut s = "hello".to_owned();
377 let s: &mut str = &mut s;
378 &mut s[..=usize::max_value()];
379 }
380
381 #[test]
382 #[should_panic]
383 fn test_str_slicemut_rangeinclusive_max_panics() {
384 let mut s = "hello".to_owned();
385 let s: &mut str = &mut s;
386 &mut s[1..=usize::max_value()];
387 }
388
389 #[test]
390 fn test_str_get_maxinclusive() {
391 let mut s = "hello".to_owned();
392 {
393 let s: &str = &s;
394 assert_eq!(s.get(..=usize::max_value()), None);
395 assert_eq!(s.get(1..=usize::max_value()), None);
396 }
397 {
398 let s: &mut str = &mut s;
399 assert_eq!(s.get(..=usize::max_value()), None);
400 assert_eq!(s.get(1..=usize::max_value()), None);
401 }
402 }
403
404 #[test]
405 fn test_is_char_boundary() {
406 let s = "ศไทย中华Việt Nam β-release 🐱123";
407 assert!(s.is_char_boundary(0));
408 assert!(s.is_char_boundary(s.len()));
409 assert!(!s.is_char_boundary(s.len() + 1));
410 for (i, ch) in s.char_indices() {
411 // ensure character locations are boundaries and continuation bytes are not
412 assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s);
413 for j in 1..ch.len_utf8() {
414 assert!(!s.is_char_boundary(i + j),
415 "{} should not be a char boundary in {:?}", i + j, s);
416 }
417 }
418 }
419 const LOREM_PARAGRAPH: &'static str = "\
420 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem sit amet dolor \
421 ultricies condimentum. Praesent iaculis purus elit, ac malesuada quam malesuada in. Duis sed orci \
422 eros. Suspendisse sit amet magna mollis, mollis nunc luctus, imperdiet mi. Integer fringilla non \
423 sem ut lacinia. Fusce varius tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec \
424 tempus vel, gravida nec quam.";
425
426 // check the panic includes the prefix of the sliced string
427 #[test]
428 #[should_panic(expected="byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")]
429 fn test_slice_fail_truncated_1() {
430 &LOREM_PARAGRAPH[..1024];
431 }
432 // check the truncation in the panic message
433 #[test]
434 #[should_panic(expected="luctus, im`[...]")]
435 fn test_slice_fail_truncated_2() {
436 &LOREM_PARAGRAPH[..1024];
437 }
438
439 #[test]
440 #[should_panic(expected="byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of")]
441 fn test_slice_fail_boundary_1() {
442 &"abcαβγ"[4..];
443 }
444
445 #[test]
446 #[should_panic(expected="byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of")]
447 fn test_slice_fail_boundary_2() {
448 &"abcαβγ"[2..6];
449 }
450
451 #[test]
452 fn test_slice_from() {
453 assert_eq!(&"abcd"[0..], "abcd");
454 assert_eq!(&"abcd"[2..], "cd");
455 assert_eq!(&"abcd"[4..], "");
456 }
457 #[test]
458 fn test_slice_to() {
459 assert_eq!(&"abcd"[..0], "");
460 assert_eq!(&"abcd"[..2], "ab");
461 assert_eq!(&"abcd"[..4], "abcd");
462 }
463
464 #[test]
465 fn test_trim_left_matches() {
466 let v: &[char] = &[];
467 assert_eq!(" *** foo *** ".trim_left_matches(v), " *** foo *** ");
468 let chars: &[char] = &['*', ' '];
469 assert_eq!(" *** foo *** ".trim_left_matches(chars), "foo *** ");
470 assert_eq!(" *** *** ".trim_left_matches(chars), "");
471 assert_eq!("foo *** ".trim_left_matches(chars), "foo *** ");
472
473 assert_eq!("11foo1bar11".trim_left_matches('1'), "foo1bar11");
474 let chars: &[char] = &['1', '2'];
475 assert_eq!("12foo1bar12".trim_left_matches(chars), "foo1bar12");
476 assert_eq!("123foo1bar123".trim_left_matches(|c: char| c.is_numeric()), "foo1bar123");
477 }
478
479 #[test]
480 fn test_trim_right_matches() {
481 let v: &[char] = &[];
482 assert_eq!(" *** foo *** ".trim_right_matches(v), " *** foo *** ");
483 let chars: &[char] = &['*', ' '];
484 assert_eq!(" *** foo *** ".trim_right_matches(chars), " *** foo");
485 assert_eq!(" *** *** ".trim_right_matches(chars), "");
486 assert_eq!(" *** foo".trim_right_matches(chars), " *** foo");
487
488 assert_eq!("11foo1bar11".trim_right_matches('1'), "11foo1bar");
489 let chars: &[char] = &['1', '2'];
490 assert_eq!("12foo1bar12".trim_right_matches(chars), "12foo1bar");
491 assert_eq!("123foo1bar123".trim_right_matches(|c: char| c.is_numeric()), "123foo1bar");
492 }
493
494 #[test]
495 fn test_trim_matches() {
496 let v: &[char] = &[];
497 assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** ");
498 let chars: &[char] = &['*', ' '];
499 assert_eq!(" *** foo *** ".trim_matches(chars), "foo");
500 assert_eq!(" *** *** ".trim_matches(chars), "");
501 assert_eq!("foo".trim_matches(chars), "foo");
502
503 assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar");
504 let chars: &[char] = &['1', '2'];
505 assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar");
506 assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar");
507 }
508
509 #[test]
510 fn test_trim_left() {
511 assert_eq!("".trim_left(), "");
512 assert_eq!("a".trim_left(), "a");
513 assert_eq!(" ".trim_left(), "");
514 assert_eq!(" blah".trim_left(), "blah");
515 assert_eq!(" \u{3000} wut".trim_left(), "wut");
516 assert_eq!("hey ".trim_left(), "hey ");
517 }
518
519 #[test]
520 fn test_trim_right() {
521 assert_eq!("".trim_right(), "");
522 assert_eq!("a".trim_right(), "a");
523 assert_eq!(" ".trim_right(), "");
524 assert_eq!("blah ".trim_right(), "blah");
525 assert_eq!("wut \u{3000} ".trim_right(), "wut");
526 assert_eq!(" hey".trim_right(), " hey");
527 }
528
529 #[test]
530 fn test_trim() {
531 assert_eq!("".trim(), "");
532 assert_eq!("a".trim(), "a");
533 assert_eq!(" ".trim(), "");
534 assert_eq!(" blah ".trim(), "blah");
535 assert_eq!("\nwut \u{3000} ".trim(), "wut");
536 assert_eq!(" hey dude ".trim(), "hey dude");
537 }
538
539 #[test]
540 fn test_is_whitespace() {
541 assert!("".chars().all(|c| c.is_whitespace()));
542 assert!(" ".chars().all(|c| c.is_whitespace()));
543 assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space
544 assert!(" \n\t ".chars().all(|c| c.is_whitespace()));
545 assert!(!" _ ".chars().all(|c| c.is_whitespace()));
546 }
547
548 #[test]
549 fn test_is_utf8() {
550 // deny overlong encodings
551 assert!(from_utf8(&[0xc0, 0x80]).is_err());
552 assert!(from_utf8(&[0xc0, 0xae]).is_err());
553 assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err());
554 assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err());
555 assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err());
556 assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err());
557 assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err());
558
559 // deny surrogates
560 assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err());
561 assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err());
562
563 assert!(from_utf8(&[0xC2, 0x80]).is_ok());
564 assert!(from_utf8(&[0xDF, 0xBF]).is_ok());
565 assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok());
566 assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok());
567 assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok());
568 assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok());
569 assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok());
570 assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok());
571 }
572
573 #[test]
574 fn from_utf8_mostly_ascii() {
575 // deny invalid bytes embedded in long stretches of ascii
576 for i in 32..64 {
577 let mut data = [0; 128];
578 data[i] = 0xC0;
579 assert!(from_utf8(&data).is_err());
580 data[i] = 0xC2;
581 assert!(from_utf8(&data).is_err());
582 }
583 }
584
585 #[test]
586 fn from_utf8_error() {
587 macro_rules! test {
588 ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => {
589 let error = from_utf8($input).unwrap_err();
590 assert_eq!(error.valid_up_to(), $expected_valid_up_to);
591 assert_eq!(error.error_len(), $expected_error_len);
592 }
593 }
594 test!(b"A\xC3\xA9 \xFF ", 4, Some(1));
595 test!(b"A\xC3\xA9 \x80 ", 4, Some(1));
596 test!(b"A\xC3\xA9 \xC1 ", 4, Some(1));
597 test!(b"A\xC3\xA9 \xC1", 4, Some(1));
598 test!(b"A\xC3\xA9 \xC2", 4, None);
599 test!(b"A\xC3\xA9 \xC2 ", 4, Some(1));
600 test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1));
601 test!(b"A\xC3\xA9 \xE0", 4, None);
602 test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1));
603 test!(b"A\xC3\xA9 \xE0\xA0", 4, None);
604 test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2));
605 test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2));
606 test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1));
607 test!(b"A\xC3\xA9 \xF1", 4, None);
608 test!(b"A\xC3\xA9 \xF1\x80", 4, None);
609 test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None);
610 test!(b"A\xC3\xA9 \xF1 ", 4, Some(1));
611 test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2));
612 test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3));
613 }
614
615 #[test]
616 fn test_as_bytes() {
617 // no null
618 let v = [
619 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
620 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
621 109
622 ];
623 let b: &[u8] = &[];
624 assert_eq!("".as_bytes(), b);
625 assert_eq!("abc".as_bytes(), b"abc");
626 assert_eq!("ศไทย中华Việt Nam".as_bytes(), v);
627 }
628
629 #[test]
630 #[should_panic]
631 fn test_as_bytes_fail() {
632 // Don't double free. (I'm not sure if this exercises the
633 // original problem code path anymore.)
634 let s = String::from("");
635 let _bytes = s.as_bytes();
636 panic!();
637 }
638
639 #[test]
640 fn test_as_ptr() {
641 let buf = "hello".as_ptr();
642 unsafe {
643 assert_eq!(*buf.offset(0), b'h');
644 assert_eq!(*buf.offset(1), b'e');
645 assert_eq!(*buf.offset(2), b'l');
646 assert_eq!(*buf.offset(3), b'l');
647 assert_eq!(*buf.offset(4), b'o');
648 }
649 }
650
651 #[test]
652 fn vec_str_conversions() {
653 let s1: String = String::from("All mimsy were the borogoves");
654
655 let v: Vec<u8> = s1.as_bytes().to_vec();
656 let s2: String = String::from(from_utf8(&v).unwrap());
657 let mut i = 0;
658 let n1 = s1.len();
659 let n2 = v.len();
660 assert_eq!(n1, n2);
661 while i < n1 {
662 let a: u8 = s1.as_bytes()[i];
663 let b: u8 = s2.as_bytes()[i];
664 assert_eq!(a, b);
665 i += 1;
666 }
667 }
668
669 #[test]
670 fn test_contains() {
671 assert!("abcde".contains("bcd"));
672 assert!("abcde".contains("abcd"));
673 assert!("abcde".contains("bcde"));
674 assert!("abcde".contains(""));
675 assert!("".contains(""));
676 assert!(!"abcde".contains("def"));
677 assert!(!"".contains("a"));
678
679 let data = "ประเทศไทย中华Việt Nam";
680 assert!(data.contains("ประเ"));
681 assert!(data.contains("ะเ"));
682 assert!(data.contains("中华"));
683 assert!(!data.contains("ไท华"));
684 }
685
686 #[test]
687 fn test_contains_char() {
688 assert!("abc".contains('b'));
689 assert!("a".contains('a'));
690 assert!(!"abc".contains('d'));
691 assert!(!"".contains('a'));
692 }
693
694 #[test]
695 fn test_split_at() {
696 let s = "ศไทย中华Việt Nam";
697 for (index, _) in s.char_indices() {
698 let (a, b) = s.split_at(index);
699 assert_eq!(&s[..a.len()], a);
700 assert_eq!(&s[a.len()..], b);
701 }
702 let (a, b) = s.split_at(s.len());
703 assert_eq!(a, s);
704 assert_eq!(b, "");
705 }
706
707 #[test]
708 fn test_split_at_mut() {
709 let mut s = "Hello World".to_string();
710 {
711 let (a, b) = s.split_at_mut(5);
712 a.make_ascii_uppercase();
713 b.make_ascii_lowercase();
714 }
715 assert_eq!(s, "HELLO world");
716 }
717
718 #[test]
719 #[should_panic]
720 fn test_split_at_boundscheck() {
721 let s = "ศไทย中华Việt Nam";
722 s.split_at(1);
723 }
724
725 #[test]
726 fn test_escape_unicode() {
727 assert_eq!("abc".escape_unicode(), "\\u{61}\\u{62}\\u{63}");
728 assert_eq!("a c".escape_unicode(), "\\u{61}\\u{20}\\u{63}");
729 assert_eq!("\r\n\t".escape_unicode(), "\\u{d}\\u{a}\\u{9}");
730 assert_eq!("'\"\\".escape_unicode(), "\\u{27}\\u{22}\\u{5c}");
731 assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(), "\\u{0}\\u{1}\\u{fe}\\u{ff}");
732 assert_eq!("\u{100}\u{ffff}".escape_unicode(), "\\u{100}\\u{ffff}");
733 assert_eq!("\u{10000}\u{10ffff}".escape_unicode(), "\\u{10000}\\u{10ffff}");
734 assert_eq!("ab\u{fb00}".escape_unicode(), "\\u{61}\\u{62}\\u{fb00}");
735 assert_eq!("\u{1d4ea}\r".escape_unicode(), "\\u{1d4ea}\\u{d}");
736 }
737
738 #[test]
739 fn test_escape_debug() {
740 assert_eq!("abc".escape_debug(), "abc");
741 assert_eq!("a c".escape_debug(), "a c");
742 assert_eq!("éèê".escape_debug(), "éèê");
743 assert_eq!("\r\n\t".escape_debug(), "\\r\\n\\t");
744 assert_eq!("'\"\\".escape_debug(), "\\'\\\"\\\\");
745 assert_eq!("\u{7f}\u{ff}".escape_debug(), "\\u{7f}\u{ff}");
746 assert_eq!("\u{100}\u{ffff}".escape_debug(), "\u{100}\\u{ffff}");
747 assert_eq!("\u{10000}\u{10ffff}".escape_debug(), "\u{10000}\\u{10ffff}");
748 assert_eq!("ab\u{200b}".escape_debug(), "ab\\u{200b}");
749 assert_eq!("\u{10d4ea}\r".escape_debug(), "\\u{10d4ea}\\r");
750 }
751
752 #[test]
753 fn test_escape_default() {
754 assert_eq!("abc".escape_default(), "abc");
755 assert_eq!("a c".escape_default(), "a c");
756 assert_eq!("éèê".escape_default(), "\\u{e9}\\u{e8}\\u{ea}");
757 assert_eq!("\r\n\t".escape_default(), "\\r\\n\\t");
758 assert_eq!("'\"\\".escape_default(), "\\'\\\"\\\\");
759 assert_eq!("\u{7f}\u{ff}".escape_default(), "\\u{7f}\\u{ff}");
760 assert_eq!("\u{100}\u{ffff}".escape_default(), "\\u{100}\\u{ffff}");
761 assert_eq!("\u{10000}\u{10ffff}".escape_default(), "\\u{10000}\\u{10ffff}");
762 assert_eq!("ab\u{200b}".escape_default(), "ab\\u{200b}");
763 assert_eq!("\u{10d4ea}\r".escape_default(), "\\u{10d4ea}\\r");
764 }
765
766 #[test]
767 fn test_total_ord() {
768 assert_eq!("1234".cmp("123"), Greater);
769 assert_eq!("123".cmp("1234"), Less);
770 assert_eq!("1234".cmp("1234"), Equal);
771 assert_eq!("12345555".cmp("123456"), Less);
772 assert_eq!("22".cmp("1234"), Greater);
773 }
774
775 #[test]
776 fn test_iterator() {
777 let s = "ศไทย中华Việt Nam";
778 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
779
780 let mut pos = 0;
781 let it = s.chars();
782
783 for c in it {
784 assert_eq!(c, v[pos]);
785 pos += 1;
786 }
787 assert_eq!(pos, v.len());
788 assert_eq!(s.chars().count(), v.len());
789 }
790
791 #[test]
792 fn test_rev_iterator() {
793 let s = "ศไทย中华Việt Nam";
794 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
795
796 let mut pos = 0;
797 let it = s.chars().rev();
798
799 for c in it {
800 assert_eq!(c, v[pos]);
801 pos += 1;
802 }
803 assert_eq!(pos, v.len());
804 }
805
806 #[test]
807 fn test_chars_decoding() {
808 let mut bytes = [0; 4];
809 for c in (0..0x110000).filter_map(::std::char::from_u32) {
810 let s = c.encode_utf8(&mut bytes);
811 if Some(c) != s.chars().next() {
812 panic!("character {:x}={} does not decode correctly", c as u32, c);
813 }
814 }
815 }
816
817 #[test]
818 fn test_chars_rev_decoding() {
819 let mut bytes = [0; 4];
820 for c in (0..0x110000).filter_map(::std::char::from_u32) {
821 let s = c.encode_utf8(&mut bytes);
822 if Some(c) != s.chars().rev().next() {
823 panic!("character {:x}={} does not decode correctly", c as u32, c);
824 }
825 }
826 }
827
828 #[test]
829 fn test_iterator_clone() {
830 let s = "ศไทย中华Việt Nam";
831 let mut it = s.chars();
832 it.next();
833 assert!(it.clone().zip(it).all(|(x,y)| x == y));
834 }
835
836 #[test]
837 fn test_iterator_last() {
838 let s = "ศไทย中华Việt Nam";
839 let mut it = s.chars();
840 it.next();
841 assert_eq!(it.last(), Some('m'));
842 }
843
844 #[test]
845 fn test_bytesator() {
846 let s = "ศไทย中华Việt Nam";
847 let v = [
848 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
849 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
850 109
851 ];
852 let mut pos = 0;
853
854 for b in s.bytes() {
855 assert_eq!(b, v[pos]);
856 pos += 1;
857 }
858 }
859
860 #[test]
861 fn test_bytes_revator() {
862 let s = "ศไทย中华Việt Nam";
863 let v = [
864 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
865 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
866 109
867 ];
868 let mut pos = v.len();
869
870 for b in s.bytes().rev() {
871 pos -= 1;
872 assert_eq!(b, v[pos]);
873 }
874 }
875
876 #[test]
877 fn test_bytesator_nth() {
878 let s = "ศไทย中华Việt Nam";
879 let v = [
880 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
881 184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
882 109
883 ];
884
885 let mut b = s.bytes();
886 assert_eq!(b.nth(2).unwrap(), v[2]);
887 assert_eq!(b.nth(10).unwrap(), v[10]);
888 assert_eq!(b.nth(200), None);
889 }
890
891 #[test]
892 fn test_bytesator_count() {
893 let s = "ศไทย中华Việt Nam";
894
895 let b = s.bytes();
896 assert_eq!(b.count(), 28)
897 }
898
899 #[test]
900 fn test_bytesator_last() {
901 let s = "ศไทย中华Việt Nam";
902
903 let b = s.bytes();
904 assert_eq!(b.last().unwrap(), 109)
905 }
906
907 #[test]
908 fn test_char_indicesator() {
909 let s = "ศไทย中华Việt Nam";
910 let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27];
911 let v = ['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
912
913 let mut pos = 0;
914 let it = s.char_indices();
915
916 for c in it {
917 assert_eq!(c, (p[pos], v[pos]));
918 pos += 1;
919 }
920 assert_eq!(pos, v.len());
921 assert_eq!(pos, p.len());
922 }
923
924 #[test]
925 fn test_char_indices_revator() {
926 let s = "ศไทย中华Việt Nam";
927 let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0];
928 let v = ['m', 'a', 'N', ' ', 't', 'ệ','i','V','华','中','ย','ท','ไ','ศ'];
929
930 let mut pos = 0;
931 let it = s.char_indices().rev();
932
933 for c in it {
934 assert_eq!(c, (p[pos], v[pos]));
935 pos += 1;
936 }
937 assert_eq!(pos, v.len());
938 assert_eq!(pos, p.len());
939 }
940
941 #[test]
942 fn test_char_indices_last() {
943 let s = "ศไทย中华Việt Nam";
944 let mut it = s.char_indices();
945 it.next();
946 assert_eq!(it.last(), Some((27, 'm')));
947 }
948
949 #[test]
950 fn test_splitn_char_iterator() {
951 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
952
953 let split: Vec<&str> = data.splitn(4, ' ').collect();
954 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
955
956 let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
957 assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
958
959 // Unicode
960 let split: Vec<&str> = data.splitn(4, 'ä').collect();
961 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
962
963 let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
964 assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
965 }
966
967 #[test]
968 fn test_split_char_iterator_no_trailing() {
969 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
970
971 let split: Vec<&str> = data.split('\n').collect();
972 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
973
974 let split: Vec<&str> = data.split_terminator('\n').collect();
975 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
976 }
977
978 #[test]
979 fn test_rsplit() {
980 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
981
982 let split: Vec<&str> = data.rsplit(' ').collect();
983 assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]);
984
985 let split: Vec<&str> = data.rsplit("lämb").collect();
986 assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]);
987
988 let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect();
989 assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]);
990 }
991
992 #[test]
993 fn test_rsplitn() {
994 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
995
996 let split: Vec<&str> = data.rsplitn(2, ' ').collect();
997 assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
998
999 let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
1000 assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
1001
1002 let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
1003 assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
1004 }
1005
1006 #[test]
1007 fn test_split_whitespace() {
1008 let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n";
1009 let words: Vec<&str> = data.split_whitespace().collect();
1010 assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
1011 }
1012
1013 #[test]
1014 fn test_lines() {
1015 let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n";
1016 let lines: Vec<&str> = data.lines().collect();
1017 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1018
1019 let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
1020 let lines: Vec<&str> = data.lines().collect();
1021 assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
1022 }
1023
1024 #[test]
1025 fn test_splitator() {
1026 fn t(s: &str, sep: &str, u: &[&str]) {
1027 let v: Vec<&str> = s.split(sep).collect();
1028 assert_eq!(v, u);
1029 }
1030 t("--1233345--", "12345", &["--1233345--"]);
1031 t("abc::hello::there", "::", &["abc", "hello", "there"]);
1032 t("::hello::there", "::", &["", "hello", "there"]);
1033 t("hello::there::", "::", &["hello", "there", ""]);
1034 t("::hello::there::", "::", &["", "hello", "there", ""]);
1035 t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]);
1036 t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]);
1037 t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]);
1038 t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]);
1039 t("", ".", &[""]);
1040 t("zz", "zz", &["",""]);
1041 t("ok", "z", &["ok"]);
1042 t("zzz", "zz", &["","z"]);
1043 t("zzzzz", "zz", &["","","z"]);
1044 }
1045
1046 #[test]
1047 fn test_str_default() {
1048 use std::default::Default;
1049
1050 fn t<S: Default + AsRef<str>>() {
1051 let s: S = Default::default();
1052 assert_eq!(s.as_ref(), "");
1053 }
1054
1055 t::<&str>();
1056 t::<String>();
1057 }
1058
1059 #[test]
1060 fn test_str_container() {
1061 fn sum_len(v: &[&str]) -> usize {
1062 v.iter().map(|x| x.len()).sum()
1063 }
1064
1065 let s = "01234";
1066 assert_eq!(5, sum_len(&["012", "", "34"]));
1067 assert_eq!(5, sum_len(&["01", "2", "34", ""]));
1068 assert_eq!(5, sum_len(&[s]));
1069 }
1070
1071 #[test]
1072 fn test_str_from_utf8() {
1073 let xs = b"hello";
1074 assert_eq!(from_utf8(xs), Ok("hello"));
1075
1076 let xs = "ศไทย中华Việt Nam".as_bytes();
1077 assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam"));
1078
1079 let xs = b"hello\xFF";
1080 assert!(from_utf8(xs).is_err());
1081 }
1082
1083 #[test]
1084 fn test_pattern_deref_forward() {
1085 let data = "aabcdaa";
1086 assert!(data.contains("bcd"));
1087 assert!(data.contains(&"bcd"));
1088 assert!(data.contains(&"bcd".to_string()));
1089 }
1090
1091 #[test]
1092 fn test_empty_match_indices() {
1093 let data = "aä中!";
1094 let vec: Vec<_> = data.match_indices("").collect();
1095 assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]);
1096 }
1097
1098 #[test]
1099 fn test_bool_from_str() {
1100 assert_eq!("true".parse().ok(), Some(true));
1101 assert_eq!("false".parse().ok(), Some(false));
1102 assert_eq!("not even a boolean".parse::<bool>().ok(), None);
1103 }
1104
1105 fn check_contains_all_substrings(s: &str) {
1106 assert!(s.contains(""));
1107 for i in 0..s.len() {
1108 for j in i+1..s.len() + 1 {
1109 assert!(s.contains(&s[i..j]));
1110 }
1111 }
1112 }
1113
1114 #[test]
1115 fn strslice_issue_16589() {
1116 assert!("bananas".contains("nana"));
1117
1118 // prior to the fix for #16589, x.contains("abcdabcd") returned false
1119 // test all substrings for good measure
1120 check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd");
1121 }
1122
1123 #[test]
1124 fn strslice_issue_16878() {
1125 assert!(!"1234567ah012345678901ah".contains("hah"));
1126 assert!(!"00abc01234567890123456789abc".contains("bcabc"));
1127 }
1128
1129
1130 #[test]
1131 fn test_strslice_contains() {
1132 let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'";
1133 check_contains_all_substrings(x);
1134 }
1135
1136 #[test]
1137 fn test_rsplitn_char_iterator() {
1138 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1139
1140 let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
1141 split.reverse();
1142 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1143
1144 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
1145 split.reverse();
1146 assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
1147
1148 // Unicode
1149 let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
1150 split.reverse();
1151 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1152
1153 let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
1154 split.reverse();
1155 assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
1156 }
1157
1158 #[test]
1159 fn test_split_char_iterator() {
1160 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1161
1162 let split: Vec<&str> = data.split(' ').collect();
1163 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1164
1165 let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
1166 rsplit.reverse();
1167 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1168
1169 let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
1170 assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1171
1172 let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
1173 rsplit.reverse();
1174 assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
1175
1176 // Unicode
1177 let split: Vec<&str> = data.split('ä').collect();
1178 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1179
1180 let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
1181 rsplit.reverse();
1182 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1183
1184 let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
1185 assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1186
1187 let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
1188 rsplit.reverse();
1189 assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
1190 }
1191
1192 #[test]
1193 fn test_rev_split_char_iterator_no_trailing() {
1194 let data = "\nMäry häd ä little lämb\nLittle lämb\n";
1195
1196 let mut split: Vec<&str> = data.split('\n').rev().collect();
1197 split.reverse();
1198 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
1199
1200 let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
1201 split.reverse();
1202 assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
1203 }
1204
1205 #[test]
1206 fn test_utf16_code_units() {
1207 use std_unicode::str::Utf16Encoder;
1208 assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
1209 [0xE9, 0xD83D, 0xDCA9])
1210 }
1211
1212 #[test]
1213 fn starts_with_in_unicode() {
1214 assert!(!"├── Cargo.toml".starts_with("# "));
1215 }
1216
1217 #[test]
1218 fn starts_short_long() {
1219 assert!(!"".starts_with("##"));
1220 assert!(!"##".starts_with("####"));
1221 assert!("####".starts_with("##"));
1222 assert!(!"##ä".starts_with("####"));
1223 assert!("####ä".starts_with("##"));
1224 assert!(!"##".starts_with("####ä"));
1225 assert!("##ä##".starts_with("##ä"));
1226
1227 assert!("".starts_with(""));
1228 assert!("ä".starts_with(""));
1229 assert!("#ä".starts_with(""));
1230 assert!("##ä".starts_with(""));
1231 assert!("ä###".starts_with(""));
1232 assert!("#ä##".starts_with(""));
1233 assert!("##ä#".starts_with(""));
1234 }
1235
1236 #[test]
1237 fn contains_weird_cases() {
1238 assert!("* \t".contains(' '));
1239 assert!(!"* \t".contains('?'));
1240 assert!(!"* \t".contains('\u{1F4A9}'));
1241 }
1242
1243 #[test]
1244 fn trim_ws() {
1245 assert_eq!(" \t a \t ".trim_left_matches(|c: char| c.is_whitespace()),
1246 "a \t ");
1247 assert_eq!(" \t a \t ".trim_right_matches(|c: char| c.is_whitespace()),
1248 " \t a");
1249 assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()),
1250 "a");
1251 assert_eq!(" \t \t ".trim_left_matches(|c: char| c.is_whitespace()),
1252 "");
1253 assert_eq!(" \t \t ".trim_right_matches(|c: char| c.is_whitespace()),
1254 "");
1255 assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()),
1256 "");
1257 }
1258
1259 #[test]
1260 fn to_lowercase() {
1261 assert_eq!("".to_lowercase(), "");
1262 assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé ");
1263
1264 // https://github.com/rust-lang/rust/issues/26035
1265 assert_eq!("ΑΣ".to_lowercase(), "ας");
1266 assert_eq!("Α'Σ".to_lowercase(), "α'ς");
1267 assert_eq!("Α''Σ".to_lowercase(), "α''ς");
1268
1269 assert_eq!("ΑΣ Α".to_lowercase(), "ας α");
1270 assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α");
1271 assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α");
1272
1273 assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α");
1274 assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α");
1275
1276 assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α");
1277 assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α");
1278
1279 assert_eq!("Α Σ".to_lowercase(), "α σ");
1280 assert_eq!("Α 'Σ".to_lowercase(), "α 'σ");
1281 assert_eq!("Α ''Σ".to_lowercase(), "α ''σ");
1282
1283 assert_eq!("Σ".to_lowercase(), "σ");
1284 assert_eq!("'Σ".to_lowercase(), "'σ");
1285 assert_eq!("''Σ".to_lowercase(), "''σ");
1286
1287 assert_eq!("ΑΣΑ".to_lowercase(), "ασα");
1288 assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α");
1289 assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α");
1290 }
1291
1292 #[test]
1293 fn to_uppercase() {
1294 assert_eq!("".to_uppercase(), "");
1295 assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
1296 }
1297
1298 #[test]
1299 fn test_into_string() {
1300 // The only way to acquire a Box<str> in the first place is through a String, so just
1301 // test that we can round-trip between Box<str> and String.
1302 let string = String::from("Some text goes here");
1303 assert_eq!(string.clone().into_boxed_str().into_string(), string);
1304 }
1305
1306 #[test]
1307 fn test_box_slice_clone() {
1308 let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!");
1309 let data2 = data.clone().into_boxed_str().clone().into_string();
1310
1311 assert_eq!(data, data2);
1312 }
1313
1314 #[test]
1315 fn test_cow_from() {
1316 let borrowed = "borrowed";
1317 let owned = String::from("owned");
1318 match (Cow::from(owned.clone()), Cow::from(borrowed)) {
1319 (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed),
1320 _ => panic!("invalid `Cow::from`"),
1321 }
1322 }
1323
1324 #[test]
1325 fn test_repeat() {
1326 assert_eq!("".repeat(3), "");
1327 assert_eq!("abc".repeat(0), "");
1328 assert_eq!("α".repeat(3), "ααα");
1329 }
1330
1331 mod pattern {
1332 use std::str::pattern::Pattern;
1333 use std::str::pattern::{Searcher, ReverseSearcher};
1334 use std::str::pattern::SearchStep::{self, Match, Reject, Done};
1335
1336 macro_rules! make_test {
1337 ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => {
1338 #[allow(unused_imports)]
1339 mod $name {
1340 use std::str::pattern::SearchStep::{Match, Reject};
1341 use super::{cmp_search_to_vec};
1342 #[test]
1343 fn fwd() {
1344 cmp_search_to_vec(false, $p, $h, vec![$($e),*]);
1345 }
1346 #[test]
1347 fn bwd() {
1348 cmp_search_to_vec(true, $p, $h, vec![$($e),*]);
1349 }
1350 }
1351 }
1352 }
1353
1354 fn cmp_search_to_vec<'a, P: Pattern<'a>>(rev: bool, pat: P, haystack: &'a str,
1355 right: Vec<SearchStep>)
1356 where P::Searcher: ReverseSearcher<'a>
1357 {
1358 let mut searcher = pat.into_searcher(haystack);
1359 let mut v = vec![];
1360 loop {
1361 match if !rev {searcher.next()} else {searcher.next_back()} {
1362 Match(a, b) => v.push(Match(a, b)),
1363 Reject(a, b) => v.push(Reject(a, b)),
1364 Done => break,
1365 }
1366 }
1367 if rev {
1368 v.reverse();
1369 }
1370
1371 let mut first_index = 0;
1372 let mut err = None;
1373
1374 for (i, e) in right.iter().enumerate() {
1375 match *e {
1376 Match(a, b) | Reject(a, b)
1377 if a <= b && a == first_index => {
1378 first_index = b;
1379 }
1380 _ => {
1381 err = Some(i);
1382 break;
1383 }
1384 }
1385 }
1386
1387 if let Some(err) = err {
1388 panic!("Input skipped range at {}", err);
1389 }
1390
1391 if first_index != haystack.len() {
1392 panic!("Did not cover whole input");
1393 }
1394
1395 assert_eq!(v, right);
1396 }
1397
1398 make_test!(str_searcher_ascii_haystack, "bb", "abbcbbd", [
1399 Reject(0, 1),
1400 Match (1, 3),
1401 Reject(3, 4),
1402 Match (4, 6),
1403 Reject(6, 7),
1404 ]);
1405 make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
1406 Reject(0, 1),
1407 Match (1, 3),
1408 Reject(3, 4),
1409 Match (4, 6),
1410 Match (6, 8),
1411 Reject(8, 9),
1412 ]);
1413 make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
1414 Match (0, 0),
1415 Reject(0, 1),
1416 Match (1, 1),
1417 Reject(1, 2),
1418 Match (2, 2),
1419 Reject(2, 3),
1420 Match (3, 3),
1421 Reject(3, 4),
1422 Match (4, 4),
1423 Reject(4, 5),
1424 Match (5, 5),
1425 Reject(5, 6),
1426 Match (6, 6),
1427 Reject(6, 7),
1428 Match (7, 7),
1429 ]);
1430 make_test!(str_searcher_mulibyte_haystack, " ", "├──", [
1431 Reject(0, 3),
1432 Reject(3, 6),
1433 Reject(6, 9),
1434 ]);
1435 make_test!(str_searcher_empty_needle_mulibyte_haystack, "", "├──", [
1436 Match (0, 0),
1437 Reject(0, 3),
1438 Match (3, 3),
1439 Reject(3, 6),
1440 Match (6, 6),
1441 Reject(6, 9),
1442 Match (9, 9),
1443 ]);
1444 make_test!(str_searcher_empty_needle_empty_haystack, "", "", [
1445 Match(0, 0),
1446 ]);
1447 make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", [
1448 ]);
1449 make_test!(char_searcher_ascii_haystack, 'b', "abbcbbd", [
1450 Reject(0, 1),
1451 Match (1, 2),
1452 Match (2, 3),
1453 Reject(3, 4),
1454 Match (4, 5),
1455 Match (5, 6),
1456 Reject(6, 7),
1457 ]);
1458 make_test!(char_searcher_mulibyte_haystack, ' ', "├──", [
1459 Reject(0, 3),
1460 Reject(3, 6),
1461 Reject(6, 9),
1462 ]);
1463 make_test!(char_searcher_short_haystack, '\u{1F4A9}', "* \t", [
1464 Reject(0, 1),
1465 Reject(1, 2),
1466 Reject(2, 3),
1467 ]);
1468
1469 }
1470
1471 macro_rules! generate_iterator_test {
1472 {
1473 $name:ident {
1474 $(
1475 ($($arg:expr),*) -> [$($t:tt)*];
1476 )*
1477 }
1478 with $fwd:expr, $bwd:expr;
1479 } => {
1480 #[test]
1481 fn $name() {
1482 $(
1483 {
1484 let res = vec![$($t)*];
1485
1486 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1487 assert_eq!(fwd_vec, res);
1488
1489 let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect();
1490 bwd_vec.reverse();
1491 assert_eq!(bwd_vec, res);
1492 }
1493 )*
1494 }
1495 };
1496 {
1497 $name:ident {
1498 $(
1499 ($($arg:expr),*) -> [$($t:tt)*];
1500 )*
1501 }
1502 with $fwd:expr;
1503 } => {
1504 #[test]
1505 fn $name() {
1506 $(
1507 {
1508 let res = vec![$($t)*];
1509
1510 let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect();
1511 assert_eq!(fwd_vec, res);
1512 }
1513 )*
1514 }
1515 }
1516 }
1517
1518 generate_iterator_test! {
1519 double_ended_split {
1520 ("foo.bar.baz", '.') -> ["foo", "bar", "baz"];
1521 ("foo::bar::baz", "::") -> ["foo", "bar", "baz"];
1522 }
1523 with str::split, str::rsplit;
1524 }
1525
1526 generate_iterator_test! {
1527 double_ended_split_terminator {
1528 ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"];
1529 }
1530 with str::split_terminator, str::rsplit_terminator;
1531 }
1532
1533 generate_iterator_test! {
1534 double_ended_matches {
1535 ("a1b2c3", char::is_numeric) -> ["1", "2", "3"];
1536 }
1537 with str::matches, str::rmatches;
1538 }
1539
1540 generate_iterator_test! {
1541 double_ended_match_indices {
1542 ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")];
1543 }
1544 with str::match_indices, str::rmatch_indices;
1545 }
1546
1547 generate_iterator_test! {
1548 not_double_ended_splitn {
1549 ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"];
1550 }
1551 with str::splitn;
1552 }
1553
1554 generate_iterator_test! {
1555 not_double_ended_rsplitn {
1556 ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"];
1557 }
1558 with str::rsplitn;
1559 }
1560
1561 #[test]
1562 fn different_str_pattern_forwarding_lifetimes() {
1563 use std::str::pattern::Pattern;
1564
1565 fn foo<'a, P>(p: P) where for<'b> &'b P: Pattern<'a> {
1566 for _ in 0..3 {
1567 "asdf".find(&p);
1568 }
1569 }
1570
1571 foo::<&str>("x");
1572 }