/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2012,2013 Intel Corporation * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authors: Mathias Hasselmann */ #include "evolution-data-server-config.h" #include #include /* Pick a locale category to set and test. */ #ifdef LC_ADDRESS /* LC_ADDRESS is a GNU extension. */ #define CATEGORY LC_ADDRESS #else /* Mimic the fallback branch in EBookQuery. */ #ifdef G_OS_WIN32 #ifndef LC_MESSAGES #define LC_MESSAGES LC_CTYPE #endif #endif #define CATEGORY LC_MESSAGES #endif /* LC_ADDRESS */ static const gchar *match_candidates[] = { "not-a-number", "+1-617-4663489", "617-4663489", "4663489", "+1.408.845.5246", "4088455246", "8455246", "+1-857-4663489" }; #ifdef ENABLE_PHONENUMBER static const EPhoneNumberMatch expected_matches[] = { /* not a number */ E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, /* +1-617-4663489 */ E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_EXACT, E_PHONE_NUMBER_MATCH_NATIONAL, E_PHONE_NUMBER_MATCH_SHORT, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, /* 617-4663489 */ E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NATIONAL, E_PHONE_NUMBER_MATCH_NATIONAL, E_PHONE_NUMBER_MATCH_SHORT, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, /* 4663489 */ E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_SHORT, E_PHONE_NUMBER_MATCH_SHORT, E_PHONE_NUMBER_MATCH_NATIONAL, /* XXX - Google, really? I'd expect a full match here. */ E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_SHORT, /* +1.408.845.5246 */ E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_EXACT, E_PHONE_NUMBER_MATCH_NATIONAL, E_PHONE_NUMBER_MATCH_SHORT, E_PHONE_NUMBER_MATCH_NONE, /* 4088455246 */ E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NATIONAL, E_PHONE_NUMBER_MATCH_NATIONAL, E_PHONE_NUMBER_MATCH_SHORT, E_PHONE_NUMBER_MATCH_NONE, /* 8455246 */ E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_SHORT, E_PHONE_NUMBER_MATCH_SHORT, E_PHONE_NUMBER_MATCH_NATIONAL, /* XXX - Google, really? I'd expect a full match here. */ E_PHONE_NUMBER_MATCH_NONE, /* +1-857-4663489 */ E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_SHORT, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_NONE, E_PHONE_NUMBER_MATCH_EXACT }; #endif /* ENABLE_PHONENUMBER */ typedef struct { gchar *phone_number; gchar *region_code; EPhoneNumberCountrySource country_source; gint country_code; gchar *national_number; gchar *formatted_numbers[4]; } ParseAndFormatData; static ParseAndFormatData * parse_and_format_data_new (const gchar *phone_number, const gchar *region_code, EPhoneNumberCountrySource country_source, gint country_code, const gchar *national_number, const gchar *formatted_e164, const gchar *formatted_intl, const gchar *formatted_natl, const gchar *formatted_uri) { ParseAndFormatData *test_data = g_slice_new0 (ParseAndFormatData); test_data->phone_number = g_strdup (phone_number); test_data->region_code = g_strdup (region_code); test_data->country_source = country_source; test_data->country_code = country_code; test_data->national_number = g_strdup (national_number); test_data->formatted_numbers[0] = g_strdup (formatted_e164); test_data->formatted_numbers[1] = g_strdup (formatted_intl); test_data->formatted_numbers[2] = g_strdup (formatted_natl); test_data->formatted_numbers[3] = g_strdup (formatted_uri); return test_data; } static void parse_and_format_data_free (gpointer data) { ParseAndFormatData *const test_data = data; g_free (test_data->phone_number); g_free (test_data->region_code); g_free (test_data->national_number); g_free (test_data->formatted_numbers[0]); g_free (test_data->formatted_numbers[1]); g_free (test_data->formatted_numbers[2]); g_free (test_data->formatted_numbers[3]); g_slice_free (ParseAndFormatData, test_data); } static void test_parse_and_format (gconstpointer data) { const ParseAndFormatData *const test_data = data; GError *error = NULL; EPhoneNumber *parsed; parsed = e_phone_number_from_string ( test_data->phone_number, test_data->region_code, &error); #ifdef ENABLE_PHONENUMBER { EPhoneNumberCountrySource source; gchar *national; gint i; g_assert_cmpint ( e_phone_number_get_country_code (parsed, &source), ==, test_data->country_code); g_assert_cmpuint (source, ==, test_data->country_source); national = e_phone_number_get_national_number (parsed); g_assert_cmpstr (national, ==, test_data->national_number); g_free (national); g_assert (parsed != NULL); g_assert (error == NULL); for (i = 0; i < G_N_ELEMENTS (test_data->formatted_numbers); ++i) { gchar *formatted = e_phone_number_to_string (parsed, i); g_assert (formatted != NULL); g_assert_cmpstr (formatted, ==, test_data->formatted_numbers[i]); g_free (formatted); } e_phone_number_free (parsed); } #else /* ENABLE_PHONENUMBER */ g_assert (parsed == NULL); g_assert (error != NULL); g_assert (error->domain == E_PHONE_NUMBER_ERROR); g_assert (error->code == E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED); g_assert (error->message != NULL); #endif /* ENABLE_PHONENUMBER */ g_clear_error (&error); } static void test_parse_bad_number (void) { GError *error = NULL; EPhoneNumber *parsed; parsed = e_phone_number_from_string ("+1-NOT-A-NUMBER", "US", &error); g_assert (parsed == NULL); g_assert (error != NULL); g_assert (error->domain == E_PHONE_NUMBER_ERROR); #ifdef ENABLE_PHONENUMBER g_assert (error->code == E_PHONE_NUMBER_ERROR_NOT_A_NUMBER); #else /* ENABLE_PHONENUMBER */ g_assert (error->code == E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED); #endif /* ENABLE_PHONENUMBER */ g_assert (error->message != NULL); g_clear_error (&error); } static void test_parse_auto_region (void) { GError *error = NULL; EPhoneNumber *parsed; parsed = e_phone_number_from_string ("212-5423789", NULL, &error); #ifdef ENABLE_PHONENUMBER { EPhoneNumberCountrySource source; gchar *national; gchar *formatted; g_assert (parsed != NULL); g_assert (error == NULL); g_assert_cmpint (e_phone_number_get_country_code (parsed, &source), ==, 1); g_assert_cmpuint (source, ==, E_PHONE_NUMBER_COUNTRY_FROM_DEFAULT); national = e_phone_number_get_national_number (parsed); g_assert_cmpstr (national, ==, "2125423789"); g_free (national); formatted = e_phone_number_to_string (parsed, E_PHONE_NUMBER_FORMAT_E164); g_assert_cmpstr (formatted, ==, "+12125423789"); g_free (formatted); e_phone_number_free (parsed); } #else /* ENABLE_PHONENUMBER */ g_assert (parsed == NULL); g_assert (error != NULL); g_assert (error->domain == E_PHONE_NUMBER_ERROR); g_assert (error->code == E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED); g_assert (error->message != NULL); g_clear_error (&error); #endif /* ENABLE_PHONENUMBER */ } static void test_compare_numbers (gconstpointer data) { const size_t n = GPOINTER_TO_UINT (data); const size_t i = n % G_N_ELEMENTS (match_candidates); const size_t j = n / G_N_ELEMENTS (match_candidates); #ifdef ENABLE_PHONENUMBER const gboolean error_expected = !(i && j); #else /* ENABLE_PHONENUMBER */ const gboolean error_expected = TRUE; #endif /* ENABLE_PHONENUMBER */ EPhoneNumberMatch actual_match; GError *error = NULL; actual_match = e_phone_number_compare_strings ( match_candidates[i], match_candidates[j], &error); #ifdef ENABLE_PHONENUMBER g_assert_cmpuint (actual_match, ==, expected_matches[n]); #else /* ENABLE_PHONENUMBER */ g_assert_cmpuint (actual_match, ==, E_PHONE_NUMBER_MATCH_NONE); #endif /* ENABLE_PHONENUMBER */ if (!error_expected) { g_assert (error == NULL); } else { g_assert (error != NULL); g_assert (error->domain == E_PHONE_NUMBER_ERROR); #ifdef ENABLE_PHONENUMBER g_assert (error->code == E_PHONE_NUMBER_ERROR_NOT_A_NUMBER); #else /* ENABLE_PHONENUMBER */ g_assert (error->code == E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED); #endif /* ENABLE_PHONENUMBER */ g_assert (error->message != NULL); g_clear_error (&error); } } static void test_supported (void) { #ifdef ENABLE_PHONENUMBER g_assert (e_phone_number_is_supported ()); #else /* ENABLE_PHONENUMBER */ g_assert (!e_phone_number_is_supported ()); #endif /* ENABLE_PHONENUMBER */ } static void test_country_code_for_region (void) { GError *error = NULL; gint code; g_assert_cmpstr (setlocale (CATEGORY, NULL), ==, "en_US.UTF-8"); #ifdef ENABLE_PHONENUMBER code = e_phone_number_get_country_code_for_region ("CH", &error); g_assert_cmpstr (error ? error->message : NULL, ==, NULL); g_assert_cmpint (code, ==, 41); code = e_phone_number_get_country_code_for_region (NULL, &error); g_assert_cmpstr (error ? error->message : NULL, ==, NULL); g_assert_cmpint (code, ==, 1); code = e_phone_number_get_country_code_for_region ("C", &error); g_assert_cmpstr (error ? error->message : NULL, ==, NULL); g_assert_cmpint (code, ==, 0); code = e_phone_number_get_country_code_for_region ("", &error); g_assert_cmpstr (error ? error->message : NULL, ==, NULL); g_assert_cmpint (code, ==, 1); #else /* ENABLE_PHONENUMBER */ code = e_phone_number_get_country_code_for_region ("CH", &error); g_assert (error != NULL); g_assert (error->domain == E_PHONE_NUMBER_ERROR); g_assert (error->code == E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED); g_assert (error->message != NULL); g_assert_cmpint (code, ==, 0); #endif /* ENABLE_PHONENUMBER */ } static void test_default_region (void) { GError *error = NULL; gchar *country; g_assert_cmpstr (setlocale (CATEGORY, NULL), ==, "en_US.UTF-8"); country = e_phone_number_get_default_region (&error); #ifdef ENABLE_PHONENUMBER g_assert_cmpstr (error ? error->message : NULL, ==, NULL); g_assert_cmpstr (country, ==, "US"); #else /* ENABLE_PHONENUMBER */ g_assert (error != NULL); g_assert (error->domain == E_PHONE_NUMBER_ERROR); g_assert (error->code == E_PHONE_NUMBER_ERROR_NOT_IMPLEMENTED); g_assert (error->message != NULL); g_assert_cmpstr (country, ==, NULL); #endif /* ENABLE_PHONENUMBER */ g_free (country); } gint main (gint argc, gchar **argv) { size_t i, j; if (setlocale (LC_ALL, "en_US.UTF-8") == NULL) { g_message ("Failed to set locale to en_US.UTF-8"); g_message ("Skipping all /ebook-phone-number/* tests"); return 0; } g_test_init (&argc, &argv, NULL); g_test_bug_base ("http://bugzilla.gnome.org/"); g_test_add_func ( "/ebook-phone-number/supported", test_supported); g_test_add_data_func_full ( "/ebook-phone-number/parse-and-format/i164", parse_and_format_data_new ( "+493011223344", NULL, E_PHONE_NUMBER_COUNTRY_FROM_FQTN, 49, "3011223344", "+493011223344", "+49 30 11223344", "030 11223344", "tel:+49-30-11223344"), test_parse_and_format, parse_and_format_data_free); g_test_add_data_func_full ( "/ebook-phone-number/parse-and-format/national", parse_and_format_data_new ( "(030) 22334-455", "DE", E_PHONE_NUMBER_COUNTRY_FROM_DEFAULT, 49, "3022334455", "+493022334455", "+49 30 22334455", "030 22334455", "tel:+49-30-22334455"), test_parse_and_format, parse_and_format_data_free); g_test_add_data_func_full ( "/ebook-phone-number/parse-and-format/national2", parse_and_format_data_new ( "0049 (30) 22334-455", "DE", E_PHONE_NUMBER_COUNTRY_FROM_IDD, 49, "3022334455", "+493022334455", "+49 30 22334455", "030 22334455", "tel:+49-30-22334455"), test_parse_and_format, parse_and_format_data_free); g_test_add_data_func_full ( "/ebook-phone-number/parse-and-format/international", parse_and_format_data_new ( "+1 212 33445566", NULL, E_PHONE_NUMBER_COUNTRY_FROM_FQTN, 1, "21233445566", "+121233445566", "+1 21233445566", "21233445566", "tel:+1-21233445566"), test_parse_and_format, parse_and_format_data_free); g_test_add_data_func_full ( "/ebook-phone-number/parse-and-format/rfc3966", parse_and_format_data_new ( "tel:+358-71-44556677", NULL, E_PHONE_NUMBER_COUNTRY_FROM_FQTN, 358, "7144556677", "+3587144556677", "+358 71 44556677", "071 44556677", "tel:+358-71-44556677"), test_parse_and_format, parse_and_format_data_free); g_test_add_func ( "/ebook-phone-number/parse-and-format/bad-number", test_parse_bad_number); g_test_add_func ( "/ebook-phone-number/parse-and-format/auto-region", test_parse_auto_region); #ifdef ENABLE_PHONENUMBER g_assert_cmpint ( G_N_ELEMENTS (match_candidates) * G_N_ELEMENTS (match_candidates), ==, G_N_ELEMENTS (expected_matches)); #endif for (i = 0; i < G_N_ELEMENTS (match_candidates); ++i) { for (j = 0; j < G_N_ELEMENTS (match_candidates); ++j) { const size_t n = j + i * G_N_ELEMENTS (match_candidates); gchar *path = g_strdup_printf ( "/ebook-phone-number/compare/%s/%s", match_candidates[i], match_candidates[j]); g_test_add_data_func ( path, GUINT_TO_POINTER (n), test_compare_numbers); g_free (path); } } g_test_add_func ( "/ebook-phone-number/country-code/for-region", test_country_code_for_region); g_test_add_func ( "/ebook-phone-number/country-code/default-region", test_default_region); return g_test_run (); }