1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2009-2012, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 */ 9 package com.ibm.icu.dev.test.util; 10 11 import java.util.Arrays; 12 13 import org.junit.Test; 14 import org.junit.runner.RunWith; 15 import org.junit.runners.JUnit4; 16 17 import com.ibm.icu.dev.test.TestFmwk; 18 import com.ibm.icu.util.IllformedLocaleException; 19 import com.ibm.icu.util.ULocale; 20 import com.ibm.icu.util.ULocale.Builder; 21 22 /** 23 * Test cases for ULocale.LocaleBuilder 24 */ 25 @RunWith(JUnit4.class) 26 public class LocaleBuilderTest extends TestFmwk { 27 @Test TestLocaleBuilder()28 public void TestLocaleBuilder() { 29 // "L": +1 = language 30 // "S": +1 = script 31 // "R": +1 = region 32 // "V": +1 = variant 33 // "K": +1 = Unicode locale key / +2 = Unicode locale type 34 // "A": +1 = Unicode locale attribute 35 // "E": +1 = extension letter / +2 = extension value 36 // "P": +1 = private use 37 // "U": +1 = ULocale 38 // "B": +1 = BCP47 language tag 39 40 // "C": Clear all 41 // "N": Clear extensions 42 // "D": +1 = Unicode locale attribute to be removed 43 44 // "X": indicates an exception must be thrown 45 // "T": +1 = expected language tag / +2 = expected locale string 46 String[][] TESTCASE = { 47 {"L", "en", "R", "us", "T", "en-US", "en_US"}, 48 {"L", "en", "R", "CA", "L", null, "T", "und-CA", "_CA"}, 49 {"L", "en", "R", "CA", "L", "", "T", "und-CA", "_CA"}, 50 {"L", "en", "R", "FR", "L", "fr", "T", "fr-FR", "fr_FR"}, 51 {"L", "123", "X"}, 52 {"R", "us", "T", "und-US", "_US"}, 53 {"R", "usa", "X"}, 54 {"R", "123", "L", "it", "R", null, "T", "it", "it"}, 55 {"R", "123", "L", "it", "R", "", "T", "it", "it"}, 56 {"R", "123", "L", "en", "T", "en-123", "en_123"}, 57 {"S", "LATN", "L", "DE", "T", "de-Latn", "de_Latn"}, 58 {"L", "De", "S", "latn", "R", "de", "S", "", "T", "de-DE", "de_DE"}, 59 {"L", "De", "S", "latn", "R", "de", "S", null, "T", "de-DE", "de_DE"}, 60 {"S", "latin", "X"}, 61 {"V", "1234", "L", "en", "T", "en-1234", "en__1234"}, 62 {"V", "1234", "L", "en", "V", "5678", "T", "en-5678", "en__5678"}, 63 {"V", "1234", "L", "en", "V", null, "T", "en", "en"}, 64 {"V", "1234", "L", "en", "V", "", "T", "en", "en"}, 65 {"V", "123", "X"}, 66 {"U", "en_US", "T", "en-US", "en_US"}, 67 {"U", "en_US_WIN", "X"}, 68 {"B", "fr-FR-1606nict-u-ca-gregory-x-test", "T", "fr-FR-1606nict-u-ca-gregory-x-test", "fr_FR_1606NICT@calendar=gregorian;x=test"}, 69 {"B", "ab-cde-fghij", "T", "cde-fghij", "cde__FGHIJ"}, 70 {"B", "und-CA", "T", "und-CA", "_CA"}, 71 {"B", "en-US-x-test-lvariant-var", "T", "en-US-x-test-lvariant-var", "en_US_VAR@x=test"}, 72 {"B", "en-US-VAR", "X"}, 73 {"U", "ja_JP@calendar=japanese;currency=JPY", "L", "ko", "T", "ko-JP-u-ca-japanese-cu-jpy", "ko_JP@calendar=japanese;currency=jpy"}, 74 {"U", "ja_JP@calendar=japanese;currency=JPY", "K", "ca", null, "T", "ja-JP-u-cu-jpy", "ja_JP@currency=jpy"}, 75 {"U", "ja_JP@calendar=japanese;currency=JPY", "E", "u", "attr1-ca-gregory", "T", "ja-JP-u-attr1-ca-gregory", "ja_JP@attribute=attr1;calendar=gregorian"}, 76 {"U", "en@colnumeric=yes", "K", "kn", "", "T", "en-u-kn", "en@colnumeric=yes"}, 77 {"L", "th", "R", "th", "K", "nu", "thai", "T", "th-TH-u-nu-thai", "th_TH@numbers=thai"}, 78 {"U", "zh_Hans", "R", "sg", "K", "ca", "badcalendar", "X"}, 79 {"U", "zh_Hans", "R", "sg", "K", "cal", "gregory", "X"}, 80 {"E", "z", "ExtZ", "L", "en", "T", "en-z-extz", "en@z=extz"}, 81 {"E", "z", "ExtZ", "L", "en", "E", "z", "", "T", "en", "en"}, 82 {"E", "z", "ExtZ", "L", "en", "E", "z", null, "T", "en", "en"}, 83 {"E", "a", "x", "X"}, 84 {"E", "a", "abc_def", "T", "und-a-abc-def", "@a=abc-def"}, 85 // Design limitation - typeless u extension keyword 0a below is interpreted as a boolean value true/yes. 86 // With the legacy keyword syntax, "yes" is used for such boolean value instead of "true". 87 // However, once the legacy keyword is translated back to BCP 47 u extension, key "0a" is unknown, 88 // so "yes" is preserved - not mapped to "true". We could change the code to automatically transform 89 // "yes" to "true", but it will break roundtrip conversion if BCP 47 u extension has "0a-yes". 90 {"L", "en", "E", "u", "bbb-aaa-0a", "T", "en-u-aaa-bbb-0a", "en@0a=yes;attribute=aaa-bbb"}, 91 {"L", "fr", "R", "FR", "P", "Yoshito-ICU", "T", "fr-FR-x-yoshito-icu", "fr_FR@x=yoshito-icu"}, 92 {"L", "ja", "R", "jp", "K", "ca", "japanese", "T", "ja-JP-u-ca-japanese", "ja_JP@calendar=japanese"}, 93 {"K", "co", "PHONEBK", "K", "ca", "gregory", "L", "De", "T", "de-u-ca-gregory-co-phonebk", "de@calendar=gregorian;collation=phonebook"}, 94 {"E", "o", "OPQR", "E", "a", "aBcD", "T", "und-a-abcd-o-opqr", "@a=abcd;o=opqr"}, 95 {"E", "u", "nu-thai-ca-gregory", "L", "TH", "T", "th-u-ca-gregory-nu-thai", "th@calendar=gregorian;numbers=thai"}, 96 {"L", "en", "K", "tz", "usnyc", "R", "US", "T", "en-US-u-tz-usnyc", "en_US@timezone=America/New_York"}, 97 {"L", "de", "K", "co", "phonebk", "K", "ks", "level1", "K", "kk", "true", "T", "de-u-co-phonebk-kk-ks-level1", "de@collation=phonebook;colnormalization=yes;colstrength=primary"}, 98 {"L", "en", "R", "US", "K", "ca", "gregory", "T", "en-US-u-ca-gregory", "en_US@calendar=gregorian"}, 99 {"L", "en", "R", "US", "K", "cal", "gregory", "X"}, 100 {"L", "en", "R", "US", "K", "ca", "gregorian", "X"}, 101 {"L", "en", "R", "US", "K", "kn", "", "T", "en-US-u-kn", "en_US@colnumeric=yes"}, 102 {"B", "de-DE-u-co-phonebk", "C", "L", "pt", "T", "pt", "pt"}, 103 {"B", "ja-jp-u-ca-japanese", "N", "T", "ja-JP", "ja_JP"}, 104 {"B", "es-u-def-abc-co-trad", "A", "hij", "D", "def", "T", "es-u-abc-hij-co-trad", "es@attribute=abc-hij;collation=traditional"}, 105 {"B", "es-u-def-abc-co-trad", "A", "hij", "D", "def", "D", "def", "T", "es-u-abc-hij-co-trad", "es@attribute=abc-hij;collation=traditional"}, 106 {"L", "en", "A", "aa", "X"}, 107 {"B", "fr-u-attr1-cu-eur", "D", "attribute1", "X"}, 108 }; 109 110 Builder bld_st = new Builder(); 111 112 for (int tidx = 0; tidx < TESTCASE.length; tidx++) { 113 int i = 0; 114 String[] expected = null; 115 116 Builder bld = bld_st; 117 118 bld.clear(); 119 120 while (true) { 121 String method = TESTCASE[tidx][i++]; 122 try { 123 // setters 124 if (method.equals("L")) { 125 bld.setLanguage(TESTCASE[tidx][i++]); 126 } else if (method.equals("S")) { 127 bld.setScript(TESTCASE[tidx][i++]); 128 } else if (method.equals("R")) { 129 bld.setRegion(TESTCASE[tidx][i++]); 130 } else if (method.equals("V")) { 131 bld.setVariant(TESTCASE[tidx][i++]); 132 } else if (method.equals("K")) { 133 String key = TESTCASE[tidx][i++]; 134 String type = TESTCASE[tidx][i++]; 135 bld.setUnicodeLocaleKeyword(key, type); 136 } else if (method.equals("A")) { 137 bld.addUnicodeLocaleAttribute(TESTCASE[tidx][i++]); 138 } else if (method.equals("E")) { 139 String key = TESTCASE[tidx][i++]; 140 String value = TESTCASE[tidx][i++]; 141 bld.setExtension(key.charAt(0), value); 142 } else if (method.equals("P")) { 143 bld.setExtension(ULocale.PRIVATE_USE_EXTENSION, TESTCASE[tidx][i++]); 144 } else if (method.equals("U")) { 145 bld.setLocale(new ULocale(TESTCASE[tidx][i++])); 146 } else if (method.equals("B")) { 147 bld.setLanguageTag(TESTCASE[tidx][i++]); 148 } 149 // clear / remove 150 else if (method.equals("C")) { 151 bld.clear(); 152 } else if (method.equals("N")) { 153 bld.clearExtensions(); 154 } else if (method.equals("D")) { 155 bld.removeUnicodeLocaleAttribute(TESTCASE[tidx][i++]); 156 } 157 // result 158 else if (method.equals("X")) { 159 errln("FAIL: No excetion was thrown - test csae: " 160 + Arrays.toString(TESTCASE[tidx])); 161 } else if (method.equals("T")) { 162 expected = new String[2]; 163 expected[0] = TESTCASE[tidx][i]; 164 expected[1] = TESTCASE[tidx][i + 1]; 165 break; 166 } else { 167 // Unknow test method 168 errln("Unknown test case method: There is an error in the test case data."); 169 } 170 171 } catch (IllformedLocaleException e) { 172 if (TESTCASE[tidx][i].equals("X")) { 173 // This exception is expected 174 break; 175 } else { 176 errln("FAIL: IllformedLocaleException at offset " + i 177 + " in test case: " + Arrays.toString(TESTCASE[tidx])); 178 } 179 } 180 } 181 if (expected != null) { 182 ULocale loc = bld.build(); 183 if (!expected[1].equals(loc.toString())) { 184 errln("FAIL: Wrong locale ID - " + loc + 185 " for test case: " + Arrays.toString(TESTCASE[tidx])); 186 } 187 String langtag = loc.toLanguageTag(); 188 if (!expected[0].equals(langtag)) { 189 errln("FAIL: Wrong language tag - " + langtag + 190 " for test case: " + Arrays.toString(TESTCASE[tidx])); 191 } 192 ULocale loc1 = ULocale.forLanguageTag(langtag); 193 if (!loc.equals(loc1)) { 194 errln("FAIL: Language tag round trip failed for " + loc); 195 } 196 } 197 } 198 } 199 200 @Test TestSetLocale()201 public void TestSetLocale() { 202 ULocale loc = new ULocale("th_TH@calendar=gregorian"); 203 Builder bld = new Builder(); 204 try { 205 bld.setLocale(loc); 206 ULocale loc1 = bld.build(); 207 if (!loc.equals(loc1)) { 208 errln("FAIL: Locale loc1 " + loc1 + " was returned by the builder. Expected " + loc); 209 } 210 bld.setLanguage("").setUnicodeLocaleKeyword("ca", "buddhist") 211 .setLanguage("TH").setUnicodeLocaleKeyword("ca", "gregory"); 212 ULocale loc2 = bld.build(); 213 if (!loc.equals(loc2)) { 214 errln("FAIL: Locale loc2 " + loc2 + " was returned by the builder. Expected " + loc); 215 } 216 } catch (IllformedLocaleException e) { 217 errln("FAIL: IllformedLocaleException: " + e.getMessage()); 218 } 219 } 220 } 221