| use core::unicode::unicode_data; |
| use std::ops::RangeInclusive; |
| |
| mod test_data; |
| |
| #[test] |
| pub fn version() { |
| let (major, _minor, _update) = core::char::UNICODE_VERSION; |
| assert!(major >= 10); |
| } |
| |
| #[track_caller] |
| fn test_boolean_property(ranges: &[RangeInclusive<char>], lookup: fn(char) -> bool) { |
| let mut start = '\u{80}'; |
| for range in ranges { |
| for c in start..*range.start() { |
| assert!(!lookup(c), "{c:?}"); |
| } |
| for c in range.clone() { |
| assert!(lookup(c), "{c:?}"); |
| } |
| start = char::from_u32(*range.end() as u32 + 1).unwrap(); |
| } |
| for c in start..=char::MAX { |
| assert!(!lookup(c), "{c:?}"); |
| } |
| } |
| |
| #[track_caller] |
| fn test_case_mapping( |
| ranges: &[(char, [char; 3])], |
| lookup: fn(char) -> [char; 3], |
| fallback: fn(char) -> [char; 3], |
| ) { |
| let mut start = '\u{80}'; |
| for &(key, val) in ranges { |
| for c in start..key { |
| assert_eq!(lookup(c), fallback(c), "{c:?}"); |
| } |
| assert_eq!(lookup(key), val, "{key:?}"); |
| start = char::from_u32(key as u32 + 1).unwrap(); |
| } |
| for c in start..=char::MAX { |
| assert_eq!(lookup(c), fallback(c), "{c:?}"); |
| } |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn alphabetic() { |
| test_boolean_property(test_data::ALPHABETIC, unicode_data::alphabetic::lookup); |
| test_boolean_property(test_data::ALPHABETIC, char::is_alphabetic); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn case_ignorable() { |
| test_boolean_property(test_data::CASE_IGNORABLE, unicode_data::case_ignorable::lookup); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn cased() { |
| test_boolean_property(test_data::CASED, unicode_data::cased::lookup); |
| test_boolean_property(test_data::CASED, char::is_cased); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn grapheme_extend() { |
| test_boolean_property(test_data::GRAPHEME_EXTEND, unicode_data::grapheme_extend::lookup); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn lowercase() { |
| test_boolean_property(test_data::LOWERCASE, unicode_data::lowercase::lookup); |
| test_boolean_property(test_data::LOWERCASE, char::is_lowercase); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn n() { |
| test_boolean_property(test_data::N, unicode_data::n::lookup); |
| test_boolean_property(test_data::N, char::is_numeric); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn uppercase() { |
| test_boolean_property(test_data::UPPERCASE, unicode_data::uppercase::lookup); |
| test_boolean_property(test_data::UPPERCASE, char::is_uppercase); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn white_space() { |
| test_boolean_property(test_data::WHITE_SPACE, unicode_data::white_space::lookup); |
| test_boolean_property(test_data::WHITE_SPACE, char::is_whitespace); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn to_lowercase() { |
| test_case_mapping(test_data::TO_LOWER, unicode_data::conversions::to_lower, |c| { |
| [c, '\0', '\0'] |
| }); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn to_uppercase() { |
| test_case_mapping(test_data::TO_UPPER, unicode_data::conversions::to_upper, |c| { |
| [c, '\0', '\0'] |
| }); |
| } |
| |
| #[test] |
| #[cfg_attr(miri, ignore)] // Miri is too slow |
| fn to_titlecase() { |
| test_case_mapping( |
| test_data::TO_TITLE, |
| unicode_data::conversions::to_title, |
| unicode_data::conversions::to_upper, |
| ); |
| } |