| 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, | |
| ); | |
| } |