diff options
Diffstat (limited to 'vendor/encode_unicode/tests')
-rw-r--r-- | vendor/encode_unicode/tests/errs.rs | 197 | ||||
-rw-r--r-- | vendor/encode_unicode/tests/exhaustive.rs | 34 | ||||
-rw-r--r-- | vendor/encode_unicode/tests/iterators.rs | 182 | ||||
-rw-r--r-- | vendor/encode_unicode/tests/oks.rs | 284 |
4 files changed, 697 insertions, 0 deletions
diff --git a/vendor/encode_unicode/tests/errs.rs b/vendor/encode_unicode/tests/errs.rs new file mode 100644 index 0000000..9c8747b --- /dev/null +++ b/vendor/encode_unicode/tests/errs.rs @@ -0,0 +1,197 @@ +/* Copyright 2016 The encode_unicode Developers + * + * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or + * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or + * http://opensource.org/licenses/MIT>, at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Test that methods gives the correct error. +//! Some also test a bit more because it's easy. + +extern crate core; +use core::char; +extern crate encode_unicode; +use encode_unicode::*; +use encode_unicode::error::*; +use encode_unicode::error::InvalidUtf8Array as a; +use encode_unicode::error::InvalidUtf8Slice as s; +use encode_unicode::error::InvalidCodepoint::*; +use encode_unicode::error::InvalidUtf8::*; +use encode_unicode::error::InvalidUtf8FirstByte::*; + + +#[test] +fn from_u32() { + for c in 0xd800..0xe000 { + assert_eq!(char::from_u32_detailed(c), Err(Utf16Reserved)); + } + let mut c = 0x11_00_00; + loop { + assert_eq!(char::from_u32_detailed(c), Err(TooHigh)); + // Don't test every value. (Range.step_by() is unstable) + match c.checked_add(0x10_11_11) { + Some(next) => c = next, + None => break, + } + } +} + +#[test] +fn utf8_extra_bytes() { + for c in 0..256 { + assert_eq!( (c as u8).extra_utf8_bytes(), match c { + 0b_1000_0000...0b_1011_1111 => Err(ContinuationByte), + 0b_1111_1000...0b_1111_1111 => Err(TooLongSeqence), + 0b_0000_0000...0b_0111_1111 => Ok(0), + 0b_1100_0000...0b_1101_1111 => Ok(1), + 0b_1110_0000...0b_1110_1111 => Ok(2), + 0b_1111_0000...0b_1111_0111 => Ok(3), + _ => unreachable!(), + }); + } +} + +#[test] +fn utf16_extra_unit() { + for c in 0..0x1_00_00 { + assert_eq!( (c as u16).utf16_needs_extra_unit(), match c { + 0b_0000_0000_0000_0000...0b_1101_0111_1111_1111 => Ok(false), + 0b_1101_1000_0000_0000...0b_1101_1011_1111_1111 => Ok(true), + 0b_1101_1100_0000_0000...0b_1101_1111_1111_1111 => Err(InvalidUtf16FirstUnit), + 0b_1110_0000_0000_0000...0b_1111_1111_1111_1111 => Ok(false), + _ => unreachable!(), + }); + } +} + + +#[test] +fn from_utf16_tuple() { + use encode_unicode::error::InvalidUtf16Tuple::*; + for u in 0xdc00..0xe000 { + let close = if u%3==0 {u-100} else {u+100}; + let doesnt_matter = if u%2==0 {Some(close)} else {None}; + assert_eq!(char::from_utf16_tuple((u,doesnt_matter)), Err(FirstIsTrailingSurrogate)); + } + for u in (0..0xd800).chain(0xe000..0x10000) { + assert_eq!( + char::from_utf16_tuple((u as u16, Some((0x100+u) as u16))), + Err(SuperfluousSecond) + ); + } + for u in 0xd800..0xdc00 { + assert_eq!(char::from_utf16_tuple((u,None)), Err(MissingSecond)); + assert_eq!(char::from_utf16_tuple((u,Some(u - 0x2ff))), Err(InvalidSecond)); + } +} + +#[test] +fn from_utf16_slice_start() { + use encode_unicode::error::InvalidUtf16Slice::*; + assert_eq!(char::from_utf16_slice_start(&[]), Err(EmptySlice)); + let mut buf = [0; 6]; + for u in 0xd800..0xdc00 { + buf[0] = u; + assert_eq!(char::from_utf16_slice_start(&buf[..1]), Err(MissingSecond)); + buf[1] = u; + let pass = 2 + (u as usize % (buf.len()-2)); + assert_eq!(char::from_utf16_slice_start(&buf[..pass]), Err(SecondNotLowSurrogate)); + } + for u in 0xdc00..0xe000 { + buf[0] = u; + let close = if u%3==0 {u-100} else {u+100}; + let pass = 1 + (u as usize % (buf.len()-1)); + buf[pass] = close; + assert_eq!(char::from_utf16_slice_start(&buf[..pass]), Err(FirstLowSurrogate)); + } +} + +#[test] +fn utf8_overlong() { + let overlongs = [ + [0xf0,0x8f], [0xf0,0x87], [0xf0,0x80], // 4-byte + [0xe0,0x9f], [0xe0,0x8f], [0xe0,0x80], // 3-byte + [0xc1,0xbf], [0xc1,0x92], [0xc1,0x80], // 2-byte + [0xc0,0xbf], [0xc0,0x9f], [0xc0,0x80], // 2-byte + ]; + for o in overlongs.iter() { + for &last in &[0x80, 0xbf] { + let arr = [o[0], o[1], last, last]; + assert_eq!(char::from_utf8_slice_start(&arr), Err(InvalidUtf8Slice::Utf8(OverLong))); + assert_eq!(char::from_utf8_array(arr), Err(InvalidUtf8Array::Utf8(OverLong))); + assert_eq!(Utf8Char::from_slice_start(&arr), Err(InvalidUtf8Slice::Utf8(OverLong))); + assert_eq!(Utf8Char::from_array(arr), Err(InvalidUtf8Array::Utf8(OverLong))); + } + } +} + +#[test] +fn from_str_start() { + assert_eq!(Utf8Char::from_str_start(""), Err(EmptyStrError)); + assert_eq!(Utf16Char::from_str_start(""), Err(EmptyStrError)); +} + +#[test] fn utf8_codepoint_is_too_high() { + assert_eq!(Utf8Char::from_array([0xf4, 0x90, 0x80, 0x80]), Err(a::Codepoint(TooHigh))); + assert_eq!(char::from_utf8_array([0xf4, 0x90, 0x80, 0x80]), Err(a::Codepoint(TooHigh))); + assert_eq!(Utf8Char::from_slice_start(&[0xf4, 0x90, 0x80, 0x80]), Err(s::Codepoint(TooHigh))); + assert_eq!(char::from_utf8_slice_start(&[0xf4, 0x90, 0x80, 0x80]), Err(s::Codepoint(TooHigh))); + + assert_eq!(Utf8Char::from_array([0xf5, 0x88, 0x99, 0xaa]), Err(a::Codepoint(TooHigh))); + assert_eq!(char::from_utf8_array([0xf5, 0xaa, 0xbb, 0x88]), Err(a::Codepoint(TooHigh))); + assert_eq!(Utf8Char::from_slice_start(&[0xf5, 0x99, 0xaa, 0xbb]), Err(s::Codepoint(TooHigh))); + assert_eq!(char::from_utf8_slice_start(&[0xf5, 0xbb, 0x88, 0x99]), Err(s::Codepoint(TooHigh))); +} + +#[test] fn utf8_codepoint_is_utf16_reserved() { + assert_eq!(Utf8Char::from_array([0xed, 0xa0, 0x80, 0xff]), Err(a::Codepoint(Utf16Reserved))); + assert_eq!(char::from_utf8_array([0xed, 0xa0, 0x8f, 0x00]), Err(a::Codepoint(Utf16Reserved))); + assert_eq!(Utf8Char::from_slice_start(&[0xed, 0xa0, 0xbe, 0xa5]), Err(s::Codepoint(Utf16Reserved))); + assert_eq!(char::from_utf8_slice_start(&[0xed, 0xa0, 0xbf]), Err(s::Codepoint(Utf16Reserved))); + assert_eq!(Utf8Char::from_array([0xed, 0xbf, 0x80, 0xff]), Err(a::Codepoint(Utf16Reserved))); + assert_eq!(char::from_utf8_array([0xed, 0xbf, 0x8f, 0x00]), Err(a::Codepoint(Utf16Reserved))); + assert_eq!(Utf8Char::from_slice_start(&[0xed, 0xbf, 0xbe, 0xa5]), Err(s::Codepoint(Utf16Reserved))); + assert_eq!(char::from_utf8_slice_start(&[0xed, 0xbf, 0xbf]), Err(s::Codepoint(Utf16Reserved))); +} + +#[test] fn utf8_first_is_continuation_byte() { + for first in 0x80..0xc0 { + let arr = [first, first<<2, first<<4, first<<6]; + assert_eq!(Utf8Char::from_array(arr), Err(a::Utf8(FirstByte(ContinuationByte)))); + assert_eq!(char::from_utf8_array(arr), Err(a::Utf8(FirstByte(ContinuationByte)))); + let len = (1 + first%3) as usize; + assert_eq!(Utf8Char::from_slice_start(&arr[..len]), Err(s::Utf8(FirstByte(ContinuationByte)))); + assert_eq!(char::from_utf8_slice_start(&arr[..len]), Err(s::Utf8(FirstByte(ContinuationByte)))); + } +} + +#[test] fn utf8_too_long() { + for first in 0xf8..0x100 { + let arr = [first as u8, 0x88, 0x80, 0x80]; + assert_eq!(Utf8Char::from_array(arr), Err(a::Utf8(FirstByte(TooLongSeqence)))); + assert_eq!(char::from_utf8_array(arr), Err(a::Utf8(FirstByte(TooLongSeqence)))); + let arr = [first as u8, 0x88, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80]; + let slice = &arr[..if first&1 == 0 {1} else {8}]; + assert_eq!(Utf8Char::from_slice_start(slice), Err(s::Utf8(FirstByte(TooLongSeqence)))); + assert_eq!(char::from_utf8_slice_start(slice), Err(s::Utf8(FirstByte(TooLongSeqence)))); + } +} + +#[test] fn utf8_not_continuation_byte() { + for first in 0xc2..0xf4 { + let mut arr = [first, 0x90, 0xa0, 0xb0]; + let extra = first.extra_utf8_bytes().unwrap(); + for corrupt in (1..extra).rev() { + let expected = NotAContinuationByte(corrupt); + for &bad in &[0x00, 0x3f, 0x40, 0x7f, 0xc0, 0xff] { + arr[corrupt] = bad; + assert_eq!(Utf8Char::from_array(arr), Err(a::Utf8(expected)), "{:?}", arr); + assert_eq!(char::from_utf8_array(arr), Err(a::Utf8(expected))); + let slice = if first&1 == 0 {&arr[..1+extra]} else {&arr}; + assert_eq!(Utf8Char::from_slice_start(slice), Err(s::Utf8(expected)), "{:?}", slice); + assert_eq!(char::from_utf8_slice_start(slice), Err(s::Utf8(expected))); + } + } + } +} diff --git a/vendor/encode_unicode/tests/exhaustive.rs b/vendor/encode_unicode/tests/exhaustive.rs new file mode 100644 index 0000000..ce60c6b --- /dev/null +++ b/vendor/encode_unicode/tests/exhaustive.rs @@ -0,0 +1,34 @@ +/* Copyright 2018 The encode_unicode Developers + * + * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or + * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or + * http://opensource.org/licenses/MIT>, at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Tests that try all possible values for at least one parameter / byte / unit +//! of the tested function. + +use std::char; +extern crate encode_unicode; +use encode_unicode::*; + +#[test] +fn from_ascii() { + for cp in 0u32..256 { + assert_eq!(Utf8Char::from_ascii(cp as u8).is_ok(), cp & 0x80 == 0); + if let Ok(u8c) = Utf8Char::from_ascii(cp as u8) { + assert_eq!(u8c, Utf8Char::from(cp as u8 as char)); + } + } +} + +#[test] +fn from_bmp() { + for cp in 0u32..0x1_00_00 { + assert_eq!( + Utf16Char::from_bmp(cp as u16).ok(), + char::from_u32(cp).map(|u32c| Utf16Char::from(u32c) ) + ); + } +} diff --git a/vendor/encode_unicode/tests/iterators.rs b/vendor/encode_unicode/tests/iterators.rs new file mode 100644 index 0000000..2a4c006 --- /dev/null +++ b/vendor/encode_unicode/tests/iterators.rs @@ -0,0 +1,182 @@ +/* Copyright 2018 The encode_unicode Developers + * + * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or + * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or + * http://opensource.org/licenses/MIT>, at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Iterator tests + +#![cfg(feature="std")] + +extern crate encode_unicode; + +use encode_unicode::{IterExt, SliceExt, CharExt}; +use encode_unicode::iterator::Utf8CharSplitter; +use encode_unicode::error::InvalidUtf8Slice::*; +use encode_unicode::error::InvalidUtf8::*; +use encode_unicode::error::InvalidUtf8FirstByte::*; +use encode_unicode::error::InvalidCodepoint::*; +use encode_unicode::error::Utf16PairError::*; +use std::io::Read; +use std::cmp::min; + +#[test] fn utf8charmerger() { + let slice = b"\xf0\xa1\x92X\xcc\xbb"; + let mut iter = slice.iter().to_utf8chars(); + assert_eq!(iter.size_hint(), (1, Some(6))); + assert_eq!(format!("{:?}", &iter), + format!("Utf8CharMerger {{ buffered: [], inner: {:?} }}", slice.iter())); + + assert_eq!(iter.next(), Some(Err(Utf8(NotAContinuationByte(3))))); + assert_eq!(iter.size_hint(), (0, Some(5))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf8CharMerger {{ buffered: [161, 146, 88], inner: {:?} }}", slice[4..].iter()) + ); + + assert_eq!(iter.next(), Some(Err(Utf8(FirstByte(ContinuationByte))))); + assert_eq!(iter.into_inner().next(), Some(&b'\xcc')); +} + +#[test] fn utf8chardecoder() { + let slice = b"\xf4\xbf\x80\x80XY\xcc\xbbZ_"; + let mut iter = slice.utf8char_indices(); + assert_eq!(iter.size_hint(), (2, Some(10))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf8CharDecoder {{ bytes[0..]: {:?} }}", &slice) + ); + + assert_eq!(iter.next(), Some((0, Err(Codepoint(TooHigh)), 1))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf8CharDecoder {{ bytes[1..]: {:?} }}", &slice[1..]) + ); + assert_eq!(iter.size_hint(), (2, Some(9))); + assert_eq!(iter.count(), 8); +} + +#[test] fn utf16charmerger() { + let slice = [0xd800, 'x' as u16, 0xd900, 0xdfff, 'λ' as u16]; + let mut iter = slice.iter().to_utf16chars(); + assert_eq!(iter.size_hint(), (2, Some(5))); + assert_eq!(format!("{:?}", &iter), + format!("Utf16CharMerger {{ buffered: None, inner: {:?} }}", slice.iter())); + + assert_eq!(iter.next(), Some(Err(UnmatchedLeadingSurrogate))); + assert_eq!(iter.size_hint(), (1, Some(4))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf16CharMerger {{ buffered: Some(120), inner: {:?} }}", slice[2..].iter()) + ); + + assert_eq!(iter.into_inner().next(), Some(&0xd900)); +} + +#[test] fn utf16chardecoder() { + let slice = [0xd800, 'x' as u16, 0xd900, 0xdfff, 'λ' as u16]; + let mut iter = slice.utf16char_indices(); + assert_eq!(iter.size_hint(), (2, Some(5))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf16CharDecoder {{ units[0..]: {:?} }}", &slice) + ); + + assert_eq!(iter.next(), Some((0, Err(UnmatchedLeadingSurrogate), 1))); + assert_eq!( + format!("{:?}", &iter), + format!("Utf16CharDecoder {{ units[1..]: {:?} }}", &slice[1..]) + ); + assert_eq!(iter.size_hint(), (2, Some(4))); + assert_eq!(iter.count(), 3); +} + + + +/// Tests for ensuring that iterators which also implement Read support +/// interleaving calls of `read()` and `next()`, and that they implement Read +/// correctly (support any buffer size at any time). + +#[test] fn read_single_ascii() { + let uc = 'a'.to_utf8(); + assert_eq!(uc.len(), 1); + for chunk in 1..5 { + let mut buf = [b'E'; 6]; + let mut iter = uc.into_iter(); + let mut written = 0; + for _ in 0..4 { + assert_eq!(iter.read(&mut buf[..0]).unwrap(), 0); + let wrote = iter.read(&mut buf[written..written+chunk]).unwrap(); + assert_eq!(wrote, min(1-written, chunk)); + written += wrote; + for &b in &buf[written..] {assert_eq!(b, b'E');} + assert_eq!(buf[..written], AsRef::<[u8]>::as_ref(&uc)[..written]); + } + assert_eq!(written, 1); + } +} + +#[test] fn read_single_nonascii() { + let uc = 'ä'.to_utf8(); + assert_eq!(uc.len(), 2); + for chunk in 1..5 { + let mut buf = [b'E'; 6]; + let mut iter = uc.into_iter(); + let mut written = 0; + for _ in 0..4 { + assert_eq!(iter.read(&mut buf[..0]).unwrap(), 0); + let wrote = iter.read(&mut buf[written..written+chunk]).unwrap(); + assert_eq!(wrote, min(2-written, chunk)); + written += wrote; + for &b in &buf[written..] {assert_eq!(b, b'E');} + assert_eq!(buf[..written], AsRef::<[u8]>::as_ref(&uc)[..written]); + } + assert_eq!(written, 2); + } +} + + +#[test] fn utf8charsplitter_read_all_sizes() { + let s = "1111\u{104444}\u{222}1\u{833}1111\u{100004}"; + assert!(s.len()%3 == 1); + let mut buf = vec![b'E'; s.len()+6]; + for size in 2..6 {//s.len()+4 { + let mut reader = Utf8CharSplitter::from(s.chars().map(|c| c.to_utf8() )); + for (offset, part) in s.as_bytes().chunks(size).enumerate() { + let read_to = if part.len() == size {(offset+1)*size} else {buf.len()}; + assert_eq!(reader.read(&mut buf[offset*size..read_to]).unwrap(), part.len()); + assert_eq!(&buf[..offset*size+part.len()], &s.as_bytes()[..offset*size+part.len()]); + } + assert_eq!(reader.read(&mut buf[..]).unwrap(), 0); + assert!(buf[s.len()..].iter().all(|&b| b==b'E' )); + } +} + +#[test] fn utf8charsplitter_alternate_iter_read() { + let s = "1111\u{104444}\u{222}1\u{833}1111\u{100004}"; + let mut buf = [b'0'; 10]; + for n in 0..2 { + // need to collect to test size_hint() + // because chars().size_hint() returns ((bytes+3)/4, Some(bytes)) + let u8chars = s.chars().map(|c| c.to_utf8() ).collect::<Vec<_>>(); + let mut iter: Utf8CharSplitter<_,_> = u8chars.into_iter().into(); + for (i, byte) in s.bytes().enumerate() { + let until_next = s.as_bytes()[i..].iter().take_while(|&b| (b>>6)==0b10u8 ).count(); + let remaining_chars = s[i+until_next..].chars().count(); + println!("{}. run: byte {:02} of {}, remaining: {:02}+{}: 0b{:08b} = {:?}", + n, i, s.len(), remaining_chars, until_next, byte, byte as char); + assert_eq!(iter.read(&mut[][..]).unwrap(), 0); + if i % 2 == n { + assert_eq!(iter.next(), Some(byte)); + } else { + assert_eq!(iter.read(&mut buf[..1]).unwrap(), 1); + assert_eq!(buf[0], byte); + } + } + assert_eq!(iter.size_hint(), (0, Some(0))); + assert_eq!(iter.next(), None); + assert_eq!(iter.read(&mut buf[..]).unwrap(), 0); + } +} diff --git a/vendor/encode_unicode/tests/oks.rs b/vendor/encode_unicode/tests/oks.rs new file mode 100644 index 0000000..8bab37f --- /dev/null +++ b/vendor/encode_unicode/tests/oks.rs @@ -0,0 +1,284 @@ +/* Copyright 2016 The encode_unicode Developers + * + * Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or + * http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or + * http://opensource.org/licenses/MIT>, at your option. This file may not be + * copied, modified, or distributed except according to those terms. + */ + +//! Test that every method gives the correct result for valid values. +//! Except iterators, which are stateful. + +use std::char; +use std::str::{self,FromStr}; +use std::cmp::Ordering; +use std::hash::{Hash,Hasher}; +use std::collections::hash_map::DefaultHasher; +#[allow(deprecated,unused)] +use std::ascii::AsciiExt; +use std::iter::FromIterator; +extern crate encode_unicode; +use encode_unicode::*; + + +#[test] +fn equal_defaults() { + assert_eq!(Utf8Char::default().to_char(), char::default()); + assert_eq!(Utf16Char::default().to_char(), char::default()); +} + +#[test] +fn same_size_as_char() { + use std::mem::size_of; + assert_eq!(size_of::<Utf8Char>(), size_of::<char>()); + assert_eq!(size_of::<Utf16Char>(), size_of::<char>()); +} + +#[test] +fn utf16chars_to_string() { + let s = "aå\u{10ffff}‽\u{100000}\u{fee1}"; + let u16cs = s.chars().map(|c| Utf16Char::from(c) ).collect::<Vec<Utf16Char>>(); + + let mut from_refs: String = u16cs.iter().collect(); + assert_eq!(&from_refs, s); + from_refs.extend(&u16cs); + assert_eq!(&from_refs[s.len()..], s); + + let mut from_vals: String = u16cs.iter().cloned().collect(); + assert_eq!(&from_vals, s); + from_vals.extend(u16cs); + assert_eq!(&from_vals[s.len()..], s); +} + + +const EDGES_AND_BETWEEN: [char;19] = [ + '\u{0}',// min + '\u{3b}',// middle ASCII + 'A',// min ASCII uppercase + 'N',// middle ASCII uppercase + 'Z',// max ASCII uppercase + 'a',// min ASCII lowercase + 'm',// middle ASCII lowercase + 'z',// max ASCII lowercase + '\u{7f}',// max ASCII and 1-byte UTF-8 + '\u{80}',// min 2-byte UTF-8 + '\u{111}',// middle + '\u{7ff}',// max 2-byte UTF-8 + '\u{800}',// min 3-byte UTF-8 + '\u{d7ff}',// before reserved + '\u{e000}',// after reserved + '\u{ffff}',// max UTF-16 single and 3-byte UTF-8 + '\u{10000}',// min UTF-16 surrogate and 4-byte UTF-8 + '\u{abcde}',// middle + '\u{10ffff}',// max +]; + +fn eq_cmp_hash(c: char) -> (Utf8Char, Utf16Char) { + fn hash<T:Hash>(v: T) -> u64 { + #[allow(deprecated)] + let mut hasher = DefaultHasher::new(); + v.hash(&mut hasher); + hasher.finish() + } + let u8c = c.to_utf8(); + assert_eq!(u8c.to_char(), c); + assert_eq!(u8c, u8c); + assert_eq!(hash(u8c), hash(u8c)); + assert_eq!(u8c.cmp(&u8c), Ordering::Equal); + assert!(u8c.eq_ignore_ascii_case(&u8c)); + let u16c = c.to_utf16(); + assert_eq!(u16c.to_char(), c); + assert_eq!(u16c, u16c); + assert_eq!(hash(u16c), hash(c)); + assert_eq!(u16c.cmp(&u16c), Ordering::Equal); + assert!(u16c.eq_ignore_ascii_case(&u16c)); + + assert_eq!(u8c, c); + assert_eq!(c, u8c); + assert_eq!(u16c, c); + assert_eq!(c, u16c); + assert_eq!(u8c, u16c); + assert_eq!(u16c, u8c); + assert_eq!(u8c == c as u8, c <= '\u{7F}'); + assert_eq!(u16c == c as u8, c <= '\u{FF}'); + assert_eq!(u16c == c as u16, c <= '\u{FFFF}'); + + assert_eq!(u8c.partial_cmp(&c), Some(Ordering::Equal)); + assert_eq!(c.partial_cmp(&u8c), Some(Ordering::Equal)); + assert_eq!(u16c.partial_cmp(&c), Some(Ordering::Equal)); + assert_eq!(c.partial_cmp(&u16c), Some(Ordering::Equal)); + assert_eq!(u8c.partial_cmp(&u16c), Some(Ordering::Equal)); + assert_eq!(u16c.partial_cmp(&u8c), Some(Ordering::Equal)); + + + for &other in &EDGES_AND_BETWEEN { + let u8other = other.to_utf8(); + assert_eq!(u8c == u8other, c == other); + assert_eq!(hash(u8c)==hash(u8other), hash(c)==hash(other)); + assert_eq!(u8c.cmp(&u8other), c.cmp(&other)); + assert_eq!(u8c.eq_ignore_ascii_case(&u8other), c.eq_ignore_ascii_case(&other)); + assert_eq!(u8c.partial_cmp(&other), c.partial_cmp(&other)); + assert_eq!(c.partial_cmp(&u8other), c.partial_cmp(&other)); + assert_eq!(u8other.partial_cmp(&c), other.partial_cmp(&c)); + assert_eq!(other.partial_cmp(&u8c), other.partial_cmp(&c)); + assert_eq!(u8c == other as u8, other as u8 <= 127 && c == other as u8 as char); + + let u16other = other.to_utf16(); + assert_eq!(u16c == u16other, c == other); + assert_eq!(hash(u16c)==hash(u16other), hash(c)==hash(other)); + assert_eq!(u16c.cmp(&u16other), c.cmp(&other)); + assert_eq!(u16c.eq_ignore_ascii_case(&u16other), c.eq_ignore_ascii_case(&other)); + assert_eq!(u16c.partial_cmp(&other), c.partial_cmp(&other)); + assert_eq!(c.partial_cmp(&u16other), c.partial_cmp(&other)); + assert_eq!(u16other.partial_cmp(&c), other.partial_cmp(&c)); + assert_eq!(other.partial_cmp(&u16c), other.partial_cmp(&c)); + assert_eq!(u16c == other as u8, c == other as u8 as char); + assert_eq!(u16c == other as u16, c as u32 == other as u16 as u32); + + assert_eq!(u8c == u16other, c == other); + assert_eq!(u16c == u8other, c == other); + assert_eq!(u8c.partial_cmp(&u16other), c.partial_cmp(&other)); + assert_eq!(u16c.partial_cmp(&u8other), c.partial_cmp(&other)); + assert_eq!(u8other.partial_cmp(&u16c), other.partial_cmp(&c)); + assert_eq!(u16other.partial_cmp(&u8c), other.partial_cmp(&c)); + } + (u8c, u16c) +} + +fn iterators(c: char) { + let mut iter = c.iter_utf8_bytes(); + let mut buf = [0; 4]; + let mut iter_ref = c.encode_utf8(&mut buf[..]).as_bytes().iter(); + for _ in 0..6 { + assert_eq!(iter.size_hint(), iter_ref.size_hint()); + assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice())); + assert_eq!(iter.next(), iter_ref.next().cloned()); + } + + let mut iter = c.iter_utf16_units(); + let mut buf = [0; 2]; + let mut iter_ref = c.encode_utf16(&mut buf[..]).iter(); + for _ in 0..4 { + assert_eq!(iter.size_hint(), iter_ref.size_hint()); + assert_eq!(format!("{:?}", iter), format!("{:?}", iter_ref.as_slice())); + assert_eq!(iter.next(), iter_ref.next().cloned()); + } +} + +fn test(c: char) { + assert_eq!(char::from_u32(c as u32), Some(c)); + assert_eq!(char::from_u32_detailed(c as u32), Ok(c)); + assert_eq!(unsafe{ char::from_u32_unchecked(c as u32) }, c); + let (u8c, u16c) = eq_cmp_hash(c); + iterators(c); + assert_eq!(Utf16Char::from(u8c), u16c); + assert_eq!(Utf8Char::from(u16c), u8c); + let utf8_len = c.len_utf8(); + let utf16_len = c.len_utf16(); + let mut as_str = c.to_string(); + + // UTF-8 + let mut buf = [0; 4]; + let reference = c.encode_utf8(&mut buf[..]).as_bytes(); + let len = reference.len(); // short name because it is used in many places. + assert_eq!(len, utf8_len); + assert_eq!(reference[0].extra_utf8_bytes(), Ok(len-1)); + assert_eq!(reference[0].extra_utf8_bytes_unchecked(), len-1); + assert_eq!(AsRef::<[u8]>::as_ref(&u8c), reference); + + let (arr,arrlen) = u8c.to_array(); + assert_eq!(arrlen, len); + assert_eq!(Utf8Char::from_array(arr), Ok(u8c)); + assert_eq!(c.to_utf8_array(), (arr, len)); + + let str_ = str::from_utf8(reference).unwrap(); + let ustr = Utf8Char::from_str(str_).unwrap(); + assert_eq!(ustr.to_array().0, arr);// bitwise equality + assert_eq!(char::from_utf8_array(arr), Ok(c)); + let mut longer = [0xff; 5]; // 0xff is never valid + longer[..len].copy_from_slice(reference); + assert_eq!(char::from_utf8_slice_start(reference), Ok((c,len))); + assert_eq!(char::from_utf8_slice_start(&longer), Ok((c,len))); + assert_eq!(Utf8Char::from_slice_start(reference), Ok((u8c,len))); + assert_eq!(Utf8Char::from_slice_start(&longer), Ok((u8c,len))); + for other in &mut longer[len..] {*other = b'?'} + assert_eq!(Utf8Char::from_str(str_), Ok(u8c)); + assert_eq!(Utf8Char::from_str_start(str_), Ok((u8c,len))); + assert_eq!(Utf8Char::from_str_start(str::from_utf8(&longer).unwrap()), Ok((u8c,len))); + unsafe { + // Hopefully make bugs easier to catch by making reads into unallocated memory by filling + // a jemalloc bin. See table on http://jemalloc.net/jemalloc.3.html for bin sizes. + // I have no idea whether this works. + let mut boxed = Box::new([0xffu8; 16]); + let start = boxed.len()-len; // reach the end + boxed[start..].copy_from_slice(reference); + let slice = &boxed[start..start]; // length of slice should be ignored. + assert_eq!(Utf8Char::from_slice_start_unchecked(slice), (u8c,len)); + } + assert_eq!(&Vec::<u8>::from_iter(Some(u8c))[..], reference); + assert_eq!(&String::from_iter(Some(u8c))[..], str_); + assert_eq!(format!("{:?}", u8c), format!("{:?}", c)); + assert_eq!(format!("{}", u8c), format!("{}", c)); + assert_eq!(u8c.is_ascii(), c.is_ascii()); + assert_eq!(u8c.to_ascii_lowercase().to_char(), c.to_ascii_lowercase()); + assert_eq!(u8c.to_ascii_uppercase().to_char(), c.to_ascii_uppercase()); + + // UTF-16 + let mut buf = [0; 2]; + let reference = c.encode_utf16(&mut buf[..]); + let len = reference.len(); + assert_eq!(len, utf16_len); + assert_eq!(reference[0].utf16_needs_extra_unit(), Ok(len==2)); + assert_eq!(reference[0].is_utf16_leading_surrogate(), len==2); + assert_eq!(u16c.as_ref(), reference); + let mut longer = [0; 3]; + longer[..len].copy_from_slice(reference); + assert_eq!(char::from_utf16_slice_start(reference), Ok((c,len))); + assert_eq!(char::from_utf16_slice_start(&longer), Ok((c,len))); + assert_eq!(Utf16Char::from_slice_start(reference), Ok((u16c,len))); + assert_eq!(Utf16Char::from_slice_start(&longer), Ok((u16c,len))); + assert_eq!(Utf16Char::from_str(&as_str), Ok(u16c)); + as_str.push(c); + assert_eq!(Utf16Char::from_str_start(&as_str), Ok((u16c,utf8_len))); + unsafe { + // Hopefully make bugs easier to catch by making reads into unallocated memory by filling + // a jemalloc bin. See table on http://jemalloc.net/jemalloc.3.html for bin sizes. + // I have no idea whether this works. + let mut boxed = Box::new([0u16; 8]); + let start = boxed.len()-len; // reach the end + boxed[start..].copy_from_slice(reference); + let slice = &boxed[start..start]; // length of slice should be ignored. + assert_eq!(Utf16Char::from_slice_start_unchecked(slice), (u16c,len)); + } + let array = c.to_utf16_array(); + let tuple = c.to_utf16_tuple(); + assert_eq!(&array[..reference.len()], reference); + assert_eq!(tuple, (reference[0],reference.get(1).cloned())); + assert_eq!(char::from_utf16_array(array), Ok(c)); + assert_eq!(char::from_utf16_tuple(tuple), Ok(c)); + assert_eq!(c.to_utf16().to_char(), c); + assert_eq!(&Vec::<u16>::from_iter(Some(u16c))[..], reference); + assert_eq!(format!("{:?}", u16c), format!("{:?}", c)); + assert_eq!(format!("{}", u16c), format!("{}", c)); + assert_eq!(u16c.is_ascii(), c.is_ascii()); + assert_eq!(u16c.to_ascii_lowercase().to_char(), c.to_ascii_lowercase()); + assert_eq!(u16c.to_ascii_uppercase().to_char(), c.to_ascii_uppercase()); +} + + +#[test] +fn edges_middle() { + for &c in &EDGES_AND_BETWEEN { + test(c); + } +} + + +#[test] +#[ignore] +fn all() { + for cp in std::iter::Iterator::chain(0..0xd800, 0xe000..0x110000) { + let c = char::from_u32(cp).expect("not a valid char"); + test(c); + } +} |