+
+/* Apple-specific, test for Apple-specific function ualoc_getLanguagesForRegion */
+enum { kUALanguageEntryMax = 10 };
+
+static void TestGetLanguagesForRegion() {
+ UALanguageEntry entries[kUALanguageEntryMax];
+ int32_t entryCount;
+ UErrorCode status;
+ const char * region;
+
+ status = U_ZERO_ERROR;
+ region = "CN";
+ entryCount = ualoc_getLanguagesForRegion(region, 0.001, entries, kUALanguageEntryMax, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region, u_errorName(status));
+ } else {
+ // Expect approximately:
+ // zh_Hans 0.90 UALANGSTATUS_OFFICIAL
+ // wuu 0.06 Wu
+ // hsn 0.06 Xiang
+ // hak 0.023 Hakka
+ // nan 0.019 Minnan
+ // gan 0.017 Gan
+ // ii 0.006 Yi
+ // ug_Arab 0.0055 Uighur UALANGSTATUS_REGIONAL_OFFICIAL
+ // ...at least 4 more with fractions >= 0.001
+ if (entryCount < kUALanguageEntryMax) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region, entryCount);
+ } else {
+ UALanguageEntry* entryPtr = entries;
+ if (uprv_strcmp(entryPtr->languageCode, "zh_Hans") != 0 || entryPtr->userFraction < 0.8 || entryPtr->userFraction > 1.0 || entryPtr->status != UALANGSTATUS_OFFICIAL) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region, entryPtr->languageCode, entryPtr->userFraction, (int)entryPtr->status);
+ }
+ for (entryPtr++; entryPtr < entries + kUALanguageEntryMax && uprv_strcmp(entryPtr->languageCode, "ug_Arab") != 0; entryPtr++)
+ ;
+ if (entryPtr < entries + kUALanguageEntryMax) {
+ // we found ug_Arab, make sure it has correct status
+ if (entryPtr->status != UALANGSTATUS_REGIONAL_OFFICIAL) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, ug_Arab had incorrect status %d\n", (int)entryPtr->status);
+ }
+ } else {
+ // did not find ug_Arab
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, entries did not include ug_Arab\n", region);
+ }
+ }
+ }
+
+ status = U_ZERO_ERROR;
+ region = "CA";
+ entryCount = ualoc_getLanguagesForRegion(region, 0.001, entries, kUALanguageEntryMax, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region, u_errorName(status));
+ } else {
+ // Expect approximately:
+ // en 0.85 UALANGSTATUS_OFFICIAL
+ // fr 0.22 UALANGSTATUS_OFFICIAL
+ // ...
+ if (entryCount < 2) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region, entryCount);
+ } else {
+ if (uprv_strcmp(entries[0].languageCode, "en") != 0 || entries[0].userFraction < 0.7 || entries[0].userFraction > 1.0 || entries[0].status != UALANGSTATUS_OFFICIAL) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[0] { %s, %.3f, %d }\n", region, entries[0].languageCode, entries[0].userFraction, (int)entries[0].status);
+ }
+ if (uprv_strcmp(entries[1].languageCode, "fr") != 0 || entries[1].userFraction < 0.1 || entries[1].userFraction > 1.0 || entries[1].status != UALANGSTATUS_OFFICIAL) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, invalid entries[1] { %s, %.3f, %d }\n", region, entries[1].languageCode, entries[1].userFraction, (int)entries[1].status);
+ }
+ }
+ }
+
+ status = U_ZERO_ERROR;
+ region = "IN";
+ entryCount = ualoc_getLanguagesForRegion(region, 0.001, NULL, 0, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, status %s\n", region, u_errorName(status));
+ } else {
+ if (entryCount < 40) {
+ log_err("FAIL: ualoc_getLanguagesForRegion %s, entryCount %d is too small\n", region, entryCount);
+ }
+ }
+}
+
+/* data for TestAppleLocalizationsToUse */
+
+typedef struct {
+ const char * const *locs;
+ int32_t locCount;
+} AppleLocsAndCount;
+
+enum { kNumLocSets = 6 };
+
+typedef struct {
+ const char * language;
+ const char ** expLocsForSets[kNumLocSets];
+} LangAndExpLocs;
+
+
+static const char * appleLocs1[] = {
+ "Arabic",
+ "Danish",
+ "Dutch",
+ "English",
+ "Finnish",
+ "French",
+ "German",
+ "Italian",
+ "Japanese",
+ "Korean",
+ "Norwegian",
+ "Polish",
+ "Portuguese",
+ "Russian",
+ "Spanish",
+ "Swedish",
+ "Thai",
+ "Turkish",
+ "ca",
+ "cs",
+ "el",
+ "he",
+ "hr",
+ "hu",
+ "id",
+ "ms",
+ "ro",
+ "sk",
+ "uk",
+ "vi",
+ "zh_CN", "zh_TW",
+};
+
+static const char * appleLocs2[] = {
+ "ar",
+ "ca",
+ "cs",
+ "da",
+ "de",
+ "el",
+ "en", "en_AU", "en_GB",
+ "es", "es_MX",
+ "fi",
+ "fr", "fr_CA",
+ "he",
+ "hr",
+ "hu",
+ "id",
+ "it",
+ "ja",
+ "ko",
+ "ms",
+ "nl",
+ "no",
+ "pl",
+ "pt", "pt_PT",
+ "ro",
+ "ru",
+ "sk",
+ "sv",
+ "th",
+ "tr",
+ "uk",
+ "vi",
+ "zh_CN", "zh_HK", "zh_TW",
+};
+
+static const char * appleLocs3[] = {
+ "ar",
+ "ca",
+ "cs",
+ "da",
+ "de",
+ "el",
+ "en", "en_AU", "en_CA", "en_GB",
+ "es", "es_419",
+ "fi",
+ "fr", "fr_CA", "fr_FR",
+ "he",
+ "hr",
+ "hu",
+ "id",
+ "it",
+ "ja",
+ "ko",
+ "ms",
+ "nb",
+ "nl",
+ "pl",
+ "pt", "pt_BR", "pt_PT",
+ "ro",
+ "ru",
+ "sk",
+ "sv",
+ "th",
+ "tr",
+ "uk",
+ "vi",
+ "zh_CN", "zh_HK", "zh_MO", "zh_TW",
+};
+
+static const char * appleLocs4[] = {
+ "en", "en_AU", "en_CA", "en_GB", "en_IN", "en_US",
+ "es", "es_419", "es_MX",
+ "fr", "fr_CA", "fr_CH", "fr_FR",
+ "nl", "nl_BE", "nl_NL",
+ "pt", "pt_BR",
+ "ro", "ro_MD", "ro_RO",
+ "zh_Hans", "zh_Hant", "zh_Hant_HK",
+};
+
+static const char * appleLocs5[] = {
+ "en", "en_001", "en_AU", "en_GB",
+ "es", "es_ES", "es_MX",
+ "zh_CN", "zh_Hans", "zh_Hant", "zh_TW",
+ "yi",
+ "fil",
+ "haw",
+ "tlh",
+ "sr",
+ "sr-Latn",
+};
+
+// list 6
+static const char * appleLocs6[] = {
+ "en", "en_001", "en_150", "en_AU", "en_GB",
+ "es", "es_419", "es_ES", "es_MX",
+ "zh_CN", "zh_Hans", "zh_Hant", "zh_Hant_HK", "zh_HK", "zh_TW",
+ "iw",
+ "in",
+ "mo",
+ "tl",
+};
+
+static const AppleLocsAndCount locAndCountEntries[kNumLocSets] = {
+ { appleLocs1, UPRV_LENGTHOF(appleLocs1) },
+ { appleLocs2, UPRV_LENGTHOF(appleLocs2) },
+ { appleLocs3, UPRV_LENGTHOF(appleLocs3) },
+ { appleLocs4, UPRV_LENGTHOF(appleLocs4) },
+ { appleLocs5, UPRV_LENGTHOF(appleLocs5) },
+ { appleLocs6, UPRV_LENGTHOF(appleLocs6) },
+};
+
+
+static const char* l1_ar[] = { "ar", NULL };
+static const char* l1_Ara[] = { "Arabic", NULL };
+static const char* l1_ca[] = { "ca", NULL };
+static const char* l1_cs[] = { "cs", NULL };
+static const char* l1_da[] = { "da", NULL };
+static const char* l1_Dan[] = { "Danish", NULL };
+static const char* l1_de[] = { "de", NULL };
+static const char* l1_Ger[] = { "German", NULL };
+static const char* l1_el[] = { "el", NULL };
+static const char* l1_en[] = { "en", NULL };
+static const char* l1_Eng[] = { "English", NULL };
+static const char* l2_en_001_[] = { "en_001", "en", NULL };
+static const char* l2_en_CA_[] = { "en_CA", "en", NULL };
+static const char* l2_en_GB_[] = { "en_GB", "en", NULL };
+static const char* l2_en_US_[] = { "en_US", "en", NULL };
+static const char* l2_en_GB_Eng[] = { "en_GB", "English", NULL };
+static const char* l3_en_GB001_[] = { "en_GB", "en_001", "en", NULL };
+static const char* l3_en_AUGB_[] = { "en_AU", "en_GB", "en", NULL };
+static const char* l3_en_INGB_[] = { "en_IN", "en_GB", "en", NULL };
+static const char* l4_en_150GB001_[] = { "en_150", "en_GB", "en_001", "en", NULL };
+static const char* l4_en_AUGB001_[] = { "en_AU", "en_GB", "en_001", "en", NULL };
+static const char* l1_es[] = { "es", NULL };
+static const char* l1_Spa[] = { "Spanish", NULL };
+static const char* l2_es_419_[] = { "es_419", "es", NULL };
+static const char* l2_es_ES_[] = { "es_ES", "es", NULL };
+static const char* l2_es_MX_[] = { "es_MX", "es", NULL };
+static const char* l2_es_MX_Spa[] = { "es_MX", "Spanish", NULL };
+static const char* l3_es_MX419_[] = { "es_MX", "es_419", "es", NULL };
+static const char* l1_fi[] = { "fi", NULL };
+static const char* l1_Fin[] = { "Finnish", NULL };
+static const char* l1_fil[] = { "fil", NULL };
+static const char* l1_tl[] = { "tl", NULL };
+static const char* l1_fr[] = { "fr", NULL };
+static const char* l1_Fre[] = { "French", NULL };
+static const char* l2_fr_CA_[] = { "fr_CA", "fr", NULL };
+static const char* l2_fr_CH_[] = { "fr_CH", "fr", NULL };
+static const char* l2_fr_FR_[] = { "fr_FR", "fr", NULL };
+static const char* l1_haw[] = { "haw", NULL };
+static const char* l1_he[] = { "he", NULL };
+static const char* l1_hr[] = { "hr", NULL };
+static const char* l1_hu[] = { "hu", NULL };
+static const char* l1_id[] = { "id", NULL };
+static const char* l1_in[] = { "in", NULL };
+static const char* l1_it[] = { "it", NULL };
+static const char* l1_Ita[] = { "Italian", NULL };
+static const char* l1_ja[] = { "ja", NULL };
+static const char* l1_Japn[] = { "Japanese", NULL };
+static const char* l1_ko[] = { "ko", NULL };
+static const char* l1_Kor[] = { "Korean", NULL };
+static const char* l1_ms[] = { "ms", NULL };
+static const char* l1_nb[] = { "nb", NULL };
+static const char* l1_no[] = { "no", NULL };
+static const char* l1_Nor[] = { "Norwegian", NULL };
+static const char* l1_nl[] = { "nl", NULL };
+static const char* l1_Dut[] = { "Dutch", NULL };
+static const char* l2_nl_BE_[] = { "nl_BE", "nl", NULL };
+static const char* l1_pl[] = { "pl", NULL };
+static const char* l1_Pol[] = { "Polish", NULL };
+static const char* l1_pt[] = { "pt", NULL };
+static const char* l1_pt_PT[] = { "pt_PT", NULL };
+static const char* l1_Port[] = { "Portuguese", NULL };
+static const char* l2_pt_BR_[] = { "pt_BR", "pt", NULL };
+static const char* l2_pt_PT_[] = { "pt_PT", "pt", NULL };
+static const char* l1_ro[] = { "ro", NULL };
+static const char* l2_ro_MD_[] = { "ro_MD", "ro", NULL };
+static const char* l1_mo[] = { "mo", NULL };
+static const char* l1_ru[] = { "ru", NULL };
+static const char* l1_Rus[] = { "Russian", NULL };
+static const char* l1_sk[] = { "sk", NULL };
+static const char* l1_sr[] = { "sr", NULL };
+static const char* l1_srLatn[] = { "sr-Latn", NULL };
+static const char* l1_sv[] = { "sv", NULL };
+static const char* l1_Swe[] = { "Swedish", NULL };
+static const char* l1_th[] = { "th", NULL };
+static const char* l1_Thai[] = { "Thai", NULL };
+static const char* l1_tlh[] = { "tlh", NULL };
+static const char* l1_tr[] = { "tr", NULL };
+static const char* l1_Tur[] = { "Turkish", NULL };
+static const char* l1_uk[] = { "uk", NULL };
+static const char* l1_vi[] = { "vi", NULL };
+static const char* l1_yi[] = { "yi", NULL };
+static const char* l1_iw[] = { "iw", NULL };
+static const char* l1_zh_CN[] = { "zh_CN", NULL };
+static const char* l1_zh_TW[] = { "zh_TW", NULL };
+static const char* l1_zh_Hans[] = { "zh_Hans", NULL };
+static const char* l1_zh_Hant[] = { "zh_Hant", NULL };
+static const char* l1_zhHant[] = { "zh-Hant", NULL };
+static const char* l2_zh_HKTW[] = { "zh_HK", "zh_TW", NULL };
+static const char* l2_zh_Hant_HK_[] = { "zh_Hant_HK", "zh_Hant", NULL };
+static const char* l2_zh_CN_Hans[] = { "zh_CN", "zh_Hans", NULL };
+static const char* l2_zh_TW_Hant[] = { "zh_TW", "zh_Hant", NULL };
+static const char* l3_zh_MOHKTW[] = { "zh_MO", "zh_HK", "zh_TW", NULL };
+static const char* l3_zh_HK_HantHK_Hant[] = { "zh_HK", "zh_Hant_HK", "zh_Hant", NULL };
+
+static const LangAndExpLocs appleLangAndLoc[] = {
+// language\ result for appleLocs1 appleLocs2 appleLocs3 appleLocs4 appleLocs5 appleLocs6
+ { "zh", { l1_zh_CN, l1_zh_CN, l1_zh_CN, l1_zh_Hans, l1_zh_Hans, l1_zh_Hans } },
+ { "zh-Hans", { l1_zh_CN, l1_zh_CN, l1_zh_CN, l1_zh_Hans, l1_zh_Hans, l1_zh_Hans } },
+ { "zh-Hant", { l1_zh_TW, l1_zh_TW, l1_zh_TW, l1_zh_Hant, l1_zh_Hant, l1_zh_Hant } },
+ { "zh-Hans-CN", { l1_zh_CN, l1_zh_CN, l1_zh_CN, l1_zh_Hans, l2_zh_CN_Hans, l2_zh_CN_Hans } },
+ { "zh-Hans-SG", { l1_zh_CN, l1_zh_CN, l1_zh_CN, l1_zh_Hans, l1_zh_Hans, l1_zh_Hans } },
+ { "zh-Hant-TW", { l1_zh_TW, l1_zh_TW, l1_zh_TW, l1_zh_Hant, l2_zh_TW_Hant, l2_zh_TW_Hant } },
+ { "zh-Hant-HK", { l1_zh_TW, l2_zh_HKTW, l2_zh_HKTW, l2_zh_Hant_HK_, l1_zh_Hant, l2_zh_Hant_HK_ } },
+ { "zh-Hant-MO", { l1_zh_TW, l2_zh_HKTW, l3_zh_MOHKTW, l2_zh_Hant_HK_, l1_zh_Hant, l2_zh_Hant_HK_ } },
+ { "zh-Hans-HK", { l1_zh_CN, l1_zh_CN, l1_zh_CN, l1_zh_Hans, l1_zh_Hans, l1_zh_Hans } },
+ { "zh-CN", { l1_zh_CN, l1_zh_CN, l1_zh_CN, l1_zh_Hans, l2_zh_CN_Hans, l2_zh_CN_Hans } },
+ { "zh-SG", { l1_zh_CN, l1_zh_CN, l1_zh_CN, l1_zh_Hans, l1_zh_Hans, l1_zh_Hans } },
+ { "zh-TW", { l1_zh_TW, l1_zh_TW, l1_zh_TW, l1_zh_Hant, l2_zh_TW_Hant, l2_zh_TW_Hant } },
+ { "zh-HK", { l1_zh_TW, l2_zh_HKTW, l2_zh_HKTW, l2_zh_Hant_HK_, l1_zh_Hant, l3_zh_HK_HantHK_Hant } },
+ { "zh-MO", { l1_zh_TW, l2_zh_HKTW, l3_zh_MOHKTW, l2_zh_Hant_HK_, l1_zh_Hant, l2_zh_Hant_HK_ } },
+ { "en", { l1_Eng, l1_en, l1_en, l1_en, l1_en, l1_en } },
+ { "en-US", { l1_Eng, l1_en, l1_en, l2_en_US_, l1_en, l1_en } },
+ { "en-AU", { l1_Eng, l3_en_AUGB_, l3_en_AUGB_, l3_en_AUGB_, l4_en_AUGB001_, l4_en_AUGB001_ } },
+ { "en-CA", { l1_Eng, l1_en, l2_en_CA_, l2_en_CA_, l2_en_001_, l2_en_001_ } },
+ { "en-GB", { l1_Eng, l2_en_GB_, l2_en_GB_, l2_en_GB_, l3_en_GB001_, l3_en_GB001_ } },
+ { "en-IN", { l1_Eng, l2_en_GB_, l2_en_GB_, l3_en_INGB_, l3_en_GB001_, l3_en_GB001_ } },
+ { "en-US", { l1_Eng, l1_en, l1_en, l2_en_US_, l1_en, l1_en } },
+ { "en_US", { l1_Eng, l1_en, l1_en, l2_en_US_, l1_en, l1_en } },
+ { "en-FR", { l1_Eng, l2_en_GB_, l2_en_GB_, l2_en_GB_, l3_en_GB001_, l4_en_150GB001_ } },
+ { "en-IL", { l1_Eng, l1_en, l1_en, l1_en, l2_en_001_, l2_en_001_ } },
+ { "en-001", { l1_Eng, l1_en, l1_en, l1_en, l2_en_001_, l2_en_001_ } },
+ { "en-150", { l1_Eng, l2_en_GB_, l2_en_GB_, l2_en_GB_, l3_en_GB001_, l4_en_150GB001_ } },
+ { "en-Latn", { l1_Eng, l1_en, l1_en, l1_en, l1_en, l1_en } },
+ { "en-Latn-US", { l1_Eng, l1_en, l1_en, l1_en,/*TODO*/ l1_en, l1_en } },
+ { "en-US-POSIX", { l1_Eng, l1_en, l1_en, l2_en_US_, l1_en, l1_en } },
+ { "en-Latn-US-POSIX", { l1_Eng, l1_en, l1_en, l1_en, l1_en, l1_en } },
+ { "en-u-ca-hebrew", { l1_Eng, l1_en, l1_en, l1_en, l1_en, l1_en } },
+ { "en@calendar=hebrew", { l1_Eng, l1_en, l1_en, l1_en, l1_en, l1_en } },
+ { "en-", { l1_Eng, l1_en, l1_en, l1_en, l1_en, l1_en } },
+ { "en_", { l1_Eng, l1_en, l1_en, l1_en, l1_en, l1_en } },
+ { "es", { l1_Spa, l1_es, l1_es, l1_es, l1_es, l1_es } },
+ { "es-ES", { l1_Spa, l1_es, l1_es, l1_es, l2_es_ES_, l2_es_ES_ } },
+ { "es-419", { l1_Spa, l1_es, l2_es_419_, l2_es_419_, l1_es, l2_es_419_ } },
+ { "es-MX", { l1_Spa, l2_es_MX_, l2_es_419_, l3_es_MX419_, l2_es_MX_, l3_es_MX419_ } },
+ { "es-AR", { l1_Spa, l1_es, l2_es_419_, l2_es_419_, l1_es, l2_es_419_ } },
+ { "es-Latn", { l1_Spa, l1_es, l1_es, l1_es, l1_es, l1_es } },
+ { "es-Latn-MX", { l1_Spa, l1_es, l1_es, l1_es, l1_es, l1_es } },
+ { "pt", { l1_Port, l1_pt, l1_pt, l1_pt, NULL, NULL } },
+ { "pt-BR", { l1_Port, l1_pt, l2_pt_BR_, l2_pt_BR_, NULL, NULL } },
+ { "pt-PT", { l1_Port, l2_pt_PT_, l2_pt_PT_, l1_pt, NULL, NULL } },
+ { "pt-MO", { l1_Port, l2_pt_PT_, l2_pt_PT_, l1_pt, NULL, NULL } },
+ { "fr", { l1_Fre, l1_fr, l1_fr, l1_fr, NULL, NULL } },
+ { "fr-FR", { l1_Fre, l1_fr, l2_fr_FR_, l2_fr_FR_, NULL, NULL } },
+ { "fr-CA", { l1_Fre, l2_fr_CA_, l2_fr_CA_, l2_fr_CA_, NULL, NULL } },
+ { "fr-CH", { l1_Fre, l1_fr, l1_fr, l2_fr_CH_, NULL, NULL } },
+ { "ar", { l1_Ara, l1_ar, l1_ar, NULL, NULL, NULL } },
+ { "da", { l1_Dan, l1_da, l1_da, NULL, NULL, NULL } },
+ { "nl", { l1_Dut, l1_nl, l1_nl, l1_nl, NULL, NULL } },
+ { "nl-BE", { l1_Dut, l1_nl, l1_nl, l2_nl_BE_, NULL, NULL } },
+ { "fi", { l1_Fin, l1_fi, l1_fi, NULL, NULL, NULL } },
+ { "de", { l1_Ger, l1_de, l1_de, NULL, NULL, NULL } },
+ { "it", { l1_Ita, l1_it, l1_it, NULL, NULL, NULL } },
+ { "ja", { l1_Japn, l1_ja, l1_ja, NULL, NULL, NULL } },
+ { "ko", { l1_Kor, l1_ko, l1_ko, NULL, NULL, NULL } },
+ { "nb", { l1_Nor, l1_no, l1_nb, NULL, NULL, NULL } },
+ { "no", { l1_Nor, l1_no, l1_nb, NULL, NULL, NULL } },
+ { "pl", { l1_Pol, l1_pl, l1_pl, NULL, NULL, NULL } },
+ { "ru", { l1_Rus, l1_ru, l1_ru, NULL, NULL, NULL } },
+ { "sv", { l1_Swe, l1_sv, l1_sv, NULL, NULL, NULL } },
+ { "th", { l1_Thai, l1_th, l1_th, NULL, NULL, NULL } },
+ { "tr", { l1_Tur, l1_tr, l1_tr, NULL, NULL, NULL } },
+ { "ca", { l1_ca, l1_ca, l1_ca, NULL, NULL, NULL } },
+ { "cs", { l1_cs, l1_cs, l1_cs, NULL, NULL, NULL } },
+ { "el", { l1_el, l1_el, l1_el, NULL, NULL, NULL } },
+ { "he", { l1_he, l1_he, l1_he, NULL, NULL, l1_iw } },
+ { "iw", { l1_he, l1_he, l1_he, NULL, NULL, l1_iw } },
+ { "hr", { l1_hr, l1_hr, l1_hr, NULL, NULL, NULL } },
+ { "hu", { l1_hu, l1_hu, l1_hu, NULL, NULL, NULL } },
+ { "id", { l1_id, l1_id, l1_id, NULL, NULL, l1_in } },
+ { "in", { l1_id, l1_id, l1_id, NULL, NULL, l1_in } },
+ { "ms", { l1_ms, l1_ms, l1_ms, NULL, NULL, NULL } },
+ { "ro", { l1_ro, l1_ro, l1_ro, l1_ro, NULL, NULL } },
+ { "mo", { l1_ro, l1_ro, l1_ro, l2_ro_MD_, NULL, l1_mo } },
+ { "sk", { l1_sk, l1_sk, l1_sk, NULL, NULL, NULL } },
+ { "uk", { l1_uk, l1_uk, l1_uk, NULL, NULL, NULL } },
+ { "vi", { l1_vi, l1_vi, l1_vi, NULL, NULL, NULL } },
+ { "yi", { NULL, NULL, NULL, NULL, l1_yi, NULL } },
+ { "ji", { NULL, NULL, NULL, NULL, l1_yi, NULL } },
+ { "fil", { NULL, NULL, NULL, NULL, l1_fil, l1_tl } },
+ { "tl", { NULL, NULL, NULL, NULL, l1_fil, l1_tl } },
+ { "haw", { NULL, NULL, NULL, NULL, l1_haw, NULL } },
+ { "sr", { NULL, NULL, NULL, NULL, l1_sr, NULL } },
+ { "sr-Cyrl", { NULL, NULL, NULL, NULL, l1_sr, NULL } },
+ { "sr-Latn", { NULL, NULL, NULL, NULL, l1_srLatn, NULL } },
+ { "tlh", { NULL, NULL, NULL, NULL, l1_tlh, NULL } },
+ { "Default@2x", { NULL, NULL, NULL, NULL, NULL, NULL } },
+ { "default", { NULL, NULL, NULL, NULL, NULL, NULL } },
+ { "root", { NULL, NULL, NULL, NULL, NULL, NULL } },
+ { "", { NULL, NULL, NULL, NULL, NULL, NULL } },
+ { "_US", { NULL, NULL, NULL, NULL, NULL, NULL } },
+ { "-US", { NULL, NULL, NULL, NULL, NULL, NULL } },
+ { "-u-ca-hebrew", { NULL, NULL, NULL, NULL, NULL, NULL } },
+ { "-u-ca-hebrew", { NULL, NULL, NULL, NULL, NULL, NULL } },
+ { "@calendar=hebrew", { NULL, NULL, NULL, NULL, NULL, NULL } },
+};
+enum { kNumAppleLangAndLoc = UPRV_LENGTHOF(appleLangAndLoc) };
+
+/* tests from <rdar://problem/21518031> */
+
+static const char * appleLocsA1[] = { "en", "fr", "de", "zh-Hant" };
+static const char * appleLocsA2[] = { "en", "fr", "de", "zh_TW", "zh_CN", "zh-Hant" };
+static const char * appleLocsA3[] = { "en", "en_IN", "en_GB", "fr", "de", "zh_TW" };
+static const char * appleLocsA4[] = { "Spanish", "es_MX", "English", "en_GB" };
+static const char * appleLocsA5[] = { "en", "fr", "de", "pt", "pt_PT" };
+static const char * appleLocsA6[] = { "en", "pt_PT" };
+
+static const AppleLocsAndCount locAndCountEntriesA[kNumLocSets] = {
+ { appleLocsA1, UPRV_LENGTHOF(appleLocsA1) },
+ { appleLocsA2, UPRV_LENGTHOF(appleLocsA2) },
+ { appleLocsA3, UPRV_LENGTHOF(appleLocsA3) },
+ { appleLocsA4, UPRV_LENGTHOF(appleLocsA4) },
+ { appleLocsA5, UPRV_LENGTHOF(appleLocsA5) },
+ { appleLocsA6, UPRV_LENGTHOF(appleLocsA6) },
+};
+
+static const LangAndExpLocs appleLangAndLocA[] = {
+// language\ result for appleLocsA1 appleLocsA2 appleLocsA3 appleLocsA4 appleLocsA5 appleLocsA6
+ { "zh-Hant", { l1_zhHant,/*0*/ l1_zhHant,/*zh_TW*/ l1_zh_TW, NULL, NULL, NULL } },
+ { "zh_Hant", { l1_zhHant, l1_zhHant,/*zh_TW*/ l1_zh_TW, NULL, NULL, NULL } },
+ { "zh_HK", { l1_zhHant, l1_zhHant,/*zh_TW*/ l1_zh_TW, NULL, NULL, NULL } },
+ { "en_IN", { l1_en, l1_en, l3_en_INGB_, l2_en_GB_Eng, l1_en, l1_en } },
+ { "es_MX", { NULL, NULL, NULL, l2_es_MX_Spa, NULL, NULL } },
+ { "pt_PT", { NULL, NULL, NULL, NULL, l2_pt_PT_, l1_pt_PT } },
+ { "pt", { NULL, NULL, NULL, NULL, l1_pt, l1_pt_PT } },
+};
+enum { kNumAppleLangAndLocA = UPRV_LENGTHOF(appleLangAndLocA) };
+
+/* tests from log attached to 21682790 */
+
+static const char * appleLocsB1[] = {
+ "ar", "Base", "ca", "cs",
+ "da", "Dutch", "el", "English",
+ "es_MX", "fi", "French", "German",
+ "he", "hr", "hu", "id",
+ "Italian", "Japanese", "ko", "ms",
+ "no", "pl", "pt", "pt_PT",
+ "ro", "ru", "sk", "Spanish",
+ "sv", "th", "tr", "uk",
+ "vi", "zh_CN", "zh_TW"
+};
+
+static const char * appleLocsB2[] = {
+ "ar", "ca", "cs",
+ "da", "Dutch", "el", "English",
+ "es_MX", "fi", "French", "German",
+ "he", "hr", "hu", "id",
+ "Italian", "Japanese", "ko", "ms",
+ "no", "pl", "pt", "pt_PT",
+ "ro", "ru", "sk", "Spanish",
+ "sv", "th", "tr", "uk",
+ "vi", "zh_CN", "zh_TW"
+};
+
+static const char * appleLocsB3[] = {
+ "ar", "ca", "cs", "da",
+ "de", "el", "en", "es",
+ "es_MX", "fi", "French", "he",
+ "hr", "hu", "id", "Italian",
+ "ja", "ko", "ms", "nl",
+ "no", "pl", "pt", "pt_PT",
+ "ro", "ru", "sk", "sv",
+ "th", "tr", "uk", "vi",
+ "zh_CN", "zh_TW"
+};
+
+static const char * appleLocsB4[] = {
+ "ar", "ca", "cs", "da",
+ "de", "el", "en", "es",
+ "es_MX", "fi", "fr", "he",
+ "hr", "hu", "id", "it",
+ "ja", "ko", "ms", "nl",
+ "no", "pl", "pt", "pt_PT",
+ "ro", "ru", "sk", "sv",
+ "th", "tr", "uk", "vi",
+ "zh_CN", "zh_TW"
+};
+
+static const char * appleLocsB5[] = { "en" };
+
+static const char * appleLocsB6[] = { "English" };
+
+static const AppleLocsAndCount locAndCountEntriesB[kNumLocSets] = {
+ { appleLocsB1, UPRV_LENGTHOF(appleLocsB1) },
+ { appleLocsB2, UPRV_LENGTHOF(appleLocsB2) },
+ { appleLocsB3, UPRV_LENGTHOF(appleLocsB3) },
+ { appleLocsB4, UPRV_LENGTHOF(appleLocsB4) },
+ { appleLocsB5, UPRV_LENGTHOF(appleLocsB5) },
+ { appleLocsB6, UPRV_LENGTHOF(appleLocsB6) },
+};
+
+static const LangAndExpLocs appleLangAndLocB[] = {
+// language\ result for appleLocsB1 appleLocsB2 appleLocsB3 appleLocsB4 appleLocsB5 appleLocsB6
+// Prefs 1, logged with sets B1-B3
+ { "en", { l1_Eng, l1_Eng, l1_en, l1_en, l1_en, l1_Eng } },
+ { "es", { l1_Spa, l1_Spa, l1_es, l1_es, NULL, NULL } },
+// Prefs 2, logged with sets B1-B6
+ { "English", { l1_Eng, l1_Eng, l1_en, l1_en, l1_en, l1_Eng } },
+ { "Spanish", { l1_Spa, l1_Spa, l1_es, l1_es, NULL, NULL } },
+};
+enum { kNumAppleLangAndLocB = UPRV_LENGTHOF(appleLangAndLocB) };
+
+typedef struct {
+ const AppleLocsAndCount * locAndCountEntriesPtr;
+ const LangAndExpLocs * appleLangAndLocPtr;
+ int32_t appleLangAndLocCount;
+} AppleLocToUseTestSet;
+
+static const AppleLocToUseTestSet altuTestSets[] = {
+ { locAndCountEntries, appleLangAndLoc, kNumAppleLangAndLoc },
+ { locAndCountEntriesA, appleLangAndLocA, kNumAppleLangAndLocA },
+ { locAndCountEntriesB, appleLangAndLocB, kNumAppleLangAndLocB },
+ { NULL, NULL, 0 }
+};
+
+/* tests for multiple prefs sets */
+
+static const char * appleLocsM[] = { "en", "en_GB", "pt", "pt_PT", "zh_CN", "zh_Hant" };
+static const char * prefLangsM[] = { "tlh", "zh_HK", "zh_SG", "zh_Hans", "pt_BR", "pt_PT", "en_IN", "en" };
+static const char * locsToUseM[] = { "zh_Hant" };
+enum {
+ kNumAppleLocsM = UPRV_LENGTHOF(appleLocsM),
+ kNumPrefLangsM = UPRV_LENGTHOF(prefLangsM),
+ kNumLocsToUseM = UPRV_LENGTHOF(locsToUseM),
+};
+
+/* general enums */
+
+enum { kMaxLocalizationsToUse = 8, kPrintArrayBufSize = 128 };
+
+// array, array of pointers to strings to print
+// count, count of array elements, may be -1 if array is terminated by a NULL entry
+// buf, buffer into which to put concatenated strings
+// bufSize, length of buf
+static void printStringArray(const char **array, int32_t count, char *buf, int32_t bufSize) {
+ char * bufPtr = buf;
+ const char * curEntry;
+ int32_t idx, countMax = bufSize/16;
+ if (count < 0 || count > countMax) {
+ count = countMax;
+ }
+ for (idx = 0; idx < count && (curEntry = *array++) != NULL; idx++) {
+ int32_t len = sprintf(bufPtr, "%s\"%.12s\"", (idx > 0)? ", ": "", curEntry);
+ if (len <= 0) {
+ break;
+ }
+ bufPtr += len;
+ }
+ *bufPtr = 0; /* ensure termination */
+}
+
+static UBool equalStringArrays(const char **array1, int32_t count1, const char **array2, int32_t count2) {
+ const char ** array1Ptr = array1;
+ const char ** array2Ptr = array2;
+ if (count1 < 0) {
+ count1 = 0;
+ while (*array1Ptr++ != NULL) {
+ count1++;
+ }
+ }
+ if (count2 < 0) {
+ count2 = 0;
+ while (*array2Ptr++ != NULL) {
+ count2++;
+ }
+ }
+ if (count1 != count2) {
+ return FALSE;
+ }
+ int32_t idx;
+ for (idx = 0; idx < count1; idx++) {
+ if (uprv_strcmp(array1[idx], array2[idx]) != 0) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void TestAppleLocalizationsToUse() {
+ const AppleLocToUseTestSet * testSetPtr;
+ const char * locsToUse[kMaxLocalizationsToUse];
+ int32_t numLocsToUse;
+ UErrorCode status;
+ char printExpected[kPrintArrayBufSize];
+ char printActual[kPrintArrayBufSize];
+
+ for (testSetPtr = altuTestSets; testSetPtr->locAndCountEntriesPtr != NULL; testSetPtr++) {
+ int32_t iLocSet, iLang;
+
+ for (iLocSet = 0; iLocSet < kNumLocSets; iLocSet++) {
+ for (iLang = 0; iLang < testSetPtr->appleLangAndLocCount; iLang++) {
+ status = U_ZERO_ERROR;
+ const char * language = testSetPtr->appleLangAndLocPtr[iLang].language;
+ const char ** expLocsForSet = testSetPtr->appleLangAndLocPtr[iLang].expLocsForSets[iLocSet];
+
+ numLocsToUse = ualoc_localizationsToUse(&language, 1,
+ testSetPtr->locAndCountEntriesPtr[iLocSet].locs, testSetPtr->locAndCountEntriesPtr[iLocSet].locCount,
+ locsToUse, kMaxLocalizationsToUse, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, status %s\n",
+ testSetPtr-altuTestSets, iLocSet+1, language, u_errorName(status));
+ } else if (numLocsToUse == 0 && expLocsForSet != NULL) {
+ printStringArray(expLocsForSet, -1, printExpected, kPrintArrayBufSize);
+ log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect {%s}, get no results\n",
+ testSetPtr-altuTestSets, iLocSet+1, language, printExpected);
+ } else if (numLocsToUse > 0 && expLocsForSet == NULL) {
+ printStringArray(locsToUse, numLocsToUse, printActual, kPrintArrayBufSize);
+ log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s, expect no results, get {%s}\n",
+ testSetPtr-altuTestSets, iLocSet+1, language, printActual);
+ } else if (numLocsToUse > 0 && !equalStringArrays(expLocsForSet, -1, locsToUse, numLocsToUse)) {
+ printStringArray(expLocsForSet, -1, printExpected, kPrintArrayBufSize);
+ printStringArray(locsToUse, numLocsToUse, printActual, kPrintArrayBufSize);
+ log_err("FAIL: ualoc_localizationsToUse testSet %d, locSet %d, lang %s:\n expect {%s}\n get {%s}\n",
+ testSetPtr-altuTestSets, iLocSet+1, language, printExpected, printActual);
+ }
+ }
+ }
+ }
+
+
+ status = U_ZERO_ERROR;
+ numLocsToUse = ualoc_localizationsToUse(prefLangsM, kNumPrefLangsM, appleLocsM, kNumAppleLocsM, locsToUse, kMaxLocalizationsToUse, &status);
+ if (U_FAILURE(status)) {
+ log_err("FAIL: ualoc_localizationsToUse appleLocsM, langs prefLangsM, status %s\n", u_errorName(status));
+ } else if (!equalStringArrays(locsToUseM, kNumLocsToUseM, locsToUse, numLocsToUse)) {
+ printStringArray(locsToUseM, kNumLocsToUseM, printExpected, kPrintArrayBufSize);
+ printStringArray(locsToUse, numLocsToUse, printActual, kPrintArrayBufSize);
+ log_err("FAIL: ualoc_localizationsToUse appleLocsM, langs prefLangsM:\n expect {%s}\n get {%s}\n",
+ printExpected, printActual);
+ }
+
+}