1 /******************************************************************** 2 * Copyright (c) 2008-2012, International Business Machines Corporation and 3 * others. All Rights Reserved. 4 ********************************************************************/ 5 6 #include "unicode/utypes.h" 7 8 #if !UCONFIG_NO_FORMATTING 9 10 #include "unicode/tmunit.h" 11 #include "unicode/tmutamt.h" 12 #include "unicode/tmutfmt.h" 13 #include "tufmtts.h" 14 #include "unicode/ustring.h" 15 16 //TODO: put as compilation flag 17 //#define TUFMTTS_DEBUG 1 18 19 #ifdef TUFMTTS_DEBUG 20 #include <iostream> 21 #endif 22 23 void TimeUnitTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) { 24 if (exec) logln("TestSuite TimeUnitTest"); 25 switch (index) { 26 TESTCASE(0, testBasic); 27 TESTCASE(1, testAPI); 28 TESTCASE(2, testGreekWithFallback); 29 TESTCASE(3, testGreekWithSanitization); 30 default: name = ""; break; 31 } 32 } 33 34 /** 35 * Test basic 36 */ 37 void TimeUnitTest::testBasic() { 38 const char* locales[] = {"en", "sl", "fr", "zh", "ar", "ru", "zh_Hant", "pa"}; 39 for ( unsigned int locIndex = 0; 40 locIndex < sizeof(locales)/sizeof(locales[0]); 41 ++locIndex ) { 42 UErrorCode status = U_ZERO_ERROR; 43 Locale loc(locales[locIndex]); 44 TimeUnitFormat** formats = new TimeUnitFormat*[2]; 45 formats[UTMUTFMT_FULL_STYLE] = new TimeUnitFormat(loc, status); 46 if (!assertSuccess("TimeUnitFormat(full)", status, TRUE)) return; 47 formats[UTMUTFMT_ABBREVIATED_STYLE] = new TimeUnitFormat(loc, UTMUTFMT_ABBREVIATED_STYLE, status); 48 if (!assertSuccess("TimeUnitFormat(short)", status)) return; 49 #ifdef TUFMTTS_DEBUG 50 std::cout << "locale: " << locales[locIndex] << "\n"; 51 #endif 52 for (int style = UTMUTFMT_FULL_STYLE; 53 style <= UTMUTFMT_ABBREVIATED_STYLE; 54 ++style) { 55 for (TimeUnit::UTimeUnitFields j = TimeUnit::UTIMEUNIT_YEAR; 56 j < TimeUnit::UTIMEUNIT_FIELD_COUNT; 57 j = (TimeUnit::UTimeUnitFields)(j+1)) { 58 #ifdef TUFMTTS_DEBUG 59 std::cout << "time unit: " << j << "\n"; 60 #endif 61 double tests[] = {0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 5, 10, 100, 101.35}; 62 for (unsigned int i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) { 63 #ifdef TUFMTTS_DEBUG 64 std::cout << "number: " << tests[i] << "\n"; 65 #endif 66 TimeUnitAmount* source = new TimeUnitAmount(tests[i], j, status); 67 if (!assertSuccess("TimeUnitAmount()", status)) return; 68 UnicodeString formatted; 69 Formattable formattable; 70 formattable.adoptObject(source); 71 formatted = ((Format*)formats[style])->format(formattable, formatted, status); 72 if (!assertSuccess("format()", status)) return; 73 #ifdef TUFMTTS_DEBUG 74 char formatResult[1000]; 75 formatted.extract(0, formatted.length(), formatResult, "UTF-8"); 76 std::cout << "format result: " << formatResult << "\n"; 77 #endif 78 Formattable result; 79 ((Format*)formats[style])->parseObject(formatted, result, status); 80 if (!assertSuccess("parseObject()", status)) return; 81 if (result != formattable) { 82 dataerrln("No round trip: "); 83 } 84 // other style parsing 85 Formattable result_1; 86 ((Format*)formats[1-style])->parseObject(formatted, result_1, status); 87 if (!assertSuccess("parseObject()", status)) return; 88 if (result_1 != formattable) { 89 dataerrln("No round trip: "); 90 } 91 } 92 } 93 } 94 delete formats[UTMUTFMT_FULL_STYLE]; 95 delete formats[UTMUTFMT_ABBREVIATED_STYLE]; 96 delete[] formats; 97 } 98 } 99 100 101 void TimeUnitTest::testAPI() { 102 //================= TimeUnit ================= 103 UErrorCode status = U_ZERO_ERROR; 104 105 TimeUnit* tmunit = TimeUnit::createInstance(TimeUnit::UTIMEUNIT_YEAR, status); 106 if (!assertSuccess("TimeUnit::createInstance", status)) return; 107 108 TimeUnit* another = (TimeUnit*)tmunit->clone(); 109 TimeUnit third(*tmunit); 110 TimeUnit fourth = third; 111 112 assertTrue("orig and clone are equal", (*tmunit == *another)); 113 assertTrue("copied and assigned are equal", (third == fourth)); 114 115 TimeUnit* tmunit_m = TimeUnit::createInstance(TimeUnit::UTIMEUNIT_MONTH, status); 116 assertTrue("year != month", (*tmunit != *tmunit_m)); 117 118 TimeUnit::UTimeUnitFields field = tmunit_m->getTimeUnitField(); 119 assertTrue("field of month time unit is month", (field == TimeUnit::UTIMEUNIT_MONTH)); 120 121 delete tmunit; 122 delete another; 123 delete tmunit_m; 124 // 125 //================= TimeUnitAmount ================= 126 127 Formattable formattable((int32_t)2); 128 TimeUnitAmount tma_long(formattable, TimeUnit::UTIMEUNIT_DAY, status); 129 if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return; 130 131 formattable.setDouble(2); 132 TimeUnitAmount tma_double(formattable, TimeUnit::UTIMEUNIT_DAY, status); 133 if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return; 134 135 formattable.setDouble(3); 136 TimeUnitAmount tma_double_3(formattable, TimeUnit::UTIMEUNIT_DAY, status); 137 if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return; 138 139 TimeUnitAmount tma(2, TimeUnit::UTIMEUNIT_DAY, status); 140 if (!assertSuccess("TimeUnitAmount(number...)", status)) return; 141 142 TimeUnitAmount tma_h(2, TimeUnit::UTIMEUNIT_HOUR, status); 143 if (!assertSuccess("TimeUnitAmount(number...)", status)) return; 144 145 TimeUnitAmount second(tma); 146 TimeUnitAmount third_tma = tma; 147 TimeUnitAmount* fourth_tma = (TimeUnitAmount*)tma.clone(); 148 149 assertTrue("orig and copy are equal", (second == tma)); 150 assertTrue("clone and assigned are equal", (third_tma == *fourth_tma)); 151 assertTrue("different if number diff", (tma_double != tma_double_3)); 152 assertTrue("different if number type diff", (tma_double != tma_long)); 153 assertTrue("different if time unit diff", (tma != tma_h)); 154 assertTrue("same even different constructor", (tma_double == tma)); 155 156 assertTrue("getTimeUnitField", (tma.getTimeUnitField() == TimeUnit::UTIMEUNIT_DAY)); 157 delete fourth_tma; 158 // 159 //================= TimeUnitFormat ================= 160 // 161 TimeUnitFormat* tmf_en = new TimeUnitFormat(Locale("en"), status); 162 if (!assertSuccess("TimeUnitFormat(en...)", status, TRUE)) return; 163 TimeUnitFormat tmf_fr(Locale("fr"), status); 164 if (!assertSuccess("TimeUnitFormat(fr...)", status)) return; 165 166 assertTrue("TimeUnitFormat: en and fr diff", (*tmf_en != tmf_fr)); 167 168 TimeUnitFormat tmf_assign = *tmf_en; 169 assertTrue("TimeUnitFormat: orig and assign are equal", (*tmf_en == tmf_assign)); 170 171 TimeUnitFormat tmf_copy(tmf_fr); 172 assertTrue("TimeUnitFormat: orig and copy are equal", (tmf_fr == tmf_copy)); 173 174 TimeUnitFormat* tmf_clone = (TimeUnitFormat*)tmf_en->clone(); 175 assertTrue("TimeUnitFormat: orig and clone are equal", (*tmf_en == *tmf_clone)); 176 delete tmf_clone; 177 178 tmf_en->setLocale(Locale("fr"), status); 179 if (!assertSuccess("setLocale(fr...)", status)) return; 180 181 NumberFormat* numberFmt = NumberFormat::createInstance( 182 Locale("fr"), status); 183 if (!assertSuccess("NumberFormat::createInstance()", status)) return; 184 tmf_en->setNumberFormat(*numberFmt, status); 185 if (!assertSuccess("setNumberFormat(en...)", status)) return; 186 assertTrue("TimeUnitFormat: setLocale", (*tmf_en == tmf_fr)); 187 188 delete tmf_en; 189 190 TimeUnitFormat* en_long = new TimeUnitFormat(Locale("en"), UTMUTFMT_FULL_STYLE, status); 191 if (!assertSuccess("TimeUnitFormat(en...)", status)) return; 192 delete en_long; 193 194 TimeUnitFormat* en_short = new TimeUnitFormat(Locale("en"), UTMUTFMT_ABBREVIATED_STYLE, status); 195 if (!assertSuccess("TimeUnitFormat(en...)", status)) return; 196 delete en_short; 197 198 TimeUnitFormat* format = new TimeUnitFormat(status); 199 format->setLocale(Locale("zh"), status); 200 format->setNumberFormat(*numberFmt, status); 201 if (!assertSuccess("TimeUnitFormat(en...)", status)) return; 202 delete numberFmt; 203 delete format; 204 } 205 206 /* @bug 7902 207 * Tests for Greek Language. 208 * This tests that requests for short unit names correctly fall back 209 * to long unit names for a locale where the locale data does not 210 * provide short unit names. As of CLDR 1.9, Greek is one such language. 211 */ 212 void TimeUnitTest::testGreekWithFallback() { 213 UErrorCode status = U_ZERO_ERROR; 214 215 const char* locales[] = {"el-GR", "el"}; 216 TimeUnit::UTimeUnitFields tunits[] = {TimeUnit::UTIMEUNIT_SECOND, TimeUnit::UTIMEUNIT_MINUTE, TimeUnit::UTIMEUNIT_HOUR, TimeUnit::UTIMEUNIT_DAY, TimeUnit::UTIMEUNIT_MONTH, TimeUnit::UTIMEUNIT_YEAR}; 217 UTimeUnitFormatStyle styles[] = {UTMUTFMT_FULL_STYLE, UTMUTFMT_ABBREVIATED_STYLE}; 218 const int numbers[] = {1, 7}; 219 220 const UChar oneSecond[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03bf, 0}; 221 const UChar oneMinute[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03cc, 0}; 222 const UChar oneHour[] = {0x0031, 0x0020, 0x03ce, 0x03c1, 0x03b1, 0}; 223 const UChar oneDay[] = {0x0031, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b1, 0}; 224 const UChar oneMonth[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b1, 0x03c2, 0}; 225 const UChar oneYear[] = {0x0031, 0x0020, 0x03ad, 0x03c4, 0x03bf, 0x03c2, 0}; 226 const UChar sevenSeconds[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03b1, 0}; 227 const UChar sevenMinutes[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03ac, 0}; 228 const UChar sevenHours[] = {0x0037, 0x0020, 0x03ce, 0x03c1, 0x03b5, 0x03c2, 0}; 229 const UChar sevenDays[] = {0x0037, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b5, 0x03c2, 0}; 230 const UChar sevenMonths[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b5, 0x3c2, 0}; 231 const UChar sevenYears[] = {0x0037, 0x0020, 0x03ad, 0x03c4, 0x03b7, 0}; 232 233 const UnicodeString oneSecondStr(oneSecond); 234 const UnicodeString oneMinuteStr(oneMinute); 235 const UnicodeString oneHourStr(oneHour); 236 const UnicodeString oneDayStr(oneDay); 237 const UnicodeString oneMonthStr(oneMonth); 238 const UnicodeString oneYearStr(oneYear); 239 const UnicodeString sevenSecondsStr(sevenSeconds); 240 const UnicodeString sevenMinutesStr(sevenMinutes); 241 const UnicodeString sevenHoursStr(sevenHours); 242 const UnicodeString sevenDaysStr(sevenDays); 243 const UnicodeString sevenMonthsStr(sevenMonths); 244 const UnicodeString sevenYearsStr(sevenYears); 245 246 const UnicodeString expected[] = {oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr, 247 oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr, 248 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr, 249 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr, 250 oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr, 251 oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr, 252 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr, 253 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr}; 254 255 int counter = 0; 256 for ( unsigned int locIndex = 0; 257 locIndex < sizeof(locales)/sizeof(locales[0]); 258 ++locIndex ) { 259 260 Locale l = Locale::createFromName(locales[locIndex]); 261 262 for ( unsigned int numberIndex = 0; 263 numberIndex < sizeof(numbers)/sizeof(int); 264 ++numberIndex ) { 265 266 for ( unsigned int styleIndex = 0; 267 styleIndex < sizeof(styles)/sizeof(styles[0]); 268 ++styleIndex ) { 269 270 for ( unsigned int unitIndex = 0; 271 unitIndex < sizeof(tunits)/sizeof(tunits[0]); 272 ++unitIndex ) { 273 274 TimeUnitAmount *tamt = new TimeUnitAmount(numbers[numberIndex], tunits[unitIndex], status); 275 if (U_FAILURE(status)) { 276 dataerrln("generating TimeUnitAmount Object failed."); 277 #ifdef TUFMTTS_DEBUG 278 std::cout << "Failed to get TimeUnitAmount for " << tunits[unitIndex] << "\n"; 279 #endif 280 return; 281 } 282 283 TimeUnitFormat *tfmt = new TimeUnitFormat(l, styles[styleIndex], status); 284 if (U_FAILURE(status)) { 285 dataerrln("generating TimeUnitAmount Object failed."); 286 #ifdef TUFMTTS_DEBUG 287 std::cout << "Failed to get TimeUnitFormat for " << locales[locIndex] << "\n"; 288 #endif 289 return; 290 } 291 292 Formattable fmt; 293 UnicodeString str; 294 295 fmt.adoptObject(tamt); 296 str = ((Format *)tfmt)->format(fmt, str, status); 297 if (!assertSuccess("formatting relative time failed", status)) { 298 delete tfmt; 299 #ifdef TUFMTTS_DEBUG 300 std::cout << "Failed to format" << "\n"; 301 #endif 302 return; 303 } 304 305 #ifdef TUFMTTS_DEBUG 306 char tmp[128]; //output 307 char tmp1[128]; //expected 308 int len = 0; 309 u_strToUTF8(tmp, 128, &len, str.getTerminatedBuffer(), str.length(), &status); 310 u_strToUTF8(tmp1, 128, &len, expected[counter].unescape().getTerminatedBuffer(), expected[counter].unescape().length(), &status); 311 std::cout << "Formatted string : " << tmp << " expected : " << tmp1 << "\n"; 312 #endif 313 if (!assertEquals("formatted time string is not expected, locale: " + UnicodeString(locales[locIndex]) + " style: " + (int)styles[styleIndex] + " units: " + (int)tunits[unitIndex], expected[counter], str)) { 314 delete tfmt; 315 str.remove(); 316 return; 317 } 318 delete tfmt; 319 str.remove(); 320 ++counter; 321 } 322 } 323 } 324 } 325 } 326 327 // Test bug9042 328 void TimeUnitTest::testGreekWithSanitization() { 329 330 UErrorCode status = U_ZERO_ERROR; 331 Locale elLoc("el"); 332 NumberFormat* numberFmt = NumberFormat::createInstance(Locale("el"), status); 333 if (!assertSuccess("NumberFormat::createInstance for el locale", status, TRUE)) return; 334 numberFmt->setMaximumFractionDigits(1); 335 336 TimeUnitFormat* timeUnitFormat = new TimeUnitFormat(elLoc, status); 337 if (!assertSuccess("TimeUnitFormat::TimeUnitFormat for el locale", status)) return; 338 339 timeUnitFormat->setNumberFormat(*numberFmt, status); 340 341 delete numberFmt; 342 delete timeUnitFormat; 343 } 344 345 346 #endif 347