1 /******************************************************************** 2 * Copyright (c) 2008-2014, 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/decimfmt.h" 11 #include "unicode/tmunit.h" 12 #include "unicode/tmutamt.h" 13 #include "unicode/tmutfmt.h" 14 #include "tufmtts.h" 15 #include "unicode/ustring.h" 16 17 //TODO: put as compilation flag 18 //#define TUFMTTS_DEBUG 1 19 20 #ifdef TUFMTTS_DEBUG 21 #include <iostream> 22 #endif 23 24 #define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 25 26 void TimeUnitTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) { 27 if (exec) logln("TestSuite TimeUnitTest"); 28 switch (index) { 29 TESTCASE(0, testBasic); 30 TESTCASE(1, testAPI); 31 TESTCASE(2, testGreekWithFallback); 32 TESTCASE(3, testGreekWithSanitization); 33 TESTCASE(4, test10219Plurals); 34 default: name = ""; break; 35 } 36 } 37 38 // This function is more lenient than equals operator as it considers integer 3 hours and 39 // double 3.0 hours to be equal 40 static UBool tmaEqual(const TimeUnitAmount& left, const TimeUnitAmount& right) { 41 if (left.getTimeUnitField() != right.getTimeUnitField()) { 42 return FALSE; 43 } 44 UErrorCode status = U_ZERO_ERROR; 45 if (!left.getNumber().isNumeric() || !right.getNumber().isNumeric()) { 46 return FALSE; 47 } 48 UBool result = left.getNumber().getDouble(status) == right.getNumber().getDouble(status); 49 if (U_FAILURE(status)) { 50 return FALSE; 51 } 52 return result; 53 } 54 55 /** 56 * Test basic 57 */ 58 void TimeUnitTest::testBasic() { 59 const char* locales[] = {"en", "sl", "fr", "zh", "ar", "ru", "zh_Hant", "pa"}; 60 for ( unsigned int locIndex = 0; 61 locIndex < sizeof(locales)/sizeof(locales[0]); 62 ++locIndex ) { 63 UErrorCode status = U_ZERO_ERROR; 64 Locale loc(locales[locIndex]); 65 TimeUnitFormat** formats = new TimeUnitFormat*[2]; 66 formats[UTMUTFMT_FULL_STYLE] = new TimeUnitFormat(loc, status); 67 if (!assertSuccess("TimeUnitFormat(full)", status, TRUE)) return; 68 formats[UTMUTFMT_ABBREVIATED_STYLE] = new TimeUnitFormat(loc, UTMUTFMT_ABBREVIATED_STYLE, status); 69 if (!assertSuccess("TimeUnitFormat(short)", status)) return; 70 #ifdef TUFMTTS_DEBUG 71 std::cout << "locale: " << locales[locIndex] << "\n"; 72 #endif 73 for (int style = UTMUTFMT_FULL_STYLE; 74 style <= UTMUTFMT_ABBREVIATED_STYLE; 75 ++style) { 76 for (TimeUnit::UTimeUnitFields j = TimeUnit::UTIMEUNIT_YEAR; 77 j < TimeUnit::UTIMEUNIT_FIELD_COUNT; 78 j = (TimeUnit::UTimeUnitFields)(j+1)) { 79 #ifdef TUFMTTS_DEBUG 80 std::cout << "time unit: " << j << "\n"; 81 #endif 82 double tests[] = {0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 5, 10, 100, 101.35}; 83 for (unsigned int i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) { 84 #ifdef TUFMTTS_DEBUG 85 std::cout << "number: " << tests[i] << "\n"; 86 #endif 87 TimeUnitAmount* source = new TimeUnitAmount(tests[i], j, status); 88 if (!assertSuccess("TimeUnitAmount()", status)) return; 89 UnicodeString formatted; 90 Formattable formattable; 91 formattable.adoptObject(source); 92 formatted = ((Format*)formats[style])->format(formattable, formatted, status); 93 if (!assertSuccess("format()", status)) return; 94 #ifdef TUFMTTS_DEBUG 95 char formatResult[1000]; 96 formatted.extract(0, formatted.length(), formatResult, "UTF-8"); 97 std::cout << "format result: " << formatResult << "\n"; 98 #endif 99 Formattable result; 100 ((Format*)formats[style])->parseObject(formatted, result, status); 101 if (!assertSuccess("parseObject()", status)) return; 102 if (!tmaEqual(*((TimeUnitAmount *)result.getObject()), *((TimeUnitAmount *) formattable.getObject()))) { 103 dataerrln("No round trip: "); 104 } 105 // other style parsing 106 Formattable result_1; 107 ((Format*)formats[1-style])->parseObject(formatted, result_1, status); 108 if (!assertSuccess("parseObject()", status)) return; 109 if (!tmaEqual(*((TimeUnitAmount *)result_1.getObject()), *((TimeUnitAmount *) formattable.getObject()))) { 110 dataerrln("No round trip: "); 111 } 112 } 113 } 114 } 115 delete formats[UTMUTFMT_FULL_STYLE]; 116 delete formats[UTMUTFMT_ABBREVIATED_STYLE]; 117 delete[] formats; 118 } 119 } 120 121 122 void TimeUnitTest::testAPI() { 123 //================= TimeUnit ================= 124 UErrorCode status = U_ZERO_ERROR; 125 126 TimeUnit* tmunit = TimeUnit::createInstance(TimeUnit::UTIMEUNIT_YEAR, status); 127 if (!assertSuccess("TimeUnit::createInstance", status)) return; 128 129 TimeUnit* another = (TimeUnit*)tmunit->clone(); 130 TimeUnit third(*tmunit); 131 TimeUnit fourth = third; 132 133 assertTrue("orig and clone are equal", (*tmunit == *another)); 134 assertTrue("copied and assigned are equal", (third == fourth)); 135 136 TimeUnit* tmunit_m = TimeUnit::createInstance(TimeUnit::UTIMEUNIT_MONTH, status); 137 assertTrue("year != month", (*tmunit != *tmunit_m)); 138 139 TimeUnit::UTimeUnitFields field = tmunit_m->getTimeUnitField(); 140 assertTrue("field of month time unit is month", (field == TimeUnit::UTIMEUNIT_MONTH)); 141 142 //===== Interoperability with MeasureUnit ====== 143 MeasureUnit **ptrs = new MeasureUnit *[TimeUnit::UTIMEUNIT_FIELD_COUNT]; 144 145 ptrs[TimeUnit::UTIMEUNIT_YEAR] = MeasureUnit::createYear(status); 146 ptrs[TimeUnit::UTIMEUNIT_MONTH] = MeasureUnit::createMonth(status); 147 ptrs[TimeUnit::UTIMEUNIT_DAY] = MeasureUnit::createDay(status); 148 ptrs[TimeUnit::UTIMEUNIT_WEEK] = MeasureUnit::createWeek(status); 149 ptrs[TimeUnit::UTIMEUNIT_HOUR] = MeasureUnit::createHour(status); 150 ptrs[TimeUnit::UTIMEUNIT_MINUTE] = MeasureUnit::createMinute(status); 151 ptrs[TimeUnit::UTIMEUNIT_SECOND] = MeasureUnit::createSecond(status); 152 if (!assertSuccess("TimeUnit::createInstance", status)) return; 153 154 for (TimeUnit::UTimeUnitFields j = TimeUnit::UTIMEUNIT_YEAR; 155 j < TimeUnit::UTIMEUNIT_FIELD_COUNT; 156 j = (TimeUnit::UTimeUnitFields)(j+1)) { 157 MeasureUnit *ptr = TimeUnit::createInstance(j, status); 158 if (!assertSuccess("TimeUnit::createInstance", status)) return; 159 // We have to convert *ptr to a MeasureUnit or else == will fail over 160 // differing types (TimeUnit vs. MeasureUnit). 161 assertTrue( 162 "Time unit should be equal to corresponding MeasureUnit", 163 MeasureUnit(*ptr) == *ptrs[j]); 164 delete ptr; 165 } 166 delete tmunit; 167 delete another; 168 delete tmunit_m; 169 for (int i = 0; i < TimeUnit::UTIMEUNIT_FIELD_COUNT; ++i) { 170 delete ptrs[i]; 171 } 172 delete [] ptrs; 173 174 // 175 //================= TimeUnitAmount ================= 176 177 Formattable formattable((int32_t)2); 178 TimeUnitAmount tma_long(formattable, TimeUnit::UTIMEUNIT_DAY, status); 179 if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return; 180 181 formattable.setDouble(2); 182 TimeUnitAmount tma_double(formattable, TimeUnit::UTIMEUNIT_DAY, status); 183 if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return; 184 185 formattable.setDouble(3); 186 TimeUnitAmount tma_double_3(formattable, TimeUnit::UTIMEUNIT_DAY, status); 187 if (!assertSuccess("TimeUnitAmount(formattable...)", status)) return; 188 189 TimeUnitAmount tma(2, TimeUnit::UTIMEUNIT_DAY, status); 190 if (!assertSuccess("TimeUnitAmount(number...)", status)) return; 191 192 TimeUnitAmount tma_h(2, TimeUnit::UTIMEUNIT_HOUR, status); 193 if (!assertSuccess("TimeUnitAmount(number...)", status)) return; 194 195 TimeUnitAmount second(tma); 196 TimeUnitAmount third_tma = tma; 197 TimeUnitAmount* fourth_tma = (TimeUnitAmount*)tma.clone(); 198 199 assertTrue("orig and copy are equal", (second == tma)); 200 assertTrue("clone and assigned are equal", (third_tma == *fourth_tma)); 201 assertTrue("different if number diff", (tma_double != tma_double_3)); 202 assertTrue("different if number type diff", (tma_double != tma_long)); 203 assertTrue("different if time unit diff", (tma != tma_h)); 204 assertTrue("same even different constructor", (tma_double == tma)); 205 206 assertTrue("getTimeUnitField", (tma.getTimeUnitField() == TimeUnit::UTIMEUNIT_DAY)); 207 delete fourth_tma; 208 // 209 //================= TimeUnitFormat ================= 210 // 211 TimeUnitFormat* tmf_en = new TimeUnitFormat(Locale("en"), status); 212 if (!assertSuccess("TimeUnitFormat(en...)", status, TRUE)) return; 213 TimeUnitFormat tmf_fr(Locale("fr"), status); 214 if (!assertSuccess("TimeUnitFormat(fr...)", status)) return; 215 216 assertTrue("TimeUnitFormat: en and fr diff", (*tmf_en != tmf_fr)); 217 218 TimeUnitFormat tmf_assign = *tmf_en; 219 assertTrue("TimeUnitFormat: orig and assign are equal", (*tmf_en == tmf_assign)); 220 221 TimeUnitFormat tmf_copy(tmf_fr); 222 assertTrue("TimeUnitFormat: orig and copy are equal", (tmf_fr == tmf_copy)); 223 224 TimeUnitFormat* tmf_clone = (TimeUnitFormat*)tmf_en->clone(); 225 assertTrue("TimeUnitFormat: orig and clone are equal", (*tmf_en == *tmf_clone)); 226 delete tmf_clone; 227 228 tmf_en->setLocale(Locale("fr"), status); 229 if (!assertSuccess("setLocale(fr...)", status)) return; 230 231 NumberFormat* numberFmt = NumberFormat::createInstance( 232 Locale("fr"), status); 233 if (!assertSuccess("NumberFormat::createInstance()", status)) return; 234 tmf_en->setNumberFormat(*numberFmt, status); 235 if (!assertSuccess("setNumberFormat(en...)", status)) return; 236 assertTrue("TimeUnitFormat: setLocale", (*tmf_en == tmf_fr)); 237 238 delete tmf_en; 239 240 TimeUnitFormat* en_long = new TimeUnitFormat(Locale("en"), UTMUTFMT_FULL_STYLE, status); 241 if (!assertSuccess("TimeUnitFormat(en...)", status)) return; 242 delete en_long; 243 244 TimeUnitFormat* en_short = new TimeUnitFormat(Locale("en"), UTMUTFMT_ABBREVIATED_STYLE, status); 245 if (!assertSuccess("TimeUnitFormat(en...)", status)) return; 246 delete en_short; 247 248 TimeUnitFormat* format = new TimeUnitFormat(status); 249 format->setLocale(Locale("zh"), status); 250 format->setNumberFormat(*numberFmt, status); 251 if (!assertSuccess("TimeUnitFormat(en...)", status)) return; 252 delete numberFmt; 253 delete format; 254 } 255 256 /* @bug 7902 257 * Tests for Greek Language. 258 * This tests that requests for short unit names correctly fall back 259 * to long unit names for a locale where the locale data does not 260 * provide short unit names. As of CLDR 1.9, Greek is one such language. 261 */ 262 void TimeUnitTest::testGreekWithFallback() { 263 UErrorCode status = U_ZERO_ERROR; 264 265 const char* locales[] = {"el-GR", "el"}; 266 TimeUnit::UTimeUnitFields tunits[] = {TimeUnit::UTIMEUNIT_SECOND, TimeUnit::UTIMEUNIT_MINUTE, TimeUnit::UTIMEUNIT_HOUR, TimeUnit::UTIMEUNIT_DAY, TimeUnit::UTIMEUNIT_MONTH, TimeUnit::UTIMEUNIT_YEAR}; 267 UTimeUnitFormatStyle styles[] = {UTMUTFMT_FULL_STYLE, UTMUTFMT_ABBREVIATED_STYLE}; 268 const int numbers[] = {1, 7}; 269 270 const UChar oneSecond[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03bf, 0}; 271 const UChar oneSecondShort[] = {0x0031, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0}; 272 const UChar oneMinute[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03cc, 0}; 273 const UChar oneMinuteShort[] = {0x0031, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0}; 274 const UChar oneHour[] = {0x0031, 0x0020, 0x03ce, 0x03c1, 0x03b1, 0}; 275 const UChar oneDay[] = {0x0031, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b1, 0}; 276 const UChar oneMonth[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b1, 0x03c2, 0}; 277 const UChar oneMonthShort[] = {0x0031, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0}; 278 const UChar oneYear[] = {0x0031, 0x0020, 0x03ad, 0x03c4, 0x03bf, 0x03c2, 0}; 279 const UChar sevenSeconds[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x03b5, 0x03c1, 0x03cc, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03b1, 0}; 280 const UChar sevenSecondsShort[] = {0x0037, 0x0020, 0x03b4, 0x03b5, 0x03c5, 0x03c4, 0x002e, 0}; 281 const UChar sevenMinutes[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x03c4, 0x03ac, 0}; 282 const UChar sevenMinutesShort[] = {0x0037, 0x0020, 0x03bb, 0x03b5, 0x03c0, 0x002e, 0}; 283 const UChar sevenHours[] = {0x0037, 0x0020, 0x03ce, 0x03c1, 0x03b5, 0x03c2, 0}; 284 const UChar sevenDays[] = {0x0037, 0x0020, 0x03b7, 0x03bc, 0x03ad, 0x03c1, 0x03b5, 0x03c2, 0}; 285 const UChar sevenMonths[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x03b5, 0x3c2, 0}; 286 const UChar sevenMonthsShort[] = {0x0037, 0x0020, 0x03bc, 0x03ae, 0x03bd, 0x002e, 0}; 287 const UChar sevenYears[] = {0x0037, 0x0020, 0x03ad, 0x03c4, 0x03b7, 0}; 288 289 const UnicodeString oneSecondStr(oneSecond); 290 const UnicodeString oneSecondShortStr(oneSecondShort); 291 const UnicodeString oneMinuteStr(oneMinute); 292 const UnicodeString oneMinuteShortStr(oneMinuteShort); 293 const UnicodeString oneHourStr(oneHour); 294 const UnicodeString oneDayStr(oneDay); 295 const UnicodeString oneMonthStr(oneMonth); 296 const UnicodeString oneMonthShortStr(oneMonthShort); 297 const UnicodeString oneYearStr(oneYear); 298 const UnicodeString sevenSecondsStr(sevenSeconds); 299 const UnicodeString sevenSecondsShortStr(sevenSecondsShort); 300 const UnicodeString sevenMinutesStr(sevenMinutes); 301 const UnicodeString sevenMinutesShortStr(sevenMinutesShort); 302 const UnicodeString sevenHoursStr(sevenHours); 303 const UnicodeString sevenDaysStr(sevenDays); 304 const UnicodeString sevenMonthsStr(sevenMonths); 305 const UnicodeString sevenMonthsShortStr(sevenMonthsShort); 306 const UnicodeString sevenYearsStr(sevenYears); 307 308 const UnicodeString expected[] = {oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr, 309 oneSecondShortStr, oneMinuteShortStr, oneHourStr, oneDayStr, oneMonthShortStr, oneYearStr, 310 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr, 311 sevenSecondsShortStr, sevenMinutesShortStr, sevenHoursStr, sevenDaysStr, sevenMonthsShortStr, sevenYearsStr, 312 oneSecondStr, oneMinuteStr, oneHourStr, oneDayStr, oneMonthStr, oneYearStr, 313 oneSecondShortStr, oneMinuteShortStr, oneHourStr, oneDayStr, oneMonthShortStr, oneYearStr, 314 sevenSecondsStr, sevenMinutesStr, sevenHoursStr, sevenDaysStr, sevenMonthsStr, sevenYearsStr, 315 sevenSecondsShortStr, sevenMinutesShortStr, sevenHoursStr, sevenDaysStr, sevenMonthsShortStr, sevenYearsStr}; 316 317 int counter = 0; 318 for ( unsigned int locIndex = 0; 319 locIndex < sizeof(locales)/sizeof(locales[0]); 320 ++locIndex ) { 321 322 Locale l = Locale::createFromName(locales[locIndex]); 323 324 for ( unsigned int numberIndex = 0; 325 numberIndex < sizeof(numbers)/sizeof(int); 326 ++numberIndex ) { 327 328 for ( unsigned int styleIndex = 0; 329 styleIndex < sizeof(styles)/sizeof(styles[0]); 330 ++styleIndex ) { 331 332 for ( unsigned int unitIndex = 0; 333 unitIndex < sizeof(tunits)/sizeof(tunits[0]); 334 ++unitIndex ) { 335 336 TimeUnitAmount *tamt = new TimeUnitAmount(numbers[numberIndex], tunits[unitIndex], status); 337 if (U_FAILURE(status)) { 338 dataerrln("generating TimeUnitAmount Object failed."); 339 #ifdef TUFMTTS_DEBUG 340 std::cout << "Failed to get TimeUnitAmount for " << tunits[unitIndex] << "\n"; 341 #endif 342 return; 343 } 344 345 TimeUnitFormat *tfmt = new TimeUnitFormat(l, styles[styleIndex], status); 346 if (U_FAILURE(status)) { 347 dataerrln("generating TimeUnitAmount Object failed."); 348 #ifdef TUFMTTS_DEBUG 349 std::cout << "Failed to get TimeUnitFormat for " << locales[locIndex] << "\n"; 350 #endif 351 return; 352 } 353 354 Formattable fmt; 355 UnicodeString str; 356 357 fmt.adoptObject(tamt); 358 str = ((Format *)tfmt)->format(fmt, str, status); 359 if (!assertSuccess("formatting relative time failed", status)) { 360 delete tfmt; 361 #ifdef TUFMTTS_DEBUG 362 std::cout << "Failed to format" << "\n"; 363 #endif 364 return; 365 } 366 367 #ifdef TUFMTTS_DEBUG 368 char tmp[128]; //output 369 char tmp1[128]; //expected 370 int len = 0; 371 u_strToUTF8(tmp, 128, &len, str.getTerminatedBuffer(), str.length(), &status); 372 u_strToUTF8(tmp1, 128, &len, expected[counter].unescape().getTerminatedBuffer(), expected[counter].unescape().length(), &status); 373 std::cout << "Formatted string : " << tmp << " expected : " << tmp1 << "\n"; 374 #endif 375 if (!assertEquals("formatted time string is not expected, locale: " + UnicodeString(locales[locIndex]) + " style: " + (int)styles[styleIndex] + " units: " + (int)tunits[unitIndex], expected[counter], str)) { 376 delete tfmt; 377 str.remove(); 378 return; 379 } 380 delete tfmt; 381 str.remove(); 382 ++counter; 383 } 384 } 385 } 386 } 387 } 388 389 // Test bug9042 390 void TimeUnitTest::testGreekWithSanitization() { 391 392 UErrorCode status = U_ZERO_ERROR; 393 Locale elLoc("el"); 394 NumberFormat* numberFmt = NumberFormat::createInstance(Locale("el"), status); 395 if (!assertSuccess("NumberFormat::createInstance for el locale", status, TRUE)) return; 396 numberFmt->setMaximumFractionDigits(1); 397 398 TimeUnitFormat* timeUnitFormat = new TimeUnitFormat(elLoc, status); 399 if (!assertSuccess("TimeUnitFormat::TimeUnitFormat for el locale", status)) return; 400 401 timeUnitFormat->setNumberFormat(*numberFmt, status); 402 403 delete numberFmt; 404 delete timeUnitFormat; 405 } 406 407 void TimeUnitTest::test10219Plurals() { 408 Locale usLocale("en_US"); 409 double values[2] = {1.588, 1.011}; 410 UnicodeString expected[2][3] = { 411 {"1 minute", "1.5 minutes", "1.58 minutes"}, 412 {"1 minute", "1.0 minutes", "1.01 minutes"} 413 }; 414 UErrorCode status = U_ZERO_ERROR; 415 TimeUnitFormat tuf(usLocale, status); 416 if (U_FAILURE(status)) { 417 dataerrln("generating TimeUnitFormat Object failed: %s", u_errorName(status)); 418 return; 419 } 420 LocalPointer<DecimalFormat> nf((DecimalFormat *) NumberFormat::createInstance(usLocale, status)); 421 if (U_FAILURE(status)) { 422 dataerrln("generating NumberFormat Object failed: %s", u_errorName(status)); 423 return; 424 } 425 for (int32_t j = 0; j < LENGTHOF(values); ++j) { 426 for (int32_t i = 0; i < LENGTHOF(expected[j]); ++i) { 427 nf->setMinimumFractionDigits(i); 428 nf->setMaximumFractionDigits(i); 429 nf->setRoundingMode(DecimalFormat::kRoundDown); 430 tuf.setNumberFormat(*nf, status); 431 if (U_FAILURE(status)) { 432 dataerrln("setting NumberFormat failed: %s", u_errorName(status)); 433 return; 434 } 435 UnicodeString actual; 436 Formattable fmt; 437 LocalPointer<TimeUnitAmount> tamt(new TimeUnitAmount(values[j], TimeUnit::UTIMEUNIT_MINUTE, status)); 438 if (U_FAILURE(status)) { 439 dataerrln("generating TimeUnitAmount Object failed: %s", u_errorName(status)); 440 return; 441 } 442 fmt.adoptObject(tamt.orphan()); 443 tuf.format(fmt, actual, status); 444 if (U_FAILURE(status)) { 445 dataerrln("Actual formatting failed: %s", u_errorName(status)); 446 return; 447 } 448 if (expected[j][i] != actual) { 449 errln("Expected " + expected[j][i] + ", got " + actual); 450 } 451 } 452 } 453 454 // test parsing 455 Formattable result; 456 ParsePosition pos; 457 UnicodeString formattedString = "1 minutes"; 458 tuf.parseObject(formattedString, result, pos); 459 if (formattedString.length() != pos.getIndex()) { 460 errln("Expect parsing to go all the way to the end of the string."); 461 } 462 } 463 464 #endif 465