1 /******************************************************************** 2 * Copyright (c) 2008-2013, 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 oneSecondShort[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0}; 222 const UChar oneMinute[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03cc, 0}; 223 const UChar oneMinuteShort[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0}; 224 const UChar oneHour[] = {0x0031, 0x0020, 0x03ce, 0x03c1, 0x03b1, 0}; 225 const UChar oneDay[] = {0x0031, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b1, 0}; 226 const UChar oneMonth[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b1, 0x03c2, 0}; 227 const UChar oneMonthShort[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0}; 228 const UChar oneYear[] = {0x0031, 0x0020, 0x03ad, 0x03c4, 0x03bf, 0x03c2, 0}; 229 const UChar sevenSeconds[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03b1, 0}; 230 const UChar sevenSecondsShort[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0}; 231 const UChar sevenMinutes[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03ac, 0}; 232 const UChar sevenMinutesShort[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0}; 233 const UChar sevenHours[] = {0x0037, 0x0020, 0x03ce, 0x03c1, 0x03b5, 0x03c2, 0}; 234 const UChar sevenDays[] = {0x0037, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b5, 0x03c2, 0}; 235 const UChar sevenMonths[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b5, 0x3c2, 0}; 236 const UChar sevenMonthsShort[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0}; 237 const UChar sevenYears[] = {0x0037, 0x0020, 0x03ad, 0x03c4, 0x03b7, 0}; 238 239 const UnicodeString oneSecondStr(oneSecond); 240 const UnicodeString oneSecondShortStr(oneSecondShort); 241 const UnicodeString oneMinuteStr(oneMinute); 242 const UnicodeString oneMinuteShortStr(oneMinuteShort); 243 const UnicodeString oneHourStr(oneHour); 244 const UnicodeString oneDayStr(oneDay); 245 const UnicodeString oneMonthStr(oneMonth); 246 const UnicodeString oneMonthShortStr(oneMonthShort); 247 const UnicodeString oneYearStr(oneYear); 248 const UnicodeString sevenSecondsStr(sevenSeconds); 249 const UnicodeString sevenSecondsShortStr(sevenSecondsShort); 250 const UnicodeString sevenMinutesStr(sevenMinutes); 251 const UnicodeString sevenMinutesShortStr(sevenMinutesShort); 252 const UnicodeString sevenHoursStr(sevenHours); 253 const UnicodeString sevenDaysStr(sevenDays); 254 const UnicodeString sevenMonthsStr(sevenMonths); 255 const UnicodeString sevenMonthsShortStr(sevenMonthsShort); 256 const UnicodeString sevenYearsStr(sevenYears); 257 258 const UnicodeString expected[] = {oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr, 259 oneSecondShortStr, oneMinuteShortStr, oneHourStr, oneDayStr, oneMonthShortStr, oneYearStr, 260 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr, 261 sevenSecondsShortStr, sevenMinutesShortStr, sevenHoursStr, sevenDaysStr, sevenMonthsShortStr, sevenYearsStr, 262 oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr, 263 oneSecondShortStr, oneMinuteShortStr, oneHourStr, oneDayStr, oneMonthShortStr, oneYearStr, 264 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr, 265 sevenSecondsShortStr, sevenMinutesShortStr, sevenHoursStr, sevenDaysStr, sevenMonthsShortStr, sevenYearsStr}; 266 267 int counter = 0; 268 for ( unsigned int locIndex = 0; 269 locIndex < sizeof(locales)/sizeof(locales[0]); 270 ++locIndex ) { 271 272 Locale l = Locale::createFromName(locales[locIndex]); 273 274 for ( unsigned int numberIndex = 0; 275 numberIndex < sizeof(numbers)/sizeof(int); 276 ++numberIndex ) { 277 278 for ( unsigned int styleIndex = 0; 279 styleIndex < sizeof(styles)/sizeof(styles[0]); 280 ++styleIndex ) { 281 282 for ( unsigned int unitIndex = 0; 283 unitIndex < sizeof(tunits)/sizeof(tunits[0]); 284 ++unitIndex ) { 285 286 TimeUnitAmount *tamt = new TimeUnitAmount(numbers[numberIndex], tunits[unitIndex], status); 287 if (U_FAILURE(status)) { 288 dataerrln("generating TimeUnitAmount Object failed."); 289 #ifdef TUFMTTS_DEBUG 290 std::cout << "Failed to get TimeUnitAmount for " << tunits[unitIndex] << "\n"; 291 #endif 292 return; 293 } 294 295 TimeUnitFormat *tfmt = new TimeUnitFormat(l, styles[styleIndex], status); 296 if (U_FAILURE(status)) { 297 dataerrln("generating TimeUnitAmount Object failed."); 298 #ifdef TUFMTTS_DEBUG 299 std::cout << "Failed to get TimeUnitFormat for " << locales[locIndex] << "\n"; 300 #endif 301 return; 302 } 303 304 Formattable fmt; 305 UnicodeString str; 306 307 fmt.adoptObject(tamt); 308 str = ((Format *)tfmt)->format(fmt, str, status); 309 if (!assertSuccess("formatting relative time failed", status)) { 310 delete tfmt; 311 #ifdef TUFMTTS_DEBUG 312 std::cout << "Failed to format" << "\n"; 313 #endif 314 return; 315 } 316 317 #ifdef TUFMTTS_DEBUG 318 char tmp[128]; //output 319 char tmp1[128]; //expected 320 int len = 0; 321 u_strToUTF8(tmp, 128, &len, str.getTerminatedBuffer(), str.length(), &status); 322 u_strToUTF8(tmp1, 128, &len, expected[counter].unescape().getTerminatedBuffer(), expected[counter].unescape().length(), &status); 323 std::cout << "Formatted string : " << tmp << " expected : " << tmp1 << "\n"; 324 #endif 325 if (!assertEquals("formatted time string is not expected, locale: " + UnicodeString(locales[locIndex]) + " style: " + (int)styles[styleIndex] + " units: " + (int)tunits[unitIndex], expected[counter], str)) { 326 delete tfmt; 327 str.remove(); 328 return; 329 } 330 delete tfmt; 331 str.remove(); 332 ++counter; 333 } 334 } 335 } 336 } 337 } 338 339 // Test bug9042 340 void TimeUnitTest::testGreekWithSanitization() { 341 342 UErrorCode status = U_ZERO_ERROR; 343 Locale elLoc("el"); 344 NumberFormat* numberFmt = NumberFormat::createInstance(Locale("el"), status); 345 if (!assertSuccess("NumberFormat::createInstance for el locale", status, TRUE)) return; 346 numberFmt->setMaximumFractionDigits(1); 347 348 TimeUnitFormat* timeUnitFormat = new TimeUnitFormat(elLoc, status); 349 if (!assertSuccess("TimeUnitFormat::TimeUnitFormat for el locale", status)) return; 350 351 timeUnitFormat->setNumberFormat(*numberFmt, status); 352 353 delete numberFmt; 354 delete timeUnitFormat; 355 } 356 357 #endif 358