]>
Commit | Line | Data |
---|---|---|
7453a54e | 1 | use std::borrow::Cow; |
c34b1796 | 2 | use std::cmp::Ordering::{Equal, Greater, Less}; |
fc512014 | 3 | use std::str::{from_utf8, from_utf8_unchecked}; |
c34b1796 AL |
4 | |
5 | #[test] | |
6 | fn test_le() { | |
7 | assert!("" <= ""); | |
8 | assert!("" <= "foo"); | |
9 | assert!("foo" <= "foo"); | |
532ac7d7 | 10 | assert_ne!("foo", "bar"); |
c34b1796 AL |
11 | } |
12 | ||
c34b1796 AL |
13 | #[test] |
14 | fn test_find() { | |
15 | assert_eq!("hello".find('l'), Some(2)); | |
dfeec247 | 16 | assert_eq!("hello".find(|c: char| c == 'o'), Some(4)); |
c34b1796 | 17 | assert!("hello".find('x').is_none()); |
dfeec247 | 18 | assert!("hello".find(|c: char| c == 'x').is_none()); |
c34b1796 AL |
19 | assert_eq!("ประเทศไทย中华Việt Nam".find('华'), Some(30)); |
20 | assert_eq!("ประเทศไทย中华Việt Nam".find(|c: char| c == '华'), Some(30)); | |
21 | } | |
22 | ||
23 | #[test] | |
24 | fn test_rfind() { | |
25 | assert_eq!("hello".rfind('l'), Some(3)); | |
dfeec247 | 26 | assert_eq!("hello".rfind(|c: char| c == 'o'), Some(4)); |
c34b1796 | 27 | assert!("hello".rfind('x').is_none()); |
dfeec247 | 28 | assert!("hello".rfind(|c: char| c == 'x').is_none()); |
c34b1796 AL |
29 | assert_eq!("ประเทศไทย中华Việt Nam".rfind('华'), Some(30)); |
30 | assert_eq!("ประเทศไทย中华Việt Nam".rfind(|c: char| c == '华'), Some(30)); | |
31 | } | |
32 | ||
33 | #[test] | |
34 | fn test_collect() { | |
b039eaaf | 35 | let empty = ""; |
c34b1796 AL |
36 | let s: String = empty.chars().collect(); |
37 | assert_eq!(empty, s); | |
b039eaaf | 38 | let data = "ประเทศไทย中"; |
c34b1796 AL |
39 | let s: String = data.chars().collect(); |
40 | assert_eq!(data, s); | |
41 | } | |
42 | ||
43 | #[test] | |
44 | fn test_into_bytes() { | |
62682a34 | 45 | let data = String::from("asdf"); |
c34b1796 AL |
46 | let buf = data.into_bytes(); |
47 | assert_eq!(buf, b"asdf"); | |
48 | } | |
49 | ||
50 | #[test] | |
51 | fn test_find_str() { | |
52 | // byte positions | |
53 | assert_eq!("".find(""), Some(0)); | |
54 | assert!("banana".find("apple pie").is_none()); | |
55 | ||
56 | let data = "abcabc"; | |
57 | assert_eq!(data[0..6].find("ab"), Some(0)); | |
58 | assert_eq!(data[2..6].find("ab"), Some(3 - 2)); | |
59 | assert!(data[2..4].find("ab").is_none()); | |
60 | ||
61 | let string = "ประเทศไทย中华Việt Nam"; | |
62682a34 | 62 | let mut data = String::from(string); |
c34b1796 AL |
63 | data.push_str(string); |
64 | assert!(data.find("ไท华").is_none()); | |
65 | assert_eq!(data[0..43].find(""), Some(0)); | |
66 | assert_eq!(data[6..43].find(""), Some(6 - 6)); | |
67 | ||
dfeec247 | 68 | assert_eq!(data[0..43].find("ประ"), Some(0)); |
c34b1796 AL |
69 | assert_eq!(data[0..43].find("ทศไ"), Some(12)); |
70 | assert_eq!(data[0..43].find("ย中"), Some(24)); | |
71 | assert_eq!(data[0..43].find("iệt"), Some(34)); | |
72 | assert_eq!(data[0..43].find("Nam"), Some(40)); | |
73 | ||
74 | assert_eq!(data[43..86].find("ประ"), Some(43 - 43)); | |
75 | assert_eq!(data[43..86].find("ทศไ"), Some(55 - 43)); | |
76 | assert_eq!(data[43..86].find("ย中"), Some(67 - 43)); | |
77 | assert_eq!(data[43..86].find("iệt"), Some(77 - 43)); | |
78 | assert_eq!(data[43..86].find("Nam"), Some(83 - 43)); | |
c34b1796 | 79 | |
b039eaaf | 80 | // find every substring -- assert that it finds it, or an earlier occurrence. |
e9174d1e SL |
81 | let string = "Việt Namacbaabcaabaaba"; |
82 | for (i, ci) in string.char_indices() { | |
83 | let ip = i + ci.len_utf8(); | |
dfeec247 | 84 | for j in string[ip..].char_indices().map(|(i, _)| i).chain(Some(string.len() - ip)) { |
e9174d1e SL |
85 | let pat = &string[i..ip + j]; |
86 | assert!(match string.find(pat) { | |
87 | None => false, | |
88 | Some(x) => x <= i, | |
89 | }); | |
90 | assert!(match string.rfind(pat) { | |
91 | None => false, | |
92 | Some(x) => x >= i, | |
93 | }); | |
94 | } | |
c34b1796 | 95 | } |
c34b1796 AL |
96 | } |
97 | ||
dfeec247 XL |
98 | fn s(x: &str) -> String { |
99 | x.to_string() | |
100 | } | |
c34b1796 AL |
101 | |
102 | macro_rules! test_concat { | |
dfeec247 XL |
103 | ($expected: expr, $string: expr) => {{ |
104 | let s: String = $string.concat(); | |
105 | assert_eq!($expected, s); | |
106 | }}; | |
c34b1796 AL |
107 | } |
108 | ||
109 | #[test] | |
110 | fn test_concat_for_different_types() { | |
111 | test_concat!("ab", vec![s("a"), s("b")]); | |
112 | test_concat!("ab", vec!["a", "b"]); | |
c34b1796 AL |
113 | } |
114 | ||
115 | #[test] | |
116 | fn test_concat_for_different_lengths() { | |
117 | let empty: &[&str] = &[]; | |
118 | test_concat!("", empty); | |
119 | test_concat!("a", ["a"]); | |
120 | test_concat!("ab", ["a", "b"]); | |
121 | test_concat!("abc", ["", "a", "bc"]); | |
122 | } | |
123 | ||
c1a9b12d | 124 | macro_rules! test_join { |
dfeec247 XL |
125 | ($expected: expr, $string: expr, $delim: expr) => {{ |
126 | let s = $string.join($delim); | |
127 | assert_eq!($expected, s); | |
128 | }}; | |
c34b1796 AL |
129 | } |
130 | ||
131 | #[test] | |
c1a9b12d SL |
132 | fn test_join_for_different_types() { |
133 | test_join!("a-b", ["a", "b"], "-"); | |
c34b1796 | 134 | let hyphen = "-".to_string(); |
c1a9b12d SL |
135 | test_join!("a-b", [s("a"), s("b")], &*hyphen); |
136 | test_join!("a-b", vec!["a", "b"], &*hyphen); | |
137 | test_join!("a-b", &*vec!["a", "b"], "-"); | |
138 | test_join!("a-b", vec![s("a"), s("b")], "-"); | |
c34b1796 AL |
139 | } |
140 | ||
141 | #[test] | |
c1a9b12d | 142 | fn test_join_for_different_lengths() { |
c34b1796 | 143 | let empty: &[&str] = &[]; |
c1a9b12d SL |
144 | test_join!("", empty, "-"); |
145 | test_join!("a", ["a"], "-"); | |
146 | test_join!("a-b", ["a", "b"], "-"); | |
147 | test_join!("-a-bc", ["", "a", "bc"], "-"); | |
c34b1796 AL |
148 | } |
149 | ||
94b46f34 XL |
150 | // join has fast paths for small separators up to 4 bytes |
151 | // this tests the slow paths. | |
152 | #[test] | |
153 | fn test_join_for_different_lengths_with_long_separator() { | |
154 | assert_eq!("~~~~~".len(), 15); | |
155 | ||
156 | let empty: &[&str] = &[]; | |
157 | test_join!("", empty, "~~~~~"); | |
158 | test_join!("a", ["a"], "~~~~~"); | |
159 | test_join!("a~~~~~b", ["a", "b"], "~~~~~"); | |
160 | test_join!("~~~~~a~~~~~bc", ["", "a", "bc"], "~~~~~"); | |
161 | } | |
162 | ||
36d6ef2b XL |
163 | #[test] |
164 | fn test_join_isue_80335() { | |
165 | use core::{borrow::Borrow, cell::Cell}; | |
166 | ||
167 | struct WeirdBorrow { | |
168 | state: Cell<bool>, | |
169 | } | |
170 | ||
171 | impl Default for WeirdBorrow { | |
172 | fn default() -> Self { | |
173 | WeirdBorrow { state: Cell::new(false) } | |
174 | } | |
175 | } | |
176 | ||
177 | impl Borrow<str> for WeirdBorrow { | |
178 | fn borrow(&self) -> &str { | |
179 | let state = self.state.get(); | |
180 | if state { | |
181 | "0" | |
182 | } else { | |
183 | self.state.set(true); | |
184 | "123456" | |
185 | } | |
186 | } | |
187 | } | |
188 | ||
189 | let arr: [WeirdBorrow; 3] = Default::default(); | |
190 | test_join!("0-0-0", arr, "-"); | |
191 | } | |
192 | ||
c34b1796 | 193 | #[test] |
60c5eb7d | 194 | #[cfg_attr(miri, ignore)] // Miri is too slow |
c34b1796 | 195 | fn test_unsafe_slice() { |
dfeec247 XL |
196 | assert_eq!("ab", unsafe { "abc".get_unchecked(0..2) }); |
197 | assert_eq!("bc", unsafe { "abc".get_unchecked(1..3) }); | |
198 | assert_eq!("", unsafe { "abc".get_unchecked(1..1) }); | |
c34b1796 AL |
199 | fn a_million_letter_a() -> String { |
200 | let mut i = 0; | |
201 | let mut rs = String::new(); | |
202 | while i < 100000 { | |
203 | rs.push_str("aaaaaaaaaa"); | |
204 | i += 1; | |
205 | } | |
206 | rs | |
207 | } | |
208 | fn half_a_million_letter_a() -> String { | |
209 | let mut i = 0; | |
210 | let mut rs = String::new(); | |
211 | while i < 100000 { | |
212 | rs.push_str("aaaaa"); | |
213 | i += 1; | |
214 | } | |
215 | rs | |
216 | } | |
217 | let letters = a_million_letter_a(); | |
dfeec247 | 218 | assert_eq!(half_a_million_letter_a(), unsafe { letters.get_unchecked(0..500000) }); |
c34b1796 AL |
219 | } |
220 | ||
221 | #[test] | |
222 | fn test_starts_with() { | |
3157f602 XL |
223 | assert!("".starts_with("")); |
224 | assert!("abc".starts_with("")); | |
225 | assert!("abc".starts_with("a")); | |
226 | assert!(!"a".starts_with("abc")); | |
227 | assert!(!"".starts_with("abc")); | |
228 | assert!(!"ödd".starts_with("-")); | |
229 | assert!("ödd".starts_with("öd")); | |
c34b1796 AL |
230 | } |
231 | ||
232 | #[test] | |
233 | fn test_ends_with() { | |
3157f602 XL |
234 | assert!("".ends_with("")); |
235 | assert!("abc".ends_with("")); | |
236 | assert!("abc".ends_with("c")); | |
237 | assert!(!"a".ends_with("abc")); | |
238 | assert!(!"".ends_with("abc")); | |
239 | assert!(!"ddö".ends_with("-")); | |
240 | assert!("ddö".ends_with("dö")); | |
c34b1796 AL |
241 | } |
242 | ||
243 | #[test] | |
244 | fn test_is_empty() { | |
245 | assert!("".is_empty()); | |
246 | assert!(!"a".is_empty()); | |
247 | } | |
248 | ||
9e0c209e SL |
249 | #[test] |
250 | fn test_replacen() { | |
251 | assert_eq!("".replacen('a', "b", 5), ""); | |
252 | assert_eq!("acaaa".replacen("a", "b", 3), "bcbba"); | |
253 | assert_eq!("aaaa".replacen("a", "b", 0), "aaaa"); | |
254 | ||
255 | let test = "test"; | |
256 | assert_eq!(" test test ".replacen(test, "toast", 3), " toast toast "); | |
257 | assert_eq!(" test test ".replacen(test, "toast", 0), " test test "); | |
258 | assert_eq!(" test test ".replacen(test, "", 5), " "); | |
259 | ||
260 | assert_eq!("qwer123zxc789".replacen(char::is_numeric, "", 3), "qwerzxc789"); | |
261 | } | |
262 | ||
c34b1796 AL |
263 | #[test] |
264 | fn test_replace() { | |
265 | let a = "a"; | |
b039eaaf SL |
266 | assert_eq!("".replace(a, "b"), ""); |
267 | assert_eq!("a".replace(a, "b"), "b"); | |
268 | assert_eq!("ab".replace(a, "b"), "bb"); | |
c34b1796 | 269 | let test = "test"; |
b039eaaf SL |
270 | assert_eq!(" test test ".replace(test, "toast"), " toast toast "); |
271 | assert_eq!(" test test ".replace(test, ""), " "); | |
c34b1796 AL |
272 | } |
273 | ||
274 | #[test] | |
275 | fn test_replace_2a() { | |
276 | let data = "ประเทศไทย中华"; | |
277 | let repl = "دولة الكويت"; | |
278 | ||
279 | let a = "ประเ"; | |
280 | let a2 = "دولة الكويتทศไทย中华"; | |
281 | assert_eq!(data.replace(a, repl), a2); | |
282 | } | |
283 | ||
284 | #[test] | |
285 | fn test_replace_2b() { | |
286 | let data = "ประเทศไทย中华"; | |
287 | let repl = "دولة الكويت"; | |
288 | ||
289 | let b = "ะเ"; | |
290 | let b2 = "ปรدولة الكويتทศไทย中华"; | |
291 | assert_eq!(data.replace(b, repl), b2); | |
292 | } | |
293 | ||
294 | #[test] | |
295 | fn test_replace_2c() { | |
296 | let data = "ประเทศไทย中华"; | |
297 | let repl = "دولة الكويت"; | |
298 | ||
299 | let c = "中华"; | |
300 | let c2 = "ประเทศไทยدولة الكويت"; | |
301 | assert_eq!(data.replace(c, repl), c2); | |
302 | } | |
303 | ||
304 | #[test] | |
305 | fn test_replace_2d() { | |
306 | let data = "ประเทศไทย中华"; | |
307 | let repl = "دولة الكويت"; | |
308 | ||
309 | let d = "ไท华"; | |
310 | assert_eq!(data.replace(d, repl), data); | |
311 | } | |
312 | ||
9cc50fc6 SL |
313 | #[test] |
314 | fn test_replace_pattern() { | |
315 | let data = "abcdαβγδabcdαβγδ"; | |
316 | assert_eq!(data.replace("dαβ", "😺😺😺"), "abc😺😺😺γδabc😺😺😺γδ"); | |
317 | assert_eq!(data.replace('γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ"); | |
318 | assert_eq!(data.replace(&['a', 'γ'] as &[_], "😺😺😺"), "😺😺😺bcdαβ😺😺😺δ😺😺😺bcdαβ😺😺😺δ"); | |
319 | assert_eq!(data.replace(|c| c == 'γ', "😺😺😺"), "abcdαβ😺😺😺δabcdαβ😺😺😺δ"); | |
320 | } | |
321 | ||
94b46f34 XL |
322 | // The current implementation of SliceIndex fails to handle methods |
323 | // orthogonally from range types; therefore, it is worth testing | |
324 | // all of the indexing operations on each input. | |
325 | mod slice_index { | |
326 | // Test a slicing operation **that should succeed,** | |
327 | // testing it on all of the indexing methods. | |
328 | // | |
329 | // This is not suitable for testing failure on invalid inputs. | |
330 | macro_rules! assert_range_eq { | |
dfeec247 | 331 | ($s:expr, $range:expr, $expected:expr) => { |
94b46f34 XL |
332 | let mut s: String = $s.to_owned(); |
333 | let mut expected: String = $expected.to_owned(); | |
334 | { | |
335 | let s: &str = &s; | |
336 | let expected: &str = &expected; | |
337 | ||
338 | assert_eq!(&s[$range], expected, "(in assertion for: index)"); | |
339 | assert_eq!(s.get($range), Some(expected), "(in assertion for: get)"); | |
340 | unsafe { | |
341 | assert_eq!( | |
dfeec247 XL |
342 | s.get_unchecked($range), |
343 | expected, | |
94b46f34 XL |
344 | "(in assertion for: get_unchecked)", |
345 | ); | |
346 | } | |
347 | } | |
348 | { | |
349 | let s: &mut str = &mut s; | |
350 | let expected: &mut str = &mut expected; | |
351 | ||
dfeec247 | 352 | assert_eq!(&mut s[$range], expected, "(in assertion for: index_mut)",); |
94b46f34 | 353 | assert_eq!( |
dfeec247 XL |
354 | s.get_mut($range), |
355 | Some(&mut expected[..]), | |
94b46f34 XL |
356 | "(in assertion for: get_mut)", |
357 | ); | |
358 | unsafe { | |
359 | assert_eq!( | |
dfeec247 XL |
360 | s.get_unchecked_mut($range), |
361 | expected, | |
94b46f34 XL |
362 | "(in assertion for: get_unchecked_mut)", |
363 | ); | |
364 | } | |
365 | } | |
dfeec247 | 366 | }; |
94b46f34 | 367 | } |
c34b1796 | 368 | |
94b46f34 XL |
369 | // Make sure the macro can actually detect bugs, |
370 | // because if it can't, then what are we even doing here? | |
371 | // | |
372 | // (Be aware this only demonstrates the ability to detect bugs | |
373 | // in the FIRST method that panics, as the macro is not designed | |
374 | // to be used in `should_panic`) | |
375 | #[test] | |
376 | #[should_panic(expected = "out of bounds")] | |
377 | fn assert_range_eq_can_fail_by_panic() { | |
378 | assert_range_eq!("abc", 0..5, "abc"); | |
379 | } | |
c34b1796 | 380 | |
94b46f34 XL |
381 | // (Be aware this only demonstrates the ability to detect bugs |
382 | // in the FIRST method it calls, as the macro is not designed | |
383 | // to be used in `should_panic`) | |
384 | #[test] | |
385 | #[should_panic(expected = "==")] | |
386 | fn assert_range_eq_can_fail_by_inequality() { | |
387 | assert_range_eq!("abc", 0..2, "abc"); | |
c34b1796 | 388 | } |
94b46f34 XL |
389 | |
390 | // Generates test cases for bad index operations. | |
391 | // | |
392 | // This generates `should_panic` test cases for Index/IndexMut | |
393 | // and `None` test cases for get/get_mut. | |
394 | macro_rules! panic_cases { | |
395 | ($( | |
396 | in mod $case_name:ident { | |
397 | data: $data:expr; | |
398 | ||
399 | // optional: | |
400 | // | |
401 | // a similar input for which DATA[input] succeeds, and the corresponding | |
402 | // output str. This helps validate "critical points" where an input range | |
403 | // straddles the boundary between valid and invalid. | |
404 | // (such as the input `len..len`, which is just barely valid) | |
405 | $( | |
406 | good: data[$good:expr] == $output:expr; | |
407 | )* | |
408 | ||
409 | bad: data[$bad:expr]; | |
410 | message: $expect_msg:expr; // must be a literal | |
411 | } | |
412 | )*) => {$( | |
413 | mod $case_name { | |
414 | #[test] | |
415 | fn pass() { | |
416 | let mut v: String = $data.into(); | |
417 | ||
418 | $( assert_range_eq!(v, $good, $output); )* | |
419 | ||
420 | { | |
421 | let v: &str = &v; | |
422 | assert_eq!(v.get($bad), None, "(in None assertion for get)"); | |
423 | } | |
424 | ||
425 | { | |
426 | let v: &mut str = &mut v; | |
427 | assert_eq!(v.get_mut($bad), None, "(in None assertion for get_mut)"); | |
428 | } | |
429 | } | |
430 | ||
431 | #[test] | |
432 | #[should_panic(expected = $expect_msg)] | |
433 | fn index_fail() { | |
434 | let v: String = $data.into(); | |
435 | let v: &str = &v; | |
436 | let _v = &v[$bad]; | |
437 | } | |
438 | ||
439 | #[test] | |
440 | #[should_panic(expected = $expect_msg)] | |
441 | fn index_mut_fail() { | |
442 | let mut v: String = $data.into(); | |
443 | let v: &mut str = &mut v; | |
444 | let _v = &mut v[$bad]; | |
445 | } | |
446 | } | |
447 | )*}; | |
448 | } | |
449 | ||
450 | #[test] | |
451 | fn simple_ascii() { | |
452 | assert_range_eq!("abc", .., "abc"); | |
453 | ||
454 | assert_range_eq!("abc", 0..2, "ab"); | |
455 | assert_range_eq!("abc", 0..=1, "ab"); | |
456 | assert_range_eq!("abc", ..2, "ab"); | |
457 | assert_range_eq!("abc", ..=1, "ab"); | |
458 | ||
459 | assert_range_eq!("abc", 1..3, "bc"); | |
460 | assert_range_eq!("abc", 1..=2, "bc"); | |
461 | assert_range_eq!("abc", 1..1, ""); | |
462 | assert_range_eq!("abc", 1..=0, ""); | |
463 | } | |
464 | ||
465 | #[test] | |
466 | fn simple_unicode() { | |
467 | // 日本 | |
468 | assert_range_eq!("\u{65e5}\u{672c}", .., "\u{65e5}\u{672c}"); | |
469 | ||
470 | assert_range_eq!("\u{65e5}\u{672c}", 0..3, "\u{65e5}"); | |
471 | assert_range_eq!("\u{65e5}\u{672c}", 0..=2, "\u{65e5}"); | |
472 | assert_range_eq!("\u{65e5}\u{672c}", ..3, "\u{65e5}"); | |
473 | assert_range_eq!("\u{65e5}\u{672c}", ..=2, "\u{65e5}"); | |
474 | ||
475 | assert_range_eq!("\u{65e5}\u{672c}", 3..6, "\u{672c}"); | |
476 | assert_range_eq!("\u{65e5}\u{672c}", 3..=5, "\u{672c}"); | |
477 | assert_range_eq!("\u{65e5}\u{672c}", 3.., "\u{672c}"); | |
478 | ||
479 | let data = "ประเทศไทย中华"; | |
480 | assert_range_eq!(data, 0..3, "ป"); | |
481 | assert_range_eq!(data, 3..6, "ร"); | |
482 | assert_range_eq!(data, 3..3, ""); | |
483 | assert_range_eq!(data, 30..33, "华"); | |
484 | ||
485 | /*0: 中 | |
dfeec247 XL |
486 | 3: 华 |
487 | 6: V | |
488 | 7: i | |
489 | 8: ệ | |
490 | 11: t | |
491 | 12: | |
492 | 13: N | |
493 | 14: a | |
494 | 15: m */ | |
94b46f34 XL |
495 | let ss = "中华Việt Nam"; |
496 | assert_range_eq!(ss, 3..6, "华"); | |
497 | assert_range_eq!(ss, 6..16, "Việt Nam"); | |
498 | assert_range_eq!(ss, 6..=15, "Việt Nam"); | |
499 | assert_range_eq!(ss, 6.., "Việt Nam"); | |
500 | ||
501 | assert_range_eq!(ss, 0..3, "中"); | |
502 | assert_range_eq!(ss, 3..7, "华V"); | |
503 | assert_range_eq!(ss, 3..=6, "华V"); | |
504 | assert_range_eq!(ss, 3..3, ""); | |
505 | assert_range_eq!(ss, 3..=2, ""); | |
506 | } | |
507 | ||
508 | #[test] | |
60c5eb7d XL |
509 | #[cfg_attr(target_os = "emscripten", ignore)] // hits an OOM |
510 | #[cfg_attr(miri, ignore)] // Miri is too slow | |
94b46f34 XL |
511 | fn simple_big() { |
512 | fn a_million_letter_x() -> String { | |
513 | let mut i = 0; | |
514 | let mut rs = String::new(); | |
515 | while i < 100000 { | |
516 | rs.push_str("华华华华华华华华华华"); | |
517 | i += 1; | |
518 | } | |
519 | rs | |
c34b1796 | 520 | } |
94b46f34 XL |
521 | fn half_a_million_letter_x() -> String { |
522 | let mut i = 0; | |
523 | let mut rs = String::new(); | |
524 | while i < 100000 { | |
525 | rs.push_str("华华华华华"); | |
526 | i += 1; | |
527 | } | |
528 | rs | |
529 | } | |
530 | let letters = a_million_letter_x(); | |
531 | assert_range_eq!(letters, 0..3 * 500000, half_a_million_letter_x()); | |
c34b1796 | 532 | } |
c34b1796 | 533 | |
94b46f34 XL |
534 | #[test] |
535 | #[should_panic] | |
536 | fn test_slice_fail() { | |
537 | &"中华Việt Nam"[0..2]; | |
538 | } | |
c34b1796 | 539 | |
94b46f34 XL |
540 | panic_cases! { |
541 | in mod rangefrom_len { | |
542 | data: "abcdef"; | |
543 | good: data[6..] == ""; | |
544 | bad: data[7..]; | |
545 | message: "out of bounds"; | |
546 | } | |
c34b1796 | 547 | |
94b46f34 XL |
548 | in mod rangeto_len { |
549 | data: "abcdef"; | |
550 | good: data[..6] == "abcdef"; | |
551 | bad: data[..7]; | |
552 | message: "out of bounds"; | |
553 | } | |
c34b1796 | 554 | |
94b46f34 XL |
555 | in mod rangetoinclusive_len { |
556 | data: "abcdef"; | |
557 | good: data[..=5] == "abcdef"; | |
558 | bad: data[..=6]; | |
559 | message: "out of bounds"; | |
560 | } | |
c34b1796 | 561 | |
29967ef6 XL |
562 | in mod rangeinclusive_len { |
563 | data: "abcdef"; | |
564 | good: data[0..=5] == "abcdef"; | |
565 | bad: data[0..=6]; | |
566 | message: "out of bounds"; | |
567 | } | |
568 | ||
94b46f34 XL |
569 | in mod range_len_len { |
570 | data: "abcdef"; | |
571 | good: data[6..6] == ""; | |
572 | bad: data[7..7]; | |
573 | message: "out of bounds"; | |
574 | } | |
c34b1796 | 575 | |
94b46f34 XL |
576 | in mod rangeinclusive_len_len { |
577 | data: "abcdef"; | |
578 | good: data[6..=5] == ""; | |
579 | bad: data[7..=6]; | |
580 | message: "out of bounds"; | |
581 | } | |
582 | } | |
041b39d2 | 583 | |
29967ef6 XL |
584 | panic_cases! { |
585 | in mod rangeinclusive_exhausted { | |
586 | data: "abcdef"; | |
587 | ||
588 | good: data[0..=5] == "abcdef"; | |
589 | good: data[{ | |
590 | let mut iter = 0..=5; | |
591 | iter.by_ref().count(); // exhaust it | |
592 | iter | |
593 | }] == ""; | |
594 | ||
595 | // 0..=6 is out of bounds before exhaustion, so it | |
596 | // stands to reason that it still would be after. | |
597 | bad: data[{ | |
598 | let mut iter = 0..=6; | |
599 | iter.by_ref().count(); // exhaust it | |
600 | iter | |
601 | }]; | |
602 | message: "out of bounds"; | |
603 | } | |
604 | } | |
605 | ||
94b46f34 XL |
606 | panic_cases! { |
607 | in mod range_neg_width { | |
608 | data: "abcdef"; | |
609 | good: data[4..4] == ""; | |
610 | bad: data[4..3]; | |
611 | message: "begin <= end (4 <= 3)"; | |
612 | } | |
041b39d2 | 613 | |
94b46f34 XL |
614 | in mod rangeinclusive_neg_width { |
615 | data: "abcdef"; | |
616 | good: data[4..=3] == ""; | |
617 | bad: data[4..=2]; | |
618 | message: "begin <= end (4 <= 3)"; | |
619 | } | |
620 | } | |
041b39d2 | 621 | |
94b46f34 XL |
622 | mod overflow { |
623 | panic_cases! { | |
624 | in mod rangeinclusive { | |
625 | data: "hello"; | |
626 | // note: using 0 specifically ensures that the result of overflowing is 0..0, | |
627 | // so that `get` doesn't simply return None for the wrong reason. | |
f035d41b | 628 | bad: data[0..=usize::MAX]; |
94b46f34 XL |
629 | message: "maximum usize"; |
630 | } | |
631 | ||
632 | in mod rangetoinclusive { | |
633 | data: "hello"; | |
f035d41b | 634 | bad: data[..=usize::MAX]; |
94b46f34 XL |
635 | message: "maximum usize"; |
636 | } | |
637 | } | |
638 | } | |
041b39d2 | 639 | |
94b46f34 | 640 | mod boundary { |
9fa01778 | 641 | const DATA: &str = "abcαβγ"; |
94b46f34 XL |
642 | |
643 | const BAD_START: usize = 4; | |
644 | const GOOD_START: usize = 3; | |
645 | const BAD_END: usize = 6; | |
646 | const GOOD_END: usize = 7; | |
647 | const BAD_END_INCL: usize = BAD_END - 1; | |
648 | const GOOD_END_INCL: usize = GOOD_END - 1; | |
649 | ||
650 | // it is especially important to test all of the different range types here | |
651 | // because some of the logic may be duplicated as part of micro-optimizations | |
652 | // to dodge unicode boundary checks on half-ranges. | |
653 | panic_cases! { | |
654 | in mod range_1 { | |
655 | data: super::DATA; | |
656 | bad: data[super::BAD_START..super::GOOD_END]; | |
657 | message: | |
658 | "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; | |
659 | } | |
660 | ||
661 | in mod range_2 { | |
662 | data: super::DATA; | |
663 | bad: data[super::GOOD_START..super::BAD_END]; | |
664 | message: | |
665 | "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; | |
666 | } | |
667 | ||
668 | in mod rangefrom { | |
669 | data: super::DATA; | |
670 | bad: data[super::BAD_START..]; | |
671 | message: | |
672 | "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; | |
673 | } | |
674 | ||
675 | in mod rangeto { | |
676 | data: super::DATA; | |
677 | bad: data[..super::BAD_END]; | |
678 | message: | |
679 | "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; | |
680 | } | |
681 | ||
682 | in mod rangeinclusive_1 { | |
683 | data: super::DATA; | |
684 | bad: data[super::BAD_START..=super::GOOD_END_INCL]; | |
685 | message: | |
686 | "byte index 4 is not a char boundary; it is inside 'α' (bytes 3..5) of"; | |
687 | } | |
688 | ||
689 | in mod rangeinclusive_2 { | |
690 | data: super::DATA; | |
691 | bad: data[super::GOOD_START..=super::BAD_END_INCL]; | |
692 | message: | |
693 | "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; | |
694 | } | |
695 | ||
696 | in mod rangetoinclusive { | |
697 | data: super::DATA; | |
698 | bad: data[..=super::BAD_END_INCL]; | |
699 | message: | |
700 | "byte index 6 is not a char boundary; it is inside 'β' (bytes 5..7) of"; | |
701 | } | |
702 | } | |
041b39d2 | 703 | } |
94b46f34 | 704 | |
9fa01778 | 705 | const LOREM_PARAGRAPH: &str = "\ |
94b46f34 XL |
706 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse quis lorem \ |
707 | sit amet dolor ultricies condimentum. Praesent iaculis purus elit, ac malesuada \ | |
708 | quam malesuada in. Duis sed orci eros. Suspendisse sit amet magna mollis, mollis \ | |
709 | nunc luctus, imperdiet mi. Integer fringilla non sem ut lacinia. Fusce varius \ | |
710 | tortor a risus porttitor hendrerit. Morbi mauris dui, ultricies nec tempus vel, \ | |
711 | gravida nec quam."; | |
712 | ||
713 | // check the panic includes the prefix of the sliced string | |
714 | #[test] | |
dfeec247 | 715 | #[should_panic(expected = "byte index 1024 is out of bounds of `Lorem ipsum dolor sit amet")] |
94b46f34 XL |
716 | fn test_slice_fail_truncated_1() { |
717 | &LOREM_PARAGRAPH[..1024]; | |
718 | } | |
719 | // check the truncation in the panic message | |
720 | #[test] | |
dfeec247 | 721 | #[should_panic(expected = "luctus, im`[...]")] |
94b46f34 XL |
722 | fn test_slice_fail_truncated_2() { |
723 | &LOREM_PARAGRAPH[..1024]; | |
041b39d2 XL |
724 | } |
725 | } | |
a7813a04 | 726 | |
0531ce1d XL |
727 | #[test] |
728 | fn test_str_slice_rangetoinclusive_ok() { | |
729 | let s = "abcαβγ"; | |
730 | assert_eq!(&s[..=2], "abc"); | |
731 | assert_eq!(&s[..=4], "abcα"); | |
732 | } | |
733 | ||
734 | #[test] | |
735 | #[should_panic] | |
736 | fn test_str_slice_rangetoinclusive_notok() { | |
737 | let s = "abcαβγ"; | |
738 | &s[..=3]; | |
739 | } | |
740 | ||
741 | #[test] | |
742 | fn test_str_slicemut_rangetoinclusive_ok() { | |
743 | let mut s = "abcαβγ".to_owned(); | |
744 | let s: &mut str = &mut s; | |
745 | assert_eq!(&mut s[..=2], "abc"); | |
746 | assert_eq!(&mut s[..=4], "abcα"); | |
747 | } | |
748 | ||
749 | #[test] | |
750 | #[should_panic] | |
751 | fn test_str_slicemut_rangetoinclusive_notok() { | |
752 | let mut s = "abcαβγ".to_owned(); | |
753 | let s: &mut str = &mut s; | |
754 | &mut s[..=3]; | |
755 | } | |
756 | ||
a7813a04 XL |
757 | #[test] |
758 | fn test_is_char_boundary() { | |
759 | let s = "ศไทย中华Việt Nam β-release 🐱123"; | |
760 | assert!(s.is_char_boundary(0)); | |
761 | assert!(s.is_char_boundary(s.len())); | |
762 | assert!(!s.is_char_boundary(s.len() + 1)); | |
763 | for (i, ch) in s.char_indices() { | |
764 | // ensure character locations are boundaries and continuation bytes are not | |
765 | assert!(s.is_char_boundary(i), "{} is a char boundary in {:?}", i, s); | |
766 | for j in 1..ch.len_utf8() { | |
dfeec247 XL |
767 | assert!( |
768 | !s.is_char_boundary(i + j), | |
769 | "{} should not be a char boundary in {:?}", | |
770 | i + j, | |
771 | s | |
772 | ); | |
a7813a04 XL |
773 | } |
774 | } | |
775 | } | |
c34b1796 AL |
776 | |
777 | #[test] | |
b7449926 | 778 | fn test_trim_start_matches() { |
c34b1796 | 779 | let v: &[char] = &[]; |
b7449926 | 780 | assert_eq!(" *** foo *** ".trim_start_matches(v), " *** foo *** "); |
c34b1796 | 781 | let chars: &[char] = &['*', ' ']; |
b7449926 XL |
782 | assert_eq!(" *** foo *** ".trim_start_matches(chars), "foo *** "); |
783 | assert_eq!(" *** *** ".trim_start_matches(chars), ""); | |
784 | assert_eq!("foo *** ".trim_start_matches(chars), "foo *** "); | |
c34b1796 | 785 | |
b7449926 | 786 | assert_eq!("11foo1bar11".trim_start_matches('1'), "foo1bar11"); |
c34b1796 | 787 | let chars: &[char] = &['1', '2']; |
b7449926 XL |
788 | assert_eq!("12foo1bar12".trim_start_matches(chars), "foo1bar12"); |
789 | assert_eq!("123foo1bar123".trim_start_matches(|c: char| c.is_numeric()), "foo1bar123"); | |
c34b1796 AL |
790 | } |
791 | ||
792 | #[test] | |
b7449926 | 793 | fn test_trim_end_matches() { |
c34b1796 | 794 | let v: &[char] = &[]; |
b7449926 | 795 | assert_eq!(" *** foo *** ".trim_end_matches(v), " *** foo *** "); |
c34b1796 | 796 | let chars: &[char] = &['*', ' ']; |
b7449926 XL |
797 | assert_eq!(" *** foo *** ".trim_end_matches(chars), " *** foo"); |
798 | assert_eq!(" *** *** ".trim_end_matches(chars), ""); | |
799 | assert_eq!(" *** foo".trim_end_matches(chars), " *** foo"); | |
c34b1796 | 800 | |
b7449926 | 801 | assert_eq!("11foo1bar11".trim_end_matches('1'), "11foo1bar"); |
c34b1796 | 802 | let chars: &[char] = &['1', '2']; |
b7449926 XL |
803 | assert_eq!("12foo1bar12".trim_end_matches(chars), "12foo1bar"); |
804 | assert_eq!("123foo1bar123".trim_end_matches(|c: char| c.is_numeric()), "123foo1bar"); | |
c34b1796 AL |
805 | } |
806 | ||
807 | #[test] | |
808 | fn test_trim_matches() { | |
809 | let v: &[char] = &[]; | |
810 | assert_eq!(" *** foo *** ".trim_matches(v), " *** foo *** "); | |
811 | let chars: &[char] = &['*', ' ']; | |
812 | assert_eq!(" *** foo *** ".trim_matches(chars), "foo"); | |
813 | assert_eq!(" *** *** ".trim_matches(chars), ""); | |
814 | assert_eq!("foo".trim_matches(chars), "foo"); | |
815 | ||
816 | assert_eq!("11foo1bar11".trim_matches('1'), "foo1bar"); | |
817 | let chars: &[char] = &['1', '2']; | |
818 | assert_eq!("12foo1bar12".trim_matches(chars), "foo1bar"); | |
819 | assert_eq!("123foo1bar123".trim_matches(|c: char| c.is_numeric()), "foo1bar"); | |
820 | } | |
821 | ||
822 | #[test] | |
b7449926 XL |
823 | fn test_trim_start() { |
824 | assert_eq!("".trim_start(), ""); | |
825 | assert_eq!("a".trim_start(), "a"); | |
826 | assert_eq!(" ".trim_start(), ""); | |
827 | assert_eq!(" blah".trim_start(), "blah"); | |
828 | assert_eq!(" \u{3000} wut".trim_start(), "wut"); | |
829 | assert_eq!("hey ".trim_start(), "hey "); | |
c34b1796 AL |
830 | } |
831 | ||
832 | #[test] | |
b7449926 XL |
833 | fn test_trim_end() { |
834 | assert_eq!("".trim_end(), ""); | |
835 | assert_eq!("a".trim_end(), "a"); | |
836 | assert_eq!(" ".trim_end(), ""); | |
837 | assert_eq!("blah ".trim_end(), "blah"); | |
838 | assert_eq!("wut \u{3000} ".trim_end(), "wut"); | |
839 | assert_eq!(" hey".trim_end(), " hey"); | |
c34b1796 AL |
840 | } |
841 | ||
842 | #[test] | |
843 | fn test_trim() { | |
844 | assert_eq!("".trim(), ""); | |
845 | assert_eq!("a".trim(), "a"); | |
846 | assert_eq!(" ".trim(), ""); | |
847 | assert_eq!(" blah ".trim(), "blah"); | |
848 | assert_eq!("\nwut \u{3000} ".trim(), "wut"); | |
849 | assert_eq!(" hey dude ".trim(), "hey dude"); | |
850 | } | |
851 | ||
852 | #[test] | |
853 | fn test_is_whitespace() { | |
854 | assert!("".chars().all(|c| c.is_whitespace())); | |
855 | assert!(" ".chars().all(|c| c.is_whitespace())); | |
856 | assert!("\u{2009}".chars().all(|c| c.is_whitespace())); // Thin space | |
857 | assert!(" \n\t ".chars().all(|c| c.is_whitespace())); | |
858 | assert!(!" _ ".chars().all(|c| c.is_whitespace())); | |
859 | } | |
860 | ||
c34b1796 AL |
861 | #[test] |
862 | fn test_is_utf8() { | |
863 | // deny overlong encodings | |
864 | assert!(from_utf8(&[0xc0, 0x80]).is_err()); | |
865 | assert!(from_utf8(&[0xc0, 0xae]).is_err()); | |
866 | assert!(from_utf8(&[0xe0, 0x80, 0x80]).is_err()); | |
867 | assert!(from_utf8(&[0xe0, 0x80, 0xaf]).is_err()); | |
868 | assert!(from_utf8(&[0xe0, 0x81, 0x81]).is_err()); | |
869 | assert!(from_utf8(&[0xf0, 0x82, 0x82, 0xac]).is_err()); | |
870 | assert!(from_utf8(&[0xf4, 0x90, 0x80, 0x80]).is_err()); | |
871 | ||
872 | // deny surrogates | |
873 | assert!(from_utf8(&[0xED, 0xA0, 0x80]).is_err()); | |
874 | assert!(from_utf8(&[0xED, 0xBF, 0xBF]).is_err()); | |
875 | ||
876 | assert!(from_utf8(&[0xC2, 0x80]).is_ok()); | |
877 | assert!(from_utf8(&[0xDF, 0xBF]).is_ok()); | |
878 | assert!(from_utf8(&[0xE0, 0xA0, 0x80]).is_ok()); | |
879 | assert!(from_utf8(&[0xED, 0x9F, 0xBF]).is_ok()); | |
880 | assert!(from_utf8(&[0xEE, 0x80, 0x80]).is_ok()); | |
881 | assert!(from_utf8(&[0xEF, 0xBF, 0xBF]).is_ok()); | |
882 | assert!(from_utf8(&[0xF0, 0x90, 0x80, 0x80]).is_ok()); | |
883 | assert!(from_utf8(&[0xF4, 0x8F, 0xBF, 0xBF]).is_ok()); | |
884 | } | |
885 | ||
9cc50fc6 SL |
886 | #[test] |
887 | fn from_utf8_mostly_ascii() { | |
888 | // deny invalid bytes embedded in long stretches of ascii | |
889 | for i in 32..64 { | |
890 | let mut data = [0; 128]; | |
891 | data[i] = 0xC0; | |
892 | assert!(from_utf8(&data).is_err()); | |
893 | data[i] = 0xC2; | |
894 | assert!(from_utf8(&data).is_err()); | |
895 | } | |
896 | } | |
897 | ||
cc61c64b XL |
898 | #[test] |
899 | fn from_utf8_error() { | |
900 | macro_rules! test { | |
901 | ($input: expr, $expected_valid_up_to: expr, $expected_error_len: expr) => { | |
902 | let error = from_utf8($input).unwrap_err(); | |
903 | assert_eq!(error.valid_up_to(), $expected_valid_up_to); | |
904 | assert_eq!(error.error_len(), $expected_error_len); | |
dfeec247 | 905 | }; |
cc61c64b XL |
906 | } |
907 | test!(b"A\xC3\xA9 \xFF ", 4, Some(1)); | |
908 | test!(b"A\xC3\xA9 \x80 ", 4, Some(1)); | |
909 | test!(b"A\xC3\xA9 \xC1 ", 4, Some(1)); | |
910 | test!(b"A\xC3\xA9 \xC1", 4, Some(1)); | |
911 | test!(b"A\xC3\xA9 \xC2", 4, None); | |
912 | test!(b"A\xC3\xA9 \xC2 ", 4, Some(1)); | |
913 | test!(b"A\xC3\xA9 \xC2\xC0", 4, Some(1)); | |
914 | test!(b"A\xC3\xA9 \xE0", 4, None); | |
915 | test!(b"A\xC3\xA9 \xE0\x9F", 4, Some(1)); | |
916 | test!(b"A\xC3\xA9 \xE0\xA0", 4, None); | |
917 | test!(b"A\xC3\xA9 \xE0\xA0\xC0", 4, Some(2)); | |
918 | test!(b"A\xC3\xA9 \xE0\xA0 ", 4, Some(2)); | |
919 | test!(b"A\xC3\xA9 \xED\xA0\x80 ", 4, Some(1)); | |
920 | test!(b"A\xC3\xA9 \xF1", 4, None); | |
921 | test!(b"A\xC3\xA9 \xF1\x80", 4, None); | |
922 | test!(b"A\xC3\xA9 \xF1\x80\x80", 4, None); | |
923 | test!(b"A\xC3\xA9 \xF1 ", 4, Some(1)); | |
924 | test!(b"A\xC3\xA9 \xF1\x80 ", 4, Some(2)); | |
925 | test!(b"A\xC3\xA9 \xF1\x80\x80 ", 4, Some(3)); | |
926 | } | |
927 | ||
c34b1796 AL |
928 | #[test] |
929 | fn test_as_bytes() { | |
930 | // no null | |
931 | let v = [ | |
dfeec247 XL |
932 | 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, |
933 | 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, | |
c34b1796 AL |
934 | ]; |
935 | let b: &[u8] = &[]; | |
936 | assert_eq!("".as_bytes(), b); | |
937 | assert_eq!("abc".as_bytes(), b"abc"); | |
938 | assert_eq!("ศไทย中华Việt Nam".as_bytes(), v); | |
939 | } | |
940 | ||
941 | #[test] | |
942 | #[should_panic] | |
943 | fn test_as_bytes_fail() { | |
944 | // Don't double free. (I'm not sure if this exercises the | |
945 | // original problem code path anymore.) | |
62682a34 | 946 | let s = String::from(""); |
c34b1796 AL |
947 | let _bytes = s.as_bytes(); |
948 | panic!(); | |
949 | } | |
950 | ||
951 | #[test] | |
952 | fn test_as_ptr() { | |
953 | let buf = "hello".as_ptr(); | |
954 | unsafe { | |
955 | assert_eq!(*buf.offset(0), b'h'); | |
956 | assert_eq!(*buf.offset(1), b'e'); | |
957 | assert_eq!(*buf.offset(2), b'l'); | |
958 | assert_eq!(*buf.offset(3), b'l'); | |
959 | assert_eq!(*buf.offset(4), b'o'); | |
960 | } | |
961 | } | |
962 | ||
c34b1796 AL |
963 | #[test] |
964 | fn vec_str_conversions() { | |
62682a34 | 965 | let s1: String = String::from("All mimsy were the borogoves"); |
c34b1796 AL |
966 | |
967 | let v: Vec<u8> = s1.as_bytes().to_vec(); | |
62682a34 | 968 | let s2: String = String::from(from_utf8(&v).unwrap()); |
c34b1796 AL |
969 | let mut i = 0; |
970 | let n1 = s1.len(); | |
971 | let n2 = v.len(); | |
972 | assert_eq!(n1, n2); | |
973 | while i < n1 { | |
974 | let a: u8 = s1.as_bytes()[i]; | |
975 | let b: u8 = s2.as_bytes()[i]; | |
c34b1796 AL |
976 | assert_eq!(a, b); |
977 | i += 1; | |
978 | } | |
979 | } | |
980 | ||
981 | #[test] | |
982 | fn test_contains() { | |
983 | assert!("abcde".contains("bcd")); | |
984 | assert!("abcde".contains("abcd")); | |
985 | assert!("abcde".contains("bcde")); | |
986 | assert!("abcde".contains("")); | |
987 | assert!("".contains("")); | |
988 | assert!(!"abcde".contains("def")); | |
989 | assert!(!"".contains("a")); | |
990 | ||
991 | let data = "ประเทศไทย中华Việt Nam"; | |
992 | assert!(data.contains("ประเ")); | |
993 | assert!(data.contains("ะเ")); | |
994 | assert!(data.contains("中华")); | |
995 | assert!(!data.contains("ไท华")); | |
996 | } | |
997 | ||
998 | #[test] | |
999 | fn test_contains_char() { | |
1000 | assert!("abc".contains('b')); | |
1001 | assert!("a".contains('a')); | |
1002 | assert!(!"abc".contains('d')); | |
1003 | assert!(!"".contains('a')); | |
1004 | } | |
1005 | ||
62682a34 SL |
1006 | #[test] |
1007 | fn test_split_at() { | |
1008 | let s = "ศไทย中华Việt Nam"; | |
1009 | for (index, _) in s.char_indices() { | |
1010 | let (a, b) = s.split_at(index); | |
1011 | assert_eq!(&s[..a.len()], a); | |
1012 | assert_eq!(&s[a.len()..], b); | |
1013 | } | |
1014 | let (a, b) = s.split_at(s.len()); | |
1015 | assert_eq!(a, s); | |
1016 | assert_eq!(b, ""); | |
1017 | } | |
1018 | ||
c1a9b12d SL |
1019 | #[test] |
1020 | fn test_split_at_mut() { | |
c1a9b12d SL |
1021 | let mut s = "Hello World".to_string(); |
1022 | { | |
1023 | let (a, b) = s.split_at_mut(5); | |
1024 | a.make_ascii_uppercase(); | |
1025 | b.make_ascii_lowercase(); | |
1026 | } | |
1027 | assert_eq!(s, "HELLO world"); | |
1028 | } | |
1029 | ||
62682a34 SL |
1030 | #[test] |
1031 | #[should_panic] | |
1032 | fn test_split_at_boundscheck() { | |
1033 | let s = "ศไทย中华Việt Nam"; | |
c1a9b12d | 1034 | s.split_at(1); |
62682a34 SL |
1035 | } |
1036 | ||
c34b1796 AL |
1037 | #[test] |
1038 | fn test_escape_unicode() { | |
9fa01778 XL |
1039 | assert_eq!("abc".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{63}"); |
1040 | assert_eq!("a c".escape_unicode().to_string(), "\\u{61}\\u{20}\\u{63}"); | |
1041 | assert_eq!("\r\n\t".escape_unicode().to_string(), "\\u{d}\\u{a}\\u{9}"); | |
1042 | assert_eq!("'\"\\".escape_unicode().to_string(), "\\u{27}\\u{22}\\u{5c}"); | |
1043 | assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode().to_string(), "\\u{0}\\u{1}\\u{fe}\\u{ff}"); | |
1044 | assert_eq!("\u{100}\u{ffff}".escape_unicode().to_string(), "\\u{100}\\u{ffff}"); | |
1045 | assert_eq!("\u{10000}\u{10ffff}".escape_unicode().to_string(), "\\u{10000}\\u{10ffff}"); | |
1046 | assert_eq!("ab\u{fb00}".escape_unicode().to_string(), "\\u{61}\\u{62}\\u{fb00}"); | |
1047 | assert_eq!("\u{1d4ea}\r".escape_unicode().to_string(), "\\u{1d4ea}\\u{d}"); | |
c34b1796 AL |
1048 | } |
1049 | ||
5bcae85e SL |
1050 | #[test] |
1051 | fn test_escape_debug() { | |
94b46f34 XL |
1052 | // Note that there are subtleties with the number of backslashes |
1053 | // on the left- and right-hand sides. In particular, Unicode code points | |
1054 | // are usually escaped with two backslashes on the right-hand side, as | |
0731742a | 1055 | // they are escaped. However, when the character is unescaped (e.g., for |
94b46f34 XL |
1056 | // printable characters), only a single backslash appears (as the character |
1057 | // itself appears in the debug string). | |
9fa01778 XL |
1058 | assert_eq!("abc".escape_debug().to_string(), "abc"); |
1059 | assert_eq!("a c".escape_debug().to_string(), "a c"); | |
1060 | assert_eq!("éèê".escape_debug().to_string(), "éèê"); | |
1061 | assert_eq!("\r\n\t".escape_debug().to_string(), "\\r\\n\\t"); | |
1062 | assert_eq!("'\"\\".escape_debug().to_string(), "\\'\\\"\\\\"); | |
1063 | assert_eq!("\u{7f}\u{ff}".escape_debug().to_string(), "\\u{7f}\u{ff}"); | |
1064 | assert_eq!("\u{100}\u{ffff}".escape_debug().to_string(), "\u{100}\\u{ffff}"); | |
1065 | assert_eq!("\u{10000}\u{10ffff}".escape_debug().to_string(), "\u{10000}\\u{10ffff}"); | |
1066 | assert_eq!("ab\u{200b}".escape_debug().to_string(), "ab\\u{200b}"); | |
1067 | assert_eq!("\u{10d4ea}\r".escape_debug().to_string(), "\\u{10d4ea}\\r"); | |
dfeec247 XL |
1068 | assert_eq!( |
1069 | "\u{301}a\u{301}bé\u{e000}".escape_debug().to_string(), | |
1070 | "\\u{301}a\u{301}bé\\u{e000}" | |
1071 | ); | |
5bcae85e SL |
1072 | } |
1073 | ||
c34b1796 AL |
1074 | #[test] |
1075 | fn test_escape_default() { | |
9fa01778 XL |
1076 | assert_eq!("abc".escape_default().to_string(), "abc"); |
1077 | assert_eq!("a c".escape_default().to_string(), "a c"); | |
1078 | assert_eq!("éèê".escape_default().to_string(), "\\u{e9}\\u{e8}\\u{ea}"); | |
1079 | assert_eq!("\r\n\t".escape_default().to_string(), "\\r\\n\\t"); | |
1080 | assert_eq!("'\"\\".escape_default().to_string(), "\\'\\\"\\\\"); | |
1081 | assert_eq!("\u{7f}\u{ff}".escape_default().to_string(), "\\u{7f}\\u{ff}"); | |
1082 | assert_eq!("\u{100}\u{ffff}".escape_default().to_string(), "\\u{100}\\u{ffff}"); | |
1083 | assert_eq!("\u{10000}\u{10ffff}".escape_default().to_string(), "\\u{10000}\\u{10ffff}"); | |
1084 | assert_eq!("ab\u{200b}".escape_default().to_string(), "ab\\u{200b}"); | |
1085 | assert_eq!("\u{10d4ea}\r".escape_default().to_string(), "\\u{10d4ea}\\r"); | |
c34b1796 AL |
1086 | } |
1087 | ||
1088 | #[test] | |
1089 | fn test_total_ord() { | |
b039eaaf SL |
1090 | assert_eq!("1234".cmp("123"), Greater); |
1091 | assert_eq!("123".cmp("1234"), Less); | |
1092 | assert_eq!("1234".cmp("1234"), Equal); | |
1093 | assert_eq!("12345555".cmp("123456"), Less); | |
1094 | assert_eq!("22".cmp("1234"), Greater); | |
c34b1796 AL |
1095 | } |
1096 | ||
c34b1796 AL |
1097 | #[test] |
1098 | fn test_iterator() { | |
1099 | let s = "ศไทย中华Việt Nam"; | |
dfeec247 | 1100 | let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm']; |
c34b1796 AL |
1101 | |
1102 | let mut pos = 0; | |
1103 | let it = s.chars(); | |
1104 | ||
1105 | for c in it { | |
1106 | assert_eq!(c, v[pos]); | |
1107 | pos += 1; | |
1108 | } | |
1109 | assert_eq!(pos, v.len()); | |
476ff2be | 1110 | assert_eq!(s.chars().count(), v.len()); |
c34b1796 AL |
1111 | } |
1112 | ||
1113 | #[test] | |
1114 | fn test_rev_iterator() { | |
1115 | let s = "ศไทย中华Việt Nam"; | |
dfeec247 | 1116 | let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ']; |
c34b1796 AL |
1117 | |
1118 | let mut pos = 0; | |
1119 | let it = s.chars().rev(); | |
1120 | ||
1121 | for c in it { | |
1122 | assert_eq!(c, v[pos]); | |
1123 | pos += 1; | |
1124 | } | |
1125 | assert_eq!(pos, v.len()); | |
1126 | } | |
1127 | ||
1128 | #[test] | |
60c5eb7d | 1129 | #[cfg_attr(miri, ignore)] // Miri is too slow |
c34b1796 | 1130 | fn test_chars_decoding() { |
c30ab7b3 | 1131 | let mut bytes = [0; 4]; |
9fa01778 | 1132 | for c in (0..0x110000).filter_map(std::char::from_u32) { |
c30ab7b3 | 1133 | let s = c.encode_utf8(&mut bytes); |
c34b1796 AL |
1134 | if Some(c) != s.chars().next() { |
1135 | panic!("character {:x}={} does not decode correctly", c as u32, c); | |
1136 | } | |
1137 | } | |
1138 | } | |
1139 | ||
1140 | #[test] | |
60c5eb7d | 1141 | #[cfg_attr(miri, ignore)] // Miri is too slow |
c34b1796 | 1142 | fn test_chars_rev_decoding() { |
c30ab7b3 | 1143 | let mut bytes = [0; 4]; |
9fa01778 | 1144 | for c in (0..0x110000).filter_map(std::char::from_u32) { |
c30ab7b3 | 1145 | let s = c.encode_utf8(&mut bytes); |
c34b1796 AL |
1146 | if Some(c) != s.chars().rev().next() { |
1147 | panic!("character {:x}={} does not decode correctly", c as u32, c); | |
1148 | } | |
1149 | } | |
1150 | } | |
1151 | ||
1152 | #[test] | |
1153 | fn test_iterator_clone() { | |
1154 | let s = "ศไทย中华Việt Nam"; | |
1155 | let mut it = s.chars(); | |
1156 | it.next(); | |
dfeec247 | 1157 | assert!(it.clone().zip(it).all(|(x, y)| x == y)); |
c34b1796 AL |
1158 | } |
1159 | ||
476ff2be SL |
1160 | #[test] |
1161 | fn test_iterator_last() { | |
1162 | let s = "ศไทย中华Việt Nam"; | |
1163 | let mut it = s.chars(); | |
1164 | it.next(); | |
1165 | assert_eq!(it.last(), Some('m')); | |
1166 | } | |
1167 | ||
416331ca XL |
1168 | #[test] |
1169 | fn test_chars_debug() { | |
1170 | let s = "ศไทย中华Việt Nam"; | |
1171 | let c = s.chars(); | |
1172 | assert_eq!( | |
1173 | format!("{:?}", c), | |
1174 | r#"Chars(['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm'])"# | |
1175 | ); | |
1176 | } | |
1177 | ||
c34b1796 AL |
1178 | #[test] |
1179 | fn test_bytesator() { | |
1180 | let s = "ศไทย中华Việt Nam"; | |
1181 | let v = [ | |
dfeec247 XL |
1182 | 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, |
1183 | 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, | |
c34b1796 AL |
1184 | ]; |
1185 | let mut pos = 0; | |
1186 | ||
1187 | for b in s.bytes() { | |
1188 | assert_eq!(b, v[pos]); | |
1189 | pos += 1; | |
1190 | } | |
1191 | } | |
1192 | ||
1193 | #[test] | |
1194 | fn test_bytes_revator() { | |
1195 | let s = "ศไทย中华Việt Nam"; | |
1196 | let v = [ | |
dfeec247 XL |
1197 | 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, |
1198 | 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, | |
c34b1796 AL |
1199 | ]; |
1200 | let mut pos = v.len(); | |
1201 | ||
1202 | for b in s.bytes().rev() { | |
1203 | pos -= 1; | |
1204 | assert_eq!(b, v[pos]); | |
1205 | } | |
1206 | } | |
1207 | ||
e9174d1e SL |
1208 | #[test] |
1209 | fn test_bytesator_nth() { | |
1210 | let s = "ศไทย中华Việt Nam"; | |
1211 | let v = [ | |
dfeec247 XL |
1212 | 224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228, 184, 173, 229, 141, 142, |
1213 | 86, 105, 225, 187, 135, 116, 32, 78, 97, 109, | |
e9174d1e SL |
1214 | ]; |
1215 | ||
1216 | let mut b = s.bytes(); | |
1217 | assert_eq!(b.nth(2).unwrap(), v[2]); | |
1218 | assert_eq!(b.nth(10).unwrap(), v[10]); | |
1219 | assert_eq!(b.nth(200), None); | |
1220 | } | |
1221 | ||
1222 | #[test] | |
1223 | fn test_bytesator_count() { | |
1224 | let s = "ศไทย中华Việt Nam"; | |
1225 | ||
1226 | let b = s.bytes(); | |
1227 | assert_eq!(b.count(), 28) | |
1228 | } | |
1229 | ||
1230 | #[test] | |
1231 | fn test_bytesator_last() { | |
1232 | let s = "ศไทย中华Việt Nam"; | |
1233 | ||
1234 | let b = s.bytes(); | |
1235 | assert_eq!(b.last().unwrap(), 109) | |
1236 | } | |
1237 | ||
c34b1796 AL |
1238 | #[test] |
1239 | fn test_char_indicesator() { | |
1240 | let s = "ศไทย中华Việt Nam"; | |
1241 | let p = [0, 3, 6, 9, 12, 15, 18, 19, 20, 23, 24, 25, 26, 27]; | |
dfeec247 | 1242 | let v = ['ศ', 'ไ', 'ท', 'ย', '中', '华', 'V', 'i', 'ệ', 't', ' ', 'N', 'a', 'm']; |
c34b1796 AL |
1243 | |
1244 | let mut pos = 0; | |
1245 | let it = s.char_indices(); | |
1246 | ||
1247 | for c in it { | |
1248 | assert_eq!(c, (p[pos], v[pos])); | |
1249 | pos += 1; | |
1250 | } | |
1251 | assert_eq!(pos, v.len()); | |
1252 | assert_eq!(pos, p.len()); | |
1253 | } | |
1254 | ||
1255 | #[test] | |
1256 | fn test_char_indices_revator() { | |
1257 | let s = "ศไทย中华Việt Nam"; | |
1258 | let p = [27, 26, 25, 24, 23, 20, 19, 18, 15, 12, 9, 6, 3, 0]; | |
dfeec247 | 1259 | let v = ['m', 'a', 'N', ' ', 't', 'ệ', 'i', 'V', '华', '中', 'ย', 'ท', 'ไ', 'ศ']; |
c34b1796 AL |
1260 | |
1261 | let mut pos = 0; | |
1262 | let it = s.char_indices().rev(); | |
1263 | ||
1264 | for c in it { | |
1265 | assert_eq!(c, (p[pos], v[pos])); | |
1266 | pos += 1; | |
1267 | } | |
1268 | assert_eq!(pos, v.len()); | |
1269 | assert_eq!(pos, p.len()); | |
1270 | } | |
1271 | ||
476ff2be SL |
1272 | #[test] |
1273 | fn test_char_indices_last() { | |
1274 | let s = "ศไทย中华Việt Nam"; | |
1275 | let mut it = s.char_indices(); | |
1276 | it.next(); | |
1277 | assert_eq!(it.last(), Some((27, 'm'))); | |
1278 | } | |
1279 | ||
c34b1796 AL |
1280 | #[test] |
1281 | fn test_splitn_char_iterator() { | |
1282 | let data = "\nMäry häd ä little lämb\nLittle lämb\n"; | |
1283 | ||
1284 | let split: Vec<&str> = data.splitn(4, ' ').collect(); | |
1285 | assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); | |
1286 | ||
1287 | let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect(); | |
1288 | assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]); | |
1289 | ||
1290 | // Unicode | |
1291 | let split: Vec<&str> = data.splitn(4, 'ä').collect(); | |
1292 | assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); | |
1293 | ||
1294 | let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect(); | |
1295 | assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]); | |
1296 | } | |
1297 | ||
1298 | #[test] | |
1299 | fn test_split_char_iterator_no_trailing() { | |
1300 | let data = "\nMäry häd ä little lämb\nLittle lämb\n"; | |
1301 | ||
1302 | let split: Vec<&str> = data.split('\n').collect(); | |
1303 | assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); | |
1304 | ||
1305 | let split: Vec<&str> = data.split_terminator('\n').collect(); | |
1306 | assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); | |
1307 | } | |
1308 | ||
74b04a01 XL |
1309 | #[test] |
1310 | fn test_split_char_iterator_inclusive() { | |
1311 | let data = "\nMäry häd ä little lämb\nLittle lämb\n"; | |
1312 | ||
1313 | let split: Vec<&str> = data.split_inclusive('\n').collect(); | |
1314 | assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]); | |
1315 | ||
1316 | let uppercase_separated = "SheePSharKTurtlECaT"; | |
1317 | let mut first_char = true; | |
1318 | let split: Vec<&str> = uppercase_separated | |
1319 | .split_inclusive(|c: char| { | |
1320 | let split = !first_char && c.is_uppercase(); | |
1321 | first_char = split; | |
1322 | split | |
1323 | }) | |
1324 | .collect(); | |
1325 | assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]); | |
1326 | } | |
1327 | ||
1328 | #[test] | |
1329 | fn test_split_char_iterator_inclusive_rev() { | |
1330 | let data = "\nMäry häd ä little lämb\nLittle lämb\n"; | |
1331 | ||
1332 | let split: Vec<&str> = data.split_inclusive('\n').rev().collect(); | |
1333 | assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]); | |
1334 | ||
1335 | // Note that the predicate is stateful and thus dependent | |
1336 | // on the iteration order. | |
1337 | // (A different predicate is needed for reverse iterator vs normal iterator.) | |
1338 | // Not sure if anything can be done though. | |
1339 | let uppercase_separated = "SheePSharKTurtlECaT"; | |
1340 | let mut term_char = true; | |
1341 | let split: Vec<&str> = uppercase_separated | |
1342 | .split_inclusive(|c: char| { | |
1343 | let split = term_char && c.is_uppercase(); | |
1344 | term_char = c.is_uppercase(); | |
1345 | split | |
1346 | }) | |
1347 | .rev() | |
1348 | .collect(); | |
1349 | assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]); | |
1350 | } | |
1351 | ||
c34b1796 AL |
1352 | #[test] |
1353 | fn test_rsplit() { | |
1354 | let data = "\nMäry häd ä little lämb\nLittle lämb\n"; | |
1355 | ||
1356 | let split: Vec<&str> = data.rsplit(' ').collect(); | |
1357 | assert_eq!(split, ["lämb\n", "lämb\nLittle", "little", "ä", "häd", "\nMäry"]); | |
1358 | ||
1359 | let split: Vec<&str> = data.rsplit("lämb").collect(); | |
1360 | assert_eq!(split, ["\n", "\nLittle ", "\nMäry häd ä little "]); | |
1361 | ||
1362 | let split: Vec<&str> = data.rsplit(|c: char| c == 'ä').collect(); | |
1363 | assert_eq!(split, ["mb\n", "mb\nLittle l", " little l", "d ", "ry h", "\nM"]); | |
1364 | } | |
1365 | ||
1366 | #[test] | |
1367 | fn test_rsplitn() { | |
1368 | let data = "\nMäry häd ä little lämb\nLittle lämb\n"; | |
1369 | ||
1370 | let split: Vec<&str> = data.rsplitn(2, ' ').collect(); | |
1371 | assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]); | |
1372 | ||
1373 | let split: Vec<&str> = data.rsplitn(2, "lämb").collect(); | |
1374 | assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]); | |
1375 | ||
1376 | let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect(); | |
1377 | assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]); | |
1378 | } | |
1379 | ||
3dfed10e XL |
1380 | #[test] |
1381 | fn test_split_once() { | |
1382 | assert_eq!("".split_once("->"), None); | |
1383 | assert_eq!("-".split_once("->"), None); | |
1384 | assert_eq!("->".split_once("->"), Some(("", ""))); | |
1385 | assert_eq!("a->".split_once("->"), Some(("a", ""))); | |
1386 | assert_eq!("->b".split_once("->"), Some(("", "b"))); | |
1387 | assert_eq!("a->b".split_once("->"), Some(("a", "b"))); | |
1388 | assert_eq!("a->b->c".split_once("->"), Some(("a", "b->c"))); | |
1389 | assert_eq!("---".split_once("--"), Some(("", "-"))); | |
1390 | } | |
1391 | ||
1392 | #[test] | |
1393 | fn test_rsplit_once() { | |
1394 | assert_eq!("".rsplit_once("->"), None); | |
1395 | assert_eq!("-".rsplit_once("->"), None); | |
1396 | assert_eq!("->".rsplit_once("->"), Some(("", ""))); | |
1397 | assert_eq!("a->".rsplit_once("->"), Some(("a", ""))); | |
1398 | assert_eq!("->b".rsplit_once("->"), Some(("", "b"))); | |
1399 | assert_eq!("a->b".rsplit_once("->"), Some(("a", "b"))); | |
1400 | assert_eq!("a->b->c".rsplit_once("->"), Some(("a->b", "c"))); | |
1401 | assert_eq!("---".rsplit_once("--"), Some(("-", ""))); | |
1402 | } | |
1403 | ||
c34b1796 | 1404 | #[test] |
d9579d0f | 1405 | fn test_split_whitespace() { |
c34b1796 | 1406 | let data = "\n \tMäry häd\tä little lämb\nLittle lämb\n"; |
d9579d0f | 1407 | let words: Vec<&str> = data.split_whitespace().collect(); |
c34b1796 AL |
1408 | assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"]) |
1409 | } | |
1410 | ||
c34b1796 AL |
1411 | #[test] |
1412 | fn test_lines() { | |
e9174d1e | 1413 | let data = "\nMäry häd ä little lämb\n\r\nLittle lämb\n"; |
c34b1796 AL |
1414 | let lines: Vec<&str> = data.lines().collect(); |
1415 | assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); | |
1416 | ||
e9174d1e | 1417 | let data = "\r\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n |
c34b1796 AL |
1418 | let lines: Vec<&str> = data.lines().collect(); |
1419 | assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]); | |
1420 | } | |
1421 | ||
c34b1796 AL |
1422 | #[test] |
1423 | fn test_splitator() { | |
1424 | fn t(s: &str, sep: &str, u: &[&str]) { | |
1425 | let v: Vec<&str> = s.split(sep).collect(); | |
1426 | assert_eq!(v, u); | |
1427 | } | |
1428 | t("--1233345--", "12345", &["--1233345--"]); | |
1429 | t("abc::hello::there", "::", &["abc", "hello", "there"]); | |
1430 | t("::hello::there", "::", &["", "hello", "there"]); | |
1431 | t("hello::there::", "::", &["hello", "there", ""]); | |
1432 | t("::hello::there::", "::", &["", "hello", "there", ""]); | |
1433 | t("ประเทศไทย中华Việt Nam", "中华", &["ประเทศไทย", "Việt Nam"]); | |
1434 | t("zzXXXzzYYYzz", "zz", &["", "XXX", "YYY", ""]); | |
1435 | t("zzXXXzYYYz", "XXX", &["zz", "zYYYz"]); | |
1436 | t(".XXX.YYY.", ".", &["", "XXX", "YYY", ""]); | |
1437 | t("", ".", &[""]); | |
dfeec247 | 1438 | t("zz", "zz", &["", ""]); |
c34b1796 | 1439 | t("ok", "z", &["ok"]); |
dfeec247 XL |
1440 | t("zzz", "zz", &["", "z"]); |
1441 | t("zzzzz", "zz", &["", "", "z"]); | |
c34b1796 AL |
1442 | } |
1443 | ||
1444 | #[test] | |
1445 | fn test_str_default() { | |
1446 | use std::default::Default; | |
1447 | ||
1448 | fn t<S: Default + AsRef<str>>() { | |
1449 | let s: S = Default::default(); | |
1450 | assert_eq!(s.as_ref(), ""); | |
1451 | } | |
1452 | ||
1453 | t::<&str>(); | |
1454 | t::<String>(); | |
94b46f34 | 1455 | t::<&mut str>(); |
c34b1796 AL |
1456 | } |
1457 | ||
1458 | #[test] | |
1459 | fn test_str_container() { | |
1460 | fn sum_len(v: &[&str]) -> usize { | |
1461 | v.iter().map(|x| x.len()).sum() | |
1462 | } | |
1463 | ||
b039eaaf | 1464 | let s = "01234"; |
c34b1796 | 1465 | assert_eq!(5, sum_len(&["012", "", "34"])); |
b039eaaf SL |
1466 | assert_eq!(5, sum_len(&["01", "2", "34", ""])); |
1467 | assert_eq!(5, sum_len(&[s])); | |
c34b1796 AL |
1468 | } |
1469 | ||
1470 | #[test] | |
1471 | fn test_str_from_utf8() { | |
1472 | let xs = b"hello"; | |
1473 | assert_eq!(from_utf8(xs), Ok("hello")); | |
1474 | ||
1475 | let xs = "ศไทย中华Việt Nam".as_bytes(); | |
1476 | assert_eq!(from_utf8(xs), Ok("ศไทย中华Việt Nam")); | |
1477 | ||
1478 | let xs = b"hello\xFF"; | |
9346a6ac AL |
1479 | assert!(from_utf8(xs).is_err()); |
1480 | } | |
1481 | ||
1482 | #[test] | |
1483 | fn test_pattern_deref_forward() { | |
1484 | let data = "aabcdaa"; | |
1485 | assert!(data.contains("bcd")); | |
1486 | assert!(data.contains(&"bcd")); | |
1487 | assert!(data.contains(&"bcd".to_string())); | |
1488 | } | |
1489 | ||
1490 | #[test] | |
1491 | fn test_empty_match_indices() { | |
1492 | let data = "aä中!"; | |
1493 | let vec: Vec<_> = data.match_indices("").collect(); | |
b039eaaf | 1494 | assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]); |
9346a6ac AL |
1495 | } |
1496 | ||
1497 | #[test] | |
1498 | fn test_bool_from_str() { | |
1499 | assert_eq!("true".parse().ok(), Some(true)); | |
1500 | assert_eq!("false".parse().ok(), Some(false)); | |
1501 | assert_eq!("not even a boolean".parse::<bool>().ok(), None); | |
1502 | } | |
1503 | ||
1504 | fn check_contains_all_substrings(s: &str) { | |
1505 | assert!(s.contains("")); | |
1506 | for i in 0..s.len() { | |
dfeec247 | 1507 | for j in i + 1..=s.len() { |
9346a6ac AL |
1508 | assert!(s.contains(&s[i..j])); |
1509 | } | |
1510 | } | |
1511 | } | |
1512 | ||
1513 | #[test] | |
60c5eb7d | 1514 | #[cfg_attr(miri, ignore)] // Miri is too slow |
9346a6ac AL |
1515 | fn strslice_issue_16589() { |
1516 | assert!("bananas".contains("nana")); | |
1517 | ||
1518 | // prior to the fix for #16589, x.contains("abcdabcd") returned false | |
1519 | // test all substrings for good measure | |
1520 | check_contains_all_substrings("012345678901234567890123456789bcdabcdabcd"); | |
1521 | } | |
1522 | ||
1523 | #[test] | |
1524 | fn strslice_issue_16878() { | |
1525 | assert!(!"1234567ah012345678901ah".contains("hah")); | |
1526 | assert!(!"00abc01234567890123456789abc".contains("bcabc")); | |
1527 | } | |
1528 | ||
9346a6ac | 1529 | #[test] |
60c5eb7d | 1530 | #[cfg_attr(miri, ignore)] // Miri is too slow |
9346a6ac AL |
1531 | fn test_strslice_contains() { |
1532 | let x = "There are moments, Jeeves, when one asks oneself, 'Do trousers matter?'"; | |
1533 | check_contains_all_substrings(x); | |
1534 | } | |
1535 | ||
1536 | #[test] | |
1537 | fn test_rsplitn_char_iterator() { | |
1538 | let data = "\nMäry häd ä little lämb\nLittle lämb\n"; | |
1539 | ||
1540 | let mut split: Vec<&str> = data.rsplitn(4, ' ').collect(); | |
1541 | split.reverse(); | |
1542 | assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); | |
1543 | ||
1544 | let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect(); | |
1545 | split.reverse(); | |
1546 | assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]); | |
1547 | ||
1548 | // Unicode | |
1549 | let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect(); | |
1550 | split.reverse(); | |
1551 | assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); | |
1552 | ||
1553 | let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect(); | |
1554 | split.reverse(); | |
1555 | assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]); | |
1556 | } | |
1557 | ||
1558 | #[test] | |
1559 | fn test_split_char_iterator() { | |
1560 | let data = "\nMäry häd ä little lämb\nLittle lämb\n"; | |
1561 | ||
1562 | let split: Vec<&str> = data.split(' ').collect(); | |
dfeec247 | 1563 | assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); |
9346a6ac AL |
1564 | |
1565 | let mut rsplit: Vec<&str> = data.split(' ').rev().collect(); | |
1566 | rsplit.reverse(); | |
1567 | assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); | |
1568 | ||
1569 | let split: Vec<&str> = data.split(|c: char| c == ' ').collect(); | |
dfeec247 | 1570 | assert_eq!(split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); |
9346a6ac AL |
1571 | |
1572 | let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect(); | |
1573 | rsplit.reverse(); | |
1574 | assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]); | |
1575 | ||
1576 | // Unicode | |
1577 | let split: Vec<&str> = data.split('ä').collect(); | |
dfeec247 | 1578 | assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); |
9346a6ac AL |
1579 | |
1580 | let mut rsplit: Vec<&str> = data.split('ä').rev().collect(); | |
1581 | rsplit.reverse(); | |
1582 | assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); | |
1583 | ||
1584 | let split: Vec<&str> = data.split(|c: char| c == 'ä').collect(); | |
dfeec247 | 1585 | assert_eq!(split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); |
9346a6ac AL |
1586 | |
1587 | let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect(); | |
1588 | rsplit.reverse(); | |
1589 | assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]); | |
1590 | } | |
1591 | ||
1592 | #[test] | |
1593 | fn test_rev_split_char_iterator_no_trailing() { | |
1594 | let data = "\nMäry häd ä little lämb\nLittle lämb\n"; | |
1595 | ||
1596 | let mut split: Vec<&str> = data.split('\n').rev().collect(); | |
1597 | split.reverse(); | |
1598 | assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]); | |
1599 | ||
1600 | let mut split: Vec<&str> = data.split_terminator('\n').rev().collect(); | |
1601 | split.reverse(); | |
1602 | assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); | |
1603 | } | |
1604 | ||
1605 | #[test] | |
1606 | fn test_utf16_code_units() { | |
dfeec247 | 1607 | assert_eq!("é\u{1F4A9}".encode_utf16().collect::<Vec<u16>>(), [0xE9, 0xD83D, 0xDCA9]) |
9346a6ac AL |
1608 | } |
1609 | ||
1610 | #[test] | |
1611 | fn starts_with_in_unicode() { | |
1612 | assert!(!"├── Cargo.toml".starts_with("# ")); | |
1613 | } | |
1614 | ||
1615 | #[test] | |
1616 | fn starts_short_long() { | |
1617 | assert!(!"".starts_with("##")); | |
1618 | assert!(!"##".starts_with("####")); | |
1619 | assert!("####".starts_with("##")); | |
1620 | assert!(!"##ä".starts_with("####")); | |
1621 | assert!("####ä".starts_with("##")); | |
1622 | assert!(!"##".starts_with("####ä")); | |
1623 | assert!("##ä##".starts_with("##ä")); | |
1624 | ||
1625 | assert!("".starts_with("")); | |
1626 | assert!("ä".starts_with("")); | |
1627 | assert!("#ä".starts_with("")); | |
1628 | assert!("##ä".starts_with("")); | |
1629 | assert!("ä###".starts_with("")); | |
1630 | assert!("#ä##".starts_with("")); | |
1631 | assert!("##ä#".starts_with("")); | |
1632 | } | |
1633 | ||
1634 | #[test] | |
1635 | fn contains_weird_cases() { | |
1636 | assert!("* \t".contains(' ')); | |
1637 | assert!(!"* \t".contains('?')); | |
1638 | assert!(!"* \t".contains('\u{1F4A9}')); | |
1639 | } | |
1640 | ||
1641 | #[test] | |
1642 | fn trim_ws() { | |
dfeec247 XL |
1643 | assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t "); |
1644 | assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a"); | |
1645 | assert_eq!(" \t a \t ".trim_start_matches(|c: char| c.is_whitespace()), "a \t "); | |
1646 | assert_eq!(" \t a \t ".trim_end_matches(|c: char| c.is_whitespace()), " \t a"); | |
1647 | assert_eq!(" \t a \t ".trim_matches(|c: char| c.is_whitespace()), "a"); | |
1648 | assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), ""); | |
1649 | assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), ""); | |
1650 | assert_eq!(" \t \t ".trim_start_matches(|c: char| c.is_whitespace()), ""); | |
1651 | assert_eq!(" \t \t ".trim_end_matches(|c: char| c.is_whitespace()), ""); | |
1652 | assert_eq!(" \t \t ".trim_matches(|c: char| c.is_whitespace()), ""); | |
9346a6ac AL |
1653 | } |
1654 | ||
62682a34 SL |
1655 | #[test] |
1656 | fn to_lowercase() { | |
1657 | assert_eq!("".to_lowercase(), ""); | |
1658 | assert_eq!("AÉDžaé ".to_lowercase(), "aédžaé "); | |
1659 | ||
1660 | // https://github.com/rust-lang/rust/issues/26035 | |
1661 | assert_eq!("ΑΣ".to_lowercase(), "ας"); | |
1662 | assert_eq!("Α'Σ".to_lowercase(), "α'ς"); | |
1663 | assert_eq!("Α''Σ".to_lowercase(), "α''ς"); | |
1664 | ||
1665 | assert_eq!("ΑΣ Α".to_lowercase(), "ας α"); | |
1666 | assert_eq!("Α'Σ Α".to_lowercase(), "α'ς α"); | |
1667 | assert_eq!("Α''Σ Α".to_lowercase(), "α''ς α"); | |
1668 | ||
1669 | assert_eq!("ΑΣ' Α".to_lowercase(), "ας' α"); | |
1670 | assert_eq!("ΑΣ'' Α".to_lowercase(), "ας'' α"); | |
1671 | ||
1672 | assert_eq!("Α'Σ' Α".to_lowercase(), "α'ς' α"); | |
1673 | assert_eq!("Α''Σ'' Α".to_lowercase(), "α''ς'' α"); | |
1674 | ||
1675 | assert_eq!("Α Σ".to_lowercase(), "α σ"); | |
1676 | assert_eq!("Α 'Σ".to_lowercase(), "α 'σ"); | |
1677 | assert_eq!("Α ''Σ".to_lowercase(), "α ''σ"); | |
1678 | ||
1679 | assert_eq!("Σ".to_lowercase(), "σ"); | |
1680 | assert_eq!("'Σ".to_lowercase(), "'σ"); | |
1681 | assert_eq!("''Σ".to_lowercase(), "''σ"); | |
1682 | ||
1683 | assert_eq!("ΑΣΑ".to_lowercase(), "ασα"); | |
1684 | assert_eq!("ΑΣ'Α".to_lowercase(), "ασ'α"); | |
1685 | assert_eq!("ΑΣ''Α".to_lowercase(), "ασ''α"); | |
1686 | } | |
1687 | ||
1688 | #[test] | |
1689 | fn to_uppercase() { | |
1690 | assert_eq!("".to_uppercase(), ""); | |
1691 | assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ"); | |
1692 | } | |
1693 | ||
c1a9b12d SL |
1694 | #[test] |
1695 | fn test_into_string() { | |
1696 | // The only way to acquire a Box<str> in the first place is through a String, so just | |
1697 | // test that we can round-trip between Box<str> and String. | |
1698 | let string = String::from("Some text goes here"); | |
e9174d1e | 1699 | assert_eq!(string.clone().into_boxed_str().into_string(), string); |
c1a9b12d SL |
1700 | } |
1701 | ||
1702 | #[test] | |
1703 | fn test_box_slice_clone() { | |
1704 | let data = String::from("hello HELLO hello HELLO yes YES 5 中ä华!!!"); | |
e9174d1e | 1705 | let data2 = data.clone().into_boxed_str().clone().into_string(); |
c1a9b12d SL |
1706 | |
1707 | assert_eq!(data, data2); | |
1708 | } | |
1709 | ||
7453a54e SL |
1710 | #[test] |
1711 | fn test_cow_from() { | |
1712 | let borrowed = "borrowed"; | |
1713 | let owned = String::from("owned"); | |
1714 | match (Cow::from(owned.clone()), Cow::from(borrowed)) { | |
1715 | (Cow::Owned(o), Cow::Borrowed(b)) => assert!(o == owned && b == borrowed), | |
1716 | _ => panic!("invalid `Cow::from`"), | |
1717 | } | |
1718 | } | |
1719 | ||
c30ab7b3 SL |
1720 | #[test] |
1721 | fn test_repeat() { | |
1722 | assert_eq!("".repeat(3), ""); | |
1723 | assert_eq!("abc".repeat(0), ""); | |
1724 | assert_eq!("α".repeat(3), "ααα"); | |
1725 | } | |
1726 | ||
9346a6ac | 1727 | mod pattern { |
dfeec247 XL |
1728 | use std::str::pattern::SearchStep::{self, Done, Match, Reject}; |
1729 | use std::str::pattern::{Pattern, ReverseSearcher, Searcher}; | |
9346a6ac AL |
1730 | |
1731 | macro_rules! make_test { | |
1732 | ($name:ident, $p:expr, $h:expr, [$($e:expr,)*]) => { | |
62682a34 | 1733 | #[allow(unused_imports)] |
9346a6ac AL |
1734 | mod $name { |
1735 | use std::str::pattern::SearchStep::{Match, Reject}; | |
1736 | use super::{cmp_search_to_vec}; | |
1737 | #[test] | |
1738 | fn fwd() { | |
1739 | cmp_search_to_vec(false, $p, $h, vec![$($e),*]); | |
1740 | } | |
1741 | #[test] | |
1742 | fn bwd() { | |
1743 | cmp_search_to_vec(true, $p, $h, vec![$($e),*]); | |
1744 | } | |
1745 | } | |
1746 | } | |
1747 | } | |
1748 | ||
416331ca XL |
1749 | fn cmp_search_to_vec<'a>( |
1750 | rev: bool, | |
1751 | pat: impl Pattern<'a, Searcher: ReverseSearcher<'a>>, | |
1752 | haystack: &'a str, | |
dfeec247 | 1753 | right: Vec<SearchStep>, |
416331ca | 1754 | ) { |
9346a6ac AL |
1755 | let mut searcher = pat.into_searcher(haystack); |
1756 | let mut v = vec![]; | |
1757 | loop { | |
dfeec247 | 1758 | match if !rev { searcher.next() } else { searcher.next_back() } { |
9346a6ac AL |
1759 | Match(a, b) => v.push(Match(a, b)), |
1760 | Reject(a, b) => v.push(Reject(a, b)), | |
1761 | Done => break, | |
1762 | } | |
1763 | } | |
1764 | if rev { | |
1765 | v.reverse(); | |
1766 | } | |
1767 | ||
1768 | let mut first_index = 0; | |
1769 | let mut err = None; | |
1770 | ||
1771 | for (i, e) in right.iter().enumerate() { | |
1772 | match *e { | |
dfeec247 | 1773 | Match(a, b) | Reject(a, b) if a <= b && a == first_index => { |
9346a6ac AL |
1774 | first_index = b; |
1775 | } | |
1776 | _ => { | |
1777 | err = Some(i); | |
1778 | break; | |
1779 | } | |
1780 | } | |
1781 | } | |
1782 | ||
1783 | if let Some(err) = err { | |
1784 | panic!("Input skipped range at {}", err); | |
1785 | } | |
1786 | ||
1787 | if first_index != haystack.len() { | |
1788 | panic!("Did not cover whole input"); | |
1789 | } | |
1790 | ||
1791 | assert_eq!(v, right); | |
1792 | } | |
1793 | ||
dfeec247 XL |
1794 | make_test!( |
1795 | str_searcher_ascii_haystack, | |
1796 | "bb", | |
1797 | "abbcbbd", | |
1798 | [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Reject(6, 7),] | |
1799 | ); | |
1800 | make_test!( | |
1801 | str_searcher_ascii_haystack_seq, | |
1802 | "bb", | |
1803 | "abbcbbbbd", | |
1804 | [Reject(0, 1), Match(1, 3), Reject(3, 4), Match(4, 6), Match(6, 8), Reject(8, 9),] | |
1805 | ); | |
1806 | make_test!( | |
1807 | str_searcher_empty_needle_ascii_haystack, | |
1808 | "", | |
1809 | "abbcbbd", | |
1810 | [ | |
1811 | Match(0, 0), | |
1812 | Reject(0, 1), | |
1813 | Match(1, 1), | |
1814 | Reject(1, 2), | |
1815 | Match(2, 2), | |
1816 | Reject(2, 3), | |
1817 | Match(3, 3), | |
1818 | Reject(3, 4), | |
1819 | Match(4, 4), | |
1820 | Reject(4, 5), | |
1821 | Match(5, 5), | |
1822 | Reject(5, 6), | |
1823 | Match(6, 6), | |
1824 | Reject(6, 7), | |
1825 | Match(7, 7), | |
1826 | ] | |
1827 | ); | |
1828 | make_test!( | |
1829 | str_searcher_multibyte_haystack, | |
1830 | " ", | |
1831 | "├──", | |
1832 | [Reject(0, 3), Reject(3, 6), Reject(6, 9),] | |
1833 | ); | |
1834 | make_test!( | |
1835 | str_searcher_empty_needle_multibyte_haystack, | |
1836 | "", | |
1837 | "├──", | |
1838 | [ | |
1839 | Match(0, 0), | |
1840 | Reject(0, 3), | |
1841 | Match(3, 3), | |
1842 | Reject(3, 6), | |
1843 | Match(6, 6), | |
1844 | Reject(6, 9), | |
1845 | Match(9, 9), | |
1846 | ] | |
1847 | ); | |
1848 | make_test!(str_searcher_empty_needle_empty_haystack, "", "", [Match(0, 0),]); | |
1849 | make_test!(str_searcher_nonempty_needle_empty_haystack, "├", "", []); | |
1850 | make_test!( | |
1851 | char_searcher_ascii_haystack, | |
1852 | 'b', | |
1853 | "abbcbbd", | |
1854 | [ | |
1855 | Reject(0, 1), | |
1856 | Match(1, 2), | |
1857 | Match(2, 3), | |
1858 | Reject(3, 4), | |
1859 | Match(4, 5), | |
1860 | Match(5, 6), | |
1861 | Reject(6, 7), | |
1862 | ] | |
1863 | ); | |
1864 | make_test!( | |
1865 | char_searcher_multibyte_haystack, | |
1866 | ' ', | |
1867 | "├──", | |
1868 | [Reject(0, 3), Reject(3, 6), Reject(6, 9),] | |
1869 | ); | |
1870 | make_test!( | |
1871 | char_searcher_short_haystack, | |
1872 | '\u{1F4A9}', | |
1873 | "* \t", | |
1874 | [Reject(0, 1), Reject(1, 2), Reject(2, 3),] | |
1875 | ); | |
9346a6ac AL |
1876 | } |
1877 | ||
1878 | macro_rules! generate_iterator_test { | |
1879 | { | |
1880 | $name:ident { | |
1881 | $( | |
1882 | ($($arg:expr),*) -> [$($t:tt)*]; | |
1883 | )* | |
1884 | } | |
1885 | with $fwd:expr, $bwd:expr; | |
1886 | } => { | |
1887 | #[test] | |
1888 | fn $name() { | |
1889 | $( | |
1890 | { | |
1891 | let res = vec![$($t)*]; | |
1892 | ||
1893 | let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect(); | |
1894 | assert_eq!(fwd_vec, res); | |
1895 | ||
1896 | let mut bwd_vec: Vec<_> = ($bwd)($($arg),*).collect(); | |
1897 | bwd_vec.reverse(); | |
1898 | assert_eq!(bwd_vec, res); | |
1899 | } | |
1900 | )* | |
1901 | } | |
1902 | }; | |
1903 | { | |
1904 | $name:ident { | |
1905 | $( | |
1906 | ($($arg:expr),*) -> [$($t:tt)*]; | |
1907 | )* | |
1908 | } | |
1909 | with $fwd:expr; | |
1910 | } => { | |
1911 | #[test] | |
1912 | fn $name() { | |
1913 | $( | |
1914 | { | |
1915 | let res = vec![$($t)*]; | |
1916 | ||
1917 | let fwd_vec: Vec<_> = ($fwd)($($arg),*).collect(); | |
1918 | assert_eq!(fwd_vec, res); | |
1919 | } | |
1920 | )* | |
1921 | } | |
1922 | } | |
1923 | } | |
1924 | ||
1925 | generate_iterator_test! { | |
1926 | double_ended_split { | |
1927 | ("foo.bar.baz", '.') -> ["foo", "bar", "baz"]; | |
1928 | ("foo::bar::baz", "::") -> ["foo", "bar", "baz"]; | |
1929 | } | |
1930 | with str::split, str::rsplit; | |
1931 | } | |
1932 | ||
1933 | generate_iterator_test! { | |
1934 | double_ended_split_terminator { | |
1935 | ("foo;bar;baz;", ';') -> ["foo", "bar", "baz"]; | |
1936 | } | |
1937 | with str::split_terminator, str::rsplit_terminator; | |
1938 | } | |
1939 | ||
1940 | generate_iterator_test! { | |
1941 | double_ended_matches { | |
1942 | ("a1b2c3", char::is_numeric) -> ["1", "2", "3"]; | |
1943 | } | |
1944 | with str::matches, str::rmatches; | |
1945 | } | |
1946 | ||
1947 | generate_iterator_test! { | |
1948 | double_ended_match_indices { | |
b039eaaf | 1949 | ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")]; |
9346a6ac AL |
1950 | } |
1951 | with str::match_indices, str::rmatch_indices; | |
1952 | } | |
1953 | ||
1954 | generate_iterator_test! { | |
1955 | not_double_ended_splitn { | |
1956 | ("foo::bar::baz", 2, "::") -> ["foo", "bar::baz"]; | |
1957 | } | |
1958 | with str::splitn; | |
1959 | } | |
1960 | ||
1961 | generate_iterator_test! { | |
1962 | not_double_ended_rsplitn { | |
1963 | ("foo::bar::baz", 2, "::") -> ["baz", "foo::bar"]; | |
1964 | } | |
1965 | with str::rsplitn; | |
c34b1796 AL |
1966 | } |
1967 | ||
54a0048b SL |
1968 | #[test] |
1969 | fn different_str_pattern_forwarding_lifetimes() { | |
1970 | use std::str::pattern::Pattern; | |
1971 | ||
dfeec247 XL |
1972 | fn foo<'a, P>(p: P) |
1973 | where | |
1974 | for<'b> &'b P: Pattern<'a>, | |
1975 | { | |
54a0048b SL |
1976 | for _ in 0..3 { |
1977 | "asdf".find(&p); | |
1978 | } | |
1979 | } | |
1980 | ||
1981 | foo::<&str>("x"); | |
1982 | } | |
1b1a35ee XL |
1983 | |
1984 | #[test] | |
1985 | fn test_str_multiline() { | |
1986 | let a: String = "this \ | |
1987 | is a test" | |
1988 | .to_string(); | |
1989 | let b: String = "this \ | |
1990 | is \ | |
1991 | another \ | |
1992 | test" | |
1993 | .to_string(); | |
1994 | assert_eq!(a, "this is a test".to_string()); | |
1995 | assert_eq!(b, "this is another test".to_string()); | |
1996 | } | |
1997 | ||
1998 | #[test] | |
1999 | fn test_str_escapes() { | |
2000 | let x = "\\\\\ | |
2001 | "; | |
2002 | assert_eq!(x, r"\\"); // extraneous whitespace stripped | |
2003 | } | |
fc512014 XL |
2004 | |
2005 | #[test] | |
2006 | fn const_str_ptr() { | |
2007 | const A: [u8; 2] = ['h' as u8, 'i' as u8]; | |
2008 | const B: &'static [u8; 2] = &A; | |
2009 | const C: *const u8 = B as *const u8; | |
2010 | ||
2011 | // Miri does not deduplicate consts (https://github.com/rust-lang/miri/issues/131) | |
2012 | #[cfg(not(miri))] | |
2013 | { | |
2014 | let foo = &A as *const u8; | |
2015 | assert_eq!(foo, C); | |
2016 | } | |
2017 | ||
2018 | unsafe { | |
2019 | assert_eq!(from_utf8_unchecked(&A), "hi"); | |
2020 | assert_eq!(*C, A[0]); | |
2021 | assert_eq!(*(&B[0] as *const u8), A[0]); | |
2022 | } | |
2023 | } | |
2024 | ||
2025 | #[test] | |
2026 | fn utf8() { | |
2027 | let yen: char = '¥'; // 0xa5 | |
2028 | let c_cedilla: char = 'ç'; // 0xe7 | |
2029 | let thorn: char = 'þ'; // 0xfe | |
2030 | let y_diaeresis: char = 'ÿ'; // 0xff | |
2031 | let pi: char = 'Π'; // 0x3a0 | |
2032 | ||
2033 | assert_eq!(yen as isize, 0xa5); | |
2034 | assert_eq!(c_cedilla as isize, 0xe7); | |
2035 | assert_eq!(thorn as isize, 0xfe); | |
2036 | assert_eq!(y_diaeresis as isize, 0xff); | |
2037 | assert_eq!(pi as isize, 0x3a0); | |
2038 | ||
2039 | assert_eq!(pi as isize, '\u{3a0}' as isize); | |
2040 | assert_eq!('\x0a' as isize, '\n' as isize); | |
2041 | ||
2042 | let bhutan: String = "འབྲུག་ཡུལ།".to_string(); | |
2043 | let japan: String = "日本".to_string(); | |
2044 | let uzbekistan: String = "Ўзбекистон".to_string(); | |
2045 | let austria: String = "Österreich".to_string(); | |
2046 | ||
2047 | let bhutan_e: String = | |
2048 | "\u{f60}\u{f56}\u{fb2}\u{f74}\u{f42}\u{f0b}\u{f61}\u{f74}\u{f63}\u{f0d}".to_string(); | |
2049 | let japan_e: String = "\u{65e5}\u{672c}".to_string(); | |
2050 | let uzbekistan_e: String = | |
2051 | "\u{40e}\u{437}\u{431}\u{435}\u{43a}\u{438}\u{441}\u{442}\u{43e}\u{43d}".to_string(); | |
2052 | let austria_e: String = "\u{d6}sterreich".to_string(); | |
2053 | ||
2054 | let oo: char = 'Ö'; | |
2055 | assert_eq!(oo as isize, 0xd6); | |
2056 | ||
2057 | fn check_str_eq(a: String, b: String) { | |
2058 | let mut i: isize = 0; | |
2059 | for ab in a.bytes() { | |
2060 | println!("{}", i); | |
2061 | println!("{}", ab); | |
2062 | let bb: u8 = b.as_bytes()[i as usize]; | |
2063 | println!("{}", bb); | |
2064 | assert_eq!(ab, bb); | |
2065 | i += 1; | |
2066 | } | |
2067 | } | |
2068 | ||
2069 | check_str_eq(bhutan, bhutan_e); | |
2070 | check_str_eq(japan, japan_e); | |
2071 | check_str_eq(uzbekistan, uzbekistan_e); | |
2072 | check_str_eq(austria, austria_e); | |
2073 | } | |
2074 | ||
2075 | #[test] | |
2076 | fn utf8_chars() { | |
2077 | // Chars of 1, 2, 3, and 4 bytes | |
2078 | let chs: Vec<char> = vec!['e', 'é', '€', '\u{10000}']; | |
2079 | let s: String = chs.iter().cloned().collect(); | |
2080 | let schs: Vec<char> = s.chars().collect(); | |
2081 | ||
2082 | assert_eq!(s.len(), 10); | |
2083 | assert_eq!(s.chars().count(), 4); | |
2084 | assert_eq!(schs.len(), 4); | |
2085 | assert_eq!(schs.iter().cloned().collect::<String>(), s); | |
2086 | ||
2087 | assert!((from_utf8(s.as_bytes()).is_ok())); | |
2088 | // invalid prefix | |
2089 | assert!((!from_utf8(&[0x80]).is_ok())); | |
2090 | // invalid 2 byte prefix | |
2091 | assert!((!from_utf8(&[0xc0]).is_ok())); | |
2092 | assert!((!from_utf8(&[0xc0, 0x10]).is_ok())); | |
2093 | // invalid 3 byte prefix | |
2094 | assert!((!from_utf8(&[0xe0]).is_ok())); | |
2095 | assert!((!from_utf8(&[0xe0, 0x10]).is_ok())); | |
2096 | assert!((!from_utf8(&[0xe0, 0xff, 0x10]).is_ok())); | |
2097 | // invalid 4 byte prefix | |
2098 | assert!((!from_utf8(&[0xf0]).is_ok())); | |
2099 | assert!((!from_utf8(&[0xf0, 0x10]).is_ok())); | |
2100 | assert!((!from_utf8(&[0xf0, 0xff, 0x10]).is_ok())); | |
2101 | assert!((!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok())); | |
2102 | } |