Update tests

This commit is contained in:
Vlasislav Kashin
2025-07-13 17:30:47 +03:00
parent 03911c0572
commit 923a941473
2 changed files with 398 additions and 9 deletions

View File

@@ -259,7 +259,7 @@ impl PhoneNumberUtil {
.full_match(national_prefix_formatting_rule); .full_match(national_prefix_formatting_rule);
} }
pub fn get_ndd_prefix_for_region(&self, region_code: &str, strip_non_digits: bool) -> String { pub fn get_ndd_prefix_for_region(&self, region_code: &str, strip_non_digits: bool) -> Option<String> {
self.region_to_metadata_map self.region_to_metadata_map
.get(region_code) .get(region_code)
.map(|metadata| { .map(|metadata| {
@@ -269,10 +269,6 @@ impl PhoneNumberUtil {
} }
prefix prefix
}) })
.unwrap_or_else(|| {
warn!("Invalid or unknown region code ({}) provided.", region_code);
"".to_string()
})
} }
/// 'hot' function wrapper for region_to_metadata_map.get /// 'hot' function wrapper for region_to_metadata_map.get
@@ -1185,11 +1181,10 @@ impl PhoneNumberUtil {
self.get_region_code_for_country_code(phone_number.country_code()); self.get_region_code_for_country_code(phone_number.country_code());
// We strip non-digits from the NDD here, and from the raw input later, so // We strip non-digits from the NDD here, and from the raw input later, so
// that we can compare them easily. // that we can compare them easily.
let national_prefix = let Some(national_prefix) =
self.get_ndd_prefix_for_region(region_code, true /* strip non-digits */); self.get_ndd_prefix_for_region(region_code, true /* strip non-digits */) else {
if national_prefix.is_empty() {
break 'default_block format_national()?; break 'default_block format_national()?;
} };
let Some(metadata) = self.region_to_metadata_map.get(region_code) else { let Some(metadata) = self.region_to_metadata_map.get(region_code) else {
// If the region doesn't have a national prefix at all, we can safely // If the region doesn't have a national prefix at all, we can safely
// return the national format without worrying about a national prefix // return the national format without worrying about a national prefix

View File

@@ -1076,6 +1076,88 @@ fn format_in_original_format() {
assert_eq!("650253000", formatted_number); assert_eq!("650253000", formatted_number);
} }
#[test]
fn get_national_dialling_prefix_for_region() {
let phone_util = get_phone_util();
// Для США префикс "1".
let ndd_prefix = phone_util.get_ndd_prefix_for_region("US", false).unwrap();
assert_eq!("1", ndd_prefix);
// Тестируем страну, не являющуюся основной, чтобы увидеть, что она получает
// национальный префикс набора для основной страны с этим кодом страны.
let ndd_prefix = phone_util.get_ndd_prefix_for_region("BS", false).unwrap();
assert_eq!("1", ndd_prefix);
// Для Новой Зеландии префикс "0".
let ndd_prefix = phone_util.get_ndd_prefix_for_region("NZ", false).unwrap();
assert_eq!("0", ndd_prefix);
// Тестируем случай с нецифровым символом в национальном префиксе.
let ndd_prefix = phone_util.get_ndd_prefix_for_region("AO", false).unwrap();
assert_eq!("0~0", ndd_prefix);
// Тестируем с удалением нецифровых символов.
let ndd_prefix = phone_util.get_ndd_prefix_for_region("AO", true).unwrap();
assert_eq!("00", ndd_prefix);
// Тестируем случаи с невалидными регионами.
assert!(phone_util.get_ndd_prefix_for_region("ZZ", false).is_none());
assert!(phone_util.get_ndd_prefix_for_region("UN001", false).is_none());
// CS уже устарел, поэтому библиотека его не поддерживает.
assert!(phone_util.get_ndd_prefix_for_region("CS", false).is_none());
}
#[test]
fn is_viable_phone_number() {
let phone_util = get_phone_util();
assert!(!phone_util.is_viable_phone_number("1"));
// Только одна или две цифры перед странной недопустимой пунктуацией.
assert!(!phone_util.is_viable_phone_number("1+1+1"));
assert!(!phone_util.is_viable_phone_number("80+0"));
// Две цифры являются жизнеспособным номером.
assert!(phone_util.is_viable_phone_number("00"));
assert!(phone_util.is_viable_phone_number("111"));
// Буквенно-цифровые номера.
assert!(phone_util.is_viable_phone_number("0800-4-pizza"));
assert!(phone_util.is_viable_phone_number("0800-4-PIZZA"));
// Нам нужно как минимум три цифры перед любыми буквенными символами.
assert!(!phone_util.is_viable_phone_number("08-PIZZA"));
assert!(!phone_util.is_viable_phone_number("8-PIZZA"));
assert!(!phone_util.is_viable_phone_number("12. March"));
}
#[test]
fn is_viable_phone_number_non_ascii() {
let phone_util = get_phone_util();
// Только одна или две цифры перед возможной пунктуацией, за которой следуют еще цифры.
// Используемый здесь знак препинания — это символ юникода u+3000.
assert!(phone_util.is_viable_phone_number("1 34"));
assert!(!phone_util.is_viable_phone_number("1 3+4"));
// Юникодные варианты возможного начального символа и другой разрешенной пунктуации/цифр.
assert!(phone_util.is_viable_phone_number("1 3456789"));
// Проверяем, что ведущий + разрешен.
assert!(phone_util.is_viable_phone_number("+1 3456789"));
}
#[test]
fn convert_alpha_characters_in_number() {
let phone_util = get_phone_util();
let input = "1800-ABC-DEF".to_string();
let result = phone_util.convert_alpha_characters_in_number(&input);
// Буквенные символы преобразуются в цифры; все остальное остается без изменений.
assert_eq!("1800-222-333", result);
// Пробуем с некоторыми не-ASCII символами.
let input = "1 800) ABC-DEF".to_string();
let expected_fullwidth_output = "1 800) 222-333";
let result = phone_util.convert_alpha_characters_in_number(&input);
assert_eq!(expected_fullwidth_output, result);
}
#[test] #[test]
fn parse_and_keep_raw() { fn parse_and_keep_raw() {
let phone_util = get_phone_util(); let phone_util = get_phone_util();
@@ -2103,6 +2185,108 @@ fn normalise_strip_alpha_characters() {
assert_eq!(expected_output, normalized_number, "Conversion did not correctly remove alpha characters"); assert_eq!(expected_output, normalized_number, "Conversion did not correctly remove alpha characters");
} }
#[test]
fn normalise_strip_non_diallable_characters() {
let phone_util = get_phone_util();
let input_number = "03*4-56&+1a#234";
let expected_output = "03*456+1#234";
assert_eq!(
expected_output,
phone_util.normalize_diallable_chars_only(&input_number),
"Conversion did not correctly remove non-diallable characters"
);
}
#[test]
fn maybe_strip_international_prefix() {
let phone_util = get_phone_util();
let international_prefix = "00[39]";
let number_to_strip = "0034567700-3898003";
// Примечание: дефис удаляется в процессе нормализации.
let stripped_number = "45677003898003";
let number_with_source = phone_util
.maybe_strip_international_prefix_and_normalize(number_to_strip, international_prefix)
.unwrap();
assert_eq!(
CountryCodeSource::FROM_NUMBER_WITH_IDD,
number_with_source.country_code_source
);
assert_eq!(stripped_number, number_with_source.phone_number, "The number was not stripped of its international prefix.");
// Теперь номер больше не начинается с префикса IDD, поэтому он должен сообщать
// FROM_DEFAULT_COUNTRY.
assert_eq!(
CountryCodeSource::FROM_DEFAULT_COUNTRY,
phone_util.maybe_strip_international_prefix_and_normalize(&number_with_source.phone_number, international_prefix)
.unwrap()
.country_code_source
);
let number_to_strip = "00945677003898003";
let number_with_source = phone_util
.maybe_strip_international_prefix_and_normalize(number_to_strip, international_prefix)
.unwrap();
assert_eq!(
CountryCodeSource::FROM_NUMBER_WITH_IDD,
number_with_source.country_code_source
);
assert_eq!(stripped_number, number_with_source.phone_number, "The number was not stripped of its international prefix.");
// Проверяем, что это работает, когда международный префикс разбит пробелами.
let number_to_strip = "00 9 45677003898003";
let number_with_source = phone_util
.maybe_strip_international_prefix_and_normalize(number_to_strip, international_prefix)
.unwrap();
assert_eq!(
CountryCodeSource::FROM_NUMBER_WITH_IDD,
number_with_source.country_code_source
);
assert_eq!(stripped_number, number_with_source.phone_number, "The number was not stripped of its international prefix.");
// Теперь номер больше не начинается с префикса IDD, поэтому он должен сообщать
// FROM_DEFAULT_COUNTRY.
assert_eq!(
CountryCodeSource::FROM_DEFAULT_COUNTRY,
phone_util.maybe_strip_international_prefix_and_normalize(&number_with_source.phone_number, international_prefix)
.unwrap()
.country_code_source
);
// Проверяем, что символ + также распознается и удаляется.
let number_to_strip = "+45677003898003";
let stripped_number_plus = "45677003898003";
let number_with_source = phone_util
.maybe_strip_international_prefix_and_normalize(number_to_strip, international_prefix)
.unwrap();
assert_eq!(
CountryCodeSource::FROM_NUMBER_WITH_PLUS_SIGN,
number_with_source.country_code_source
);
assert_eq!(stripped_number_plus, number_with_source.phone_number, "The number supplied was not stripped of the plus symbol.");
// Если после префикса идет ноль, мы не должны его удалять - ни один код страны не начинается с 0.
let number_to_strip = "0090112-3123";
let stripped_number_zero = "00901123123";
let number_with_source = phone_util
.maybe_strip_international_prefix_and_normalize(number_to_strip, international_prefix)
.unwrap();
assert_eq!(
CountryCodeSource::FROM_DEFAULT_COUNTRY,
number_with_source.country_code_source
);
assert_eq!(stripped_number_zero, number_with_source.phone_number, "The number had a 0 after the match so shouldn't be stripped.");
// Здесь 0 отделен от IDD пробелом.
let number_to_strip = "009 0-112-3123";
assert_eq!(
CountryCodeSource::FROM_DEFAULT_COUNTRY,
phone_util.maybe_strip_international_prefix_and_normalize(number_to_strip, international_prefix)
.unwrap()
.country_code_source
);
}
#[test] #[test]
fn maybe_strip_extension() { fn maybe_strip_extension() {
@@ -2289,6 +2473,216 @@ fn parse_national_number() {
assert_eq!(short_number, test_number); assert_eq!(short_number, test_number);
} }
#[test]
fn parse_number_with_alpha_characters() {
let phone_util = get_phone_util();
// Тестовый случай с буквенными символами.
let mut tollfree_number = PhoneNumber::new();
tollfree_number.set_country_code(64);
tollfree_number.set_national_number(800332005);
let mut test_number = phone_util.parse("0800 DDA 005", "NZ").unwrap();
assert_eq!(tollfree_number, test_number);
let mut premium_number = PhoneNumber::new();
premium_number.set_country_code(64);
premium_number.set_national_number(9003326005);
test_number = phone_util.parse("0900 DDA 6005", "NZ").unwrap();
assert_eq!(premium_number, test_number);
// Недостаточно буквенных символов, чтобы считать их преднамеренными, поэтому они удаляются.
test_number = phone_util.parse("0900 332 6005a", "NZ").unwrap();
assert_eq!(premium_number, test_number);
test_number = phone_util.parse("0900 332 600a5", "NZ").unwrap();
assert_eq!(premium_number, test_number);
test_number = phone_util.parse("0900 332 600A5", "NZ").unwrap();
assert_eq!(premium_number, test_number);
test_number = phone_util.parse("0900 a332 600A5", "NZ").unwrap();
assert_eq!(premium_number, test_number);
}
#[test]
fn parse_with_international_prefixes() {
let phone_util = get_phone_util();
let mut us_number = PhoneNumber::new();
us_number.set_country_code(1);
us_number.set_national_number(6503336000);
let mut test_number = phone_util.parse("+1 (650) 333-6000", "US").unwrap();
assert_eq!(us_number, test_number);
test_number = phone_util.parse("+1-650-333-6000", "US").unwrap();
assert_eq!(us_number, test_number);
// Звонок на номер США из Сингапура с использованием разных поставщиков услуг
// 1-й тест: звонок с использованием услуги SingTel IDD (IDD - 001)
test_number = phone_util.parse("0011-650-333-6000", "SG").unwrap();
assert_eq!(us_number, test_number);
// 2-й тест: звонок с использованием услуги StarHub IDD (IDD - 008)
test_number = phone_util.parse("0081-650-333-6000", "SG").unwrap();
assert_eq!(us_number, test_number);
// 3-й тест: звонок с использованием услуги SingTel V019 (IDD - 019)
test_number = phone_util.parse("0191-650-333-6000", "SG").unwrap();
assert_eq!(us_number, test_number);
// Звонок на номер США из Польши
test_number = phone_util.parse("0~01-650-333-6000", "PL").unwrap();
assert_eq!(us_number, test_number);
// Использование "++" в начале.
test_number = phone_util.parse("++1 (650) 333-6000", "PL").unwrap();
assert_eq!(us_number, test_number);
// Использование полноширинного знака плюса.
test_number = phone_util.parse("1 (650) 333-6000", "SG").unwrap();
assert_eq!(us_number, test_number);
// Использование мягкого дефиса U+00AD.
test_number = phone_util.parse("1 (650) 333\u{00AD}-6000", "US").unwrap();
assert_eq!(us_number, test_number);
// Весь номер, включая знаки препинания, представлен в полноширинной форме.
test_number = phone_util.parse("  ", "SG").unwrap();
assert_eq!(us_number, test_number);
// Использование тире U+30FC.
test_number = phone_util.parse("+1 (650) 333ー6000", "SG").unwrap();
assert_eq!(us_number, test_number);
let mut toll_free_number = PhoneNumber::new();
toll_free_number.set_country_code(800);
toll_free_number.set_national_number(12345678);
test_number = phone_util.parse("011 800 1234 5678", "US").unwrap();
assert_eq!(toll_free_number, test_number);
}
#[test]
fn parse_with_leading_zero() {
let phone_util = get_phone_util();
let mut it_number = PhoneNumber::new();
it_number.set_country_code(39);
it_number.set_national_number(236618300);
it_number.set_italian_leading_zero(true);
let mut test_number = phone_util.parse("+39 02-36618 300", "NZ").unwrap();
assert_eq!(it_number, test_number);
test_number = phone_util.parse("02-36618 300", "IT").unwrap();
assert_eq!(it_number, test_number);
it_number.clear();
it_number.set_country_code(39);
it_number.set_national_number(312345678);
test_number = phone_util.parse("312 345 678", "IT").unwrap();
assert_eq!(it_number, test_number);
}
#[test]
fn parse_national_number_argentina() {
let phone_util = get_phone_util();
// Тестирование парсинга мобильных номеров Аргентины.
let mut ar_number = PhoneNumber::new();
ar_number.set_country_code(54);
ar_number.set_national_number(93435551212);
let mut test_number = phone_util.parse("+54 9 343 555 1212", "AR").unwrap();
assert_eq!(ar_number, test_number);
test_number = phone_util.parse("0343 15 555 1212", "AR").unwrap();
assert_eq!(ar_number, test_number);
ar_number.set_national_number(93715654320);
test_number = phone_util.parse("+54 9 3715 65 4320", "AR").unwrap();
assert_eq!(ar_number, test_number);
test_number = phone_util.parse("03715 15 65 4320", "AR").unwrap();
assert_eq!(ar_number, test_number);
// Тестирование парсинга стационарных номеров Аргентины.
ar_number.set_national_number(1137970000);
test_number = phone_util.parse("+54 11 3797 0000", "AR").unwrap();
assert_eq!(ar_number, test_number);
test_number = phone_util.parse("011 3797 0000", "AR").unwrap();
assert_eq!(ar_number, test_number);
ar_number.set_national_number(3715654321);
test_number = phone_util.parse("+54 3715 65 4321", "AR").unwrap();
assert_eq!(ar_number, test_number);
test_number = phone_util.parse("03715 65 4321", "AR").unwrap();
assert_eq!(ar_number, test_number);
ar_number.set_national_number(2312340000);
test_number = phone_util.parse("+54 23 1234 0000", "AR").unwrap();
assert_eq!(ar_number, test_number);
test_number = phone_util.parse("023 1234 0000", "AR").unwrap();
assert_eq!(ar_number, test_number);
}
#[test]
fn parse_with_x_in_number() {
let phone_util = get_phone_util();
// Проверяем, что наличие 'x' в начале номера телефона допустимо и что он просто удаляется.
let mut ar_number = PhoneNumber::new();
ar_number.set_country_code(54);
ar_number.set_national_number(123456789);
let mut test_number = phone_util.parse("0123456789", "AR").unwrap();
assert_eq!(ar_number, test_number);
test_number = phone_util.parse("(0) 123456789", "AR").unwrap();
assert_eq!(ar_number, test_number);
test_number = phone_util.parse("0 123456789", "AR").unwrap();
assert_eq!(ar_number, test_number);
test_number = phone_util.parse("(0xx) 123456789", "AR").unwrap();
assert_eq!(ar_number, test_number);
let mut ar_from_us = PhoneNumber::new();
ar_from_us.set_country_code(54);
ar_from_us.set_national_number(81429712);
// Этот тест намеренно построен так, что количество цифр после xx больше 7,
// чтобы номер не был ошибочно принят за добавочный, так как мы разрешаем
// добавочные номера до 7 цифр. Это предположение на данный момент приемлемо,
// так как все страны, где код выбора оператора записывается в виде xx,
// имеют национальный значащий номер длиной более 7.
test_number = phone_util.parse("011xx5481429712", "US").unwrap();
assert_eq!(ar_from_us, test_number);
}
#[test]
fn parse_numbers_mexico() {
let phone_util = get_phone_util();
// Тестирование парсинга стационарных номеров Мексики.
let mut mx_number = PhoneNumber::new();
mx_number.set_country_code(52);
mx_number.set_national_number(4499780001);
let mut test_number = phone_util.parse("+52 (449)978-0001", "MX").unwrap();
assert_eq!(mx_number, test_number);
test_number = phone_util.parse("01 (449)978-0001", "MX").unwrap();
assert_eq!(mx_number, test_number);
test_number = phone_util.parse("(449)978-0001", "MX").unwrap();
assert_eq!(mx_number, test_number);
// Тестирование парсинга мобильных номеров Мексики.
mx_number.clear();
mx_number.set_country_code(52);
mx_number.set_national_number(13312345678);
test_number = phone_util.parse("+52 1 33 1234-5678", "MX").unwrap();
assert_eq!(mx_number, test_number);
test_number = phone_util.parse("044 (33) 1234-5678", "MX").unwrap();
assert_eq!(mx_number, test_number);
test_number = phone_util.parse("045 33 1234-5678", "MX").unwrap();
assert_eq!(mx_number, test_number);
}
#[test] #[test]
fn parse_with_phone_context() { fn parse_with_phone_context() {
fn assert_throws_for_invalid_phone_context(phone_util: &PhoneNumberUtil, number_to_parse: &str) { fn assert_throws_for_invalid_phone_context(phone_util: &PhoneNumberUtil, number_to_parse: &str) {