1// © 2016 and later: Unicode, Inc. and others. 2// License & terms of use: http://www.unicode.org/copyright.html 3/*********************************************************************** 4 * COPYRIGHT: 5 * Copyright (c) 1997-2011, International Business Machines Corporation 6 * and others. All Rights Reserved. 7 ***********************************************************************/ 8 9#include "unicode/utypes.h" 10 11#if !UCONFIG_NO_FORMATTING 12 13#include "dtfmapts.h" 14 15#include "unicode/datefmt.h" 16#include "unicode/smpdtfmt.h" 17#include "unicode/decimfmt.h" 18#include "unicode/choicfmt.h" 19#include "unicode/msgfmt.h" 20 21 22// This is an API test, not a unit test. It doesn't test very many cases, and doesn't 23// try to test the full functionality. It just calls each function in the class and 24// verifies that it works on a basic level. 25 26void IntlTestDateFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) 27{ 28 if (exec) logln("TestSuite DateFormatAPI"); 29 switch (index) { 30 case 0: name = "DateFormat API test"; 31 if (exec) { 32 logln("DateFormat API test---"); logln(""); 33 UErrorCode status = U_ZERO_ERROR; 34 Locale saveLocale; 35 Locale::setDefault(Locale::getEnglish(), status); 36 if(U_FAILURE(status)) { 37 errln("ERROR: Could not set default locale, test may not give correct results"); 38 } 39 testAPI(/*par*/); 40 Locale::setDefault(saveLocale, status); 41 } 42 break; 43 44 case 1: name = "TestEquals"; 45 if (exec) { 46 logln("TestEquals---"); logln(""); 47 TestEquals(); 48 } 49 break; 50 51 case 2: name = "TestNameHiding"; 52 if (exec) { 53 logln("TestNameHiding---"); logln(""); 54 TestNameHiding(); 55 } 56 break; 57 58 case 3: name = "TestCoverage"; 59 if (exec) { 60 logln("TestCoverage---"); logln(""); 61 TestCoverage(); 62 } 63 break; 64 65 default: name = ""; break; 66 } 67} 68 69/** 70 * Add better code coverage. 71 */ 72void IntlTestDateFormatAPI::TestCoverage(void) 73{ 74 const char *LOCALES[] = { 75 "zh_CN@calendar=chinese", 76 "cop_EG@calendar=coptic", 77 "hi_IN@calendar=indian", 78 "am_ET@calendar=ethiopic" 79 }; 80 int32_t numOfLocales = 4; 81 82 for (int32_t i = 0; i < numOfLocales; i++) { 83 DateFormat *df = DateFormat::createDateTimeInstance(DateFormat::kMedium, DateFormat::kMedium, Locale(LOCALES[i])); 84 if (df == NULL){ 85 dataerrln("Error creating DateFormat instances."); 86 return; 87 } 88 delete df; 89 } 90} 91/** 92 * Test that the equals method works correctly. 93 */ 94void IntlTestDateFormatAPI::TestEquals(void) 95{ 96 UErrorCode status = U_ZERO_ERROR; 97 // Create two objects at different system times 98 DateFormat *a = DateFormat::createInstance(); 99 UDate start = Calendar::getNow(); 100 while (Calendar::getNow() == start) ; // Wait for time to change 101 DateFormat *b = DateFormat::createInstance(); 102 103 if (a == NULL || b == NULL){ 104 dataerrln("Error calling DateFormat::createInstance()"); 105 delete a; 106 delete b; 107 return; 108 } 109 110 if (!(*a == *b)) 111 errln("FAIL: DateFormat objects created at different times are unequal."); 112 113 SimpleDateFormat *sdtfmt = dynamic_cast<SimpleDateFormat *>(b); 114 if (sdtfmt != NULL) 115 { 116 double ONE_YEAR = 365*24*60*60*1000.0; 117 sdtfmt->set2DigitYearStart(start + 50*ONE_YEAR, status); 118 if (U_FAILURE(status)) 119 errln("FAIL: setTwoDigitStartDate failed."); 120 else if (*a == *b) 121 errln("FAIL: DateFormat objects with different two digit start dates are equal."); 122 } 123 delete a; 124 delete b; 125} 126 127/** 128 * This test checks various generic API methods in DateFormat to achieve 100% 129 * API coverage. 130 */ 131void IntlTestDateFormatAPI::testAPI(/* char* par */) 132{ 133 UErrorCode status = U_ZERO_ERROR; 134 135// ======= Test constructors 136 137 logln("Testing DateFormat constructors"); 138 139 DateFormat *def = DateFormat::createInstance(); 140 DateFormat *fr = DateFormat::createTimeInstance(DateFormat::FULL, Locale::getFrench()); 141 DateFormat *it = DateFormat::createDateInstance(DateFormat::MEDIUM, Locale::getItalian()); 142 DateFormat *de = DateFormat::createDateTimeInstance(DateFormat::LONG, DateFormat::LONG, Locale::getGerman()); 143 144 if (def == NULL || fr == NULL || it == NULL || de == NULL){ 145 dataerrln("Error creating DateFormat instances."); 146 } 147 148// ======= Test equality 149if (fr != NULL && def != NULL) 150{ 151 logln("Testing equality operator"); 152 153 if( *fr == *it ) { 154 errln("ERROR: == failed"); 155 } 156} 157 158// ======= Test various format() methods 159if (fr != NULL && it != NULL && de != NULL) 160{ 161 logln("Testing various format() methods"); 162 163 UDate d = 837039928046.0; 164 Formattable fD(d, Formattable::kIsDate); 165 166 UnicodeString res1, res2, res3; 167 FieldPosition pos1(FieldPosition::DONT_CARE), pos2(FieldPosition::DONT_CARE); 168 169 status = U_ZERO_ERROR; 170 res1 = fr->format(d, res1, pos1, status); 171 if(U_FAILURE(status)) { 172 errln("ERROR: format() failed (French)"); 173 } 174 logln( (UnicodeString) "" + d + " formatted to " + res1); 175 176 res2 = it->format(d, res2, pos2); 177 logln( (UnicodeString) "" + d + " formatted to " + res2); 178 179 res3 = de->format(d, res3); 180 logln( (UnicodeString) "" + d + " formatted to " + res3); 181} 182 183// ======= Test parse() 184if (def != NULL) 185{ 186 logln("Testing parse()"); 187 188 UnicodeString text("02/03/76 2:50 AM, CST"); 189 Formattable result1; 190 UDate result2, result3; 191 ParsePosition pos(0), pos01(0); 192 def->parseObject(text, result1, pos); 193 if(result1.getType() != Formattable::kDate) { 194 errln("ERROR: parseObject() failed for " + text); 195 } 196 logln(text + " parsed into " + result1.getDate()); 197 198 status = U_ZERO_ERROR; 199 result2 = def->parse(text, status); 200 if(U_FAILURE(status)) { 201 errln("ERROR: parse() failed, stopping testing"); 202 return; 203 } 204 logln(text + " parsed into " + result2); 205 206 result3 = def->parse(text, pos01); 207 logln(text + " parsed into " + result3); 208} 209 210// ======= Test getters and setters 211if (fr != NULL && it != NULL && de != NULL) 212{ 213 logln("Testing getters and setters"); 214 215 int32_t count = 0; 216 const Locale *locales = DateFormat::getAvailableLocales(count); 217 logln((UnicodeString) "Got " + count + " locales" ); 218 for(int32_t i = 0; i < count; i++) { 219 UnicodeString name; 220 name = locales[i].getName(); 221 logln(name); 222 } 223 224 fr->setLenient(it->isLenient()); 225 if(fr->isLenient() != it->isLenient()) { 226 errln("ERROR: setLenient() failed"); 227 } 228 229 const Calendar *cal = def->getCalendar(); 230 Calendar *newCal = cal->clone(); 231 de->adoptCalendar(newCal); 232 it->setCalendar(*newCal); 233 if( *(de->getCalendar()) != *(it->getCalendar())) { 234 errln("ERROR: adopt or set Calendar() failed"); 235 } 236 237 const NumberFormat *nf = def->getNumberFormat(); 238 NumberFormat *newNf = (NumberFormat*) nf->clone(); 239 de->adoptNumberFormat(newNf); 240 it->setNumberFormat(*newNf); 241 if( *(de->getNumberFormat()) != *(it->getNumberFormat())) { 242 errln("ERROR: adopt or set NumberFormat() failed"); 243 } 244 245 const TimeZone& tz = def->getTimeZone(); 246 TimeZone *newTz = tz.clone(); 247 de->adoptTimeZone(newTz); 248 it->setTimeZone(*newTz); 249 if( de->getTimeZone() != it->getTimeZone()) { 250 errln("ERROR: adopt or set TimeZone() failed"); 251 } 252} 253// ======= Test getStaticClassID() 254 255 logln("Testing getStaticClassID()"); 256 257 status = U_ZERO_ERROR; 258 DateFormat *test = new SimpleDateFormat(status); 259 if(U_FAILURE(status)) { 260 dataerrln("ERROR: Couldn't create a DateFormat - %s", u_errorName(status)); 261 } 262 263 if(test->getDynamicClassID() != SimpleDateFormat::getStaticClassID()) { 264 errln("ERROR: getDynamicClassID() didn't return the expected value"); 265 } 266 267 delete test; 268 delete def; 269 delete fr; 270 delete it; 271 delete de; 272} 273 274/** 275 * Test hiding of parse() and format() APIs in the Format hierarchy. 276 * We test the entire hierarchy, even though this test is located in 277 * the DateFormat API test. 278 */ 279void 280IntlTestDateFormatAPI::TestNameHiding(void) { 281 282 // N.B.: This test passes if it COMPILES, since it's a test of 283 // compile-time name hiding. 284 285 UErrorCode status = U_ZERO_ERROR; 286 Formattable dateObj(0, Formattable::kIsDate); 287 Formattable numObj(3.1415926535897932384626433832795); 288 Formattable obj; 289 UnicodeString str; 290 FieldPosition fpos; 291 ParsePosition ppos; 292 293 // DateFormat calling Format API 294 { 295 logln("DateFormat"); 296 DateFormat *dateFmt = DateFormat::createInstance(); 297 if (dateFmt) { 298 dateFmt->format(dateObj, str, status); 299 dateFmt->format(dateObj, str, fpos, status); 300 delete dateFmt; 301 } else { 302 dataerrln("FAIL: Can't create DateFormat"); 303 } 304 } 305 306 // SimpleDateFormat calling Format & DateFormat API 307 { 308 logln("SimpleDateFormat"); 309 status = U_ZERO_ERROR; 310 SimpleDateFormat sdf(status); 311 if (U_SUCCESS(status)) { 312 // Format API 313 sdf.format(dateObj, str, status); 314 sdf.format(dateObj, str, fpos, status); 315 // DateFormat API 316 sdf.format((UDate)0, str, fpos); 317 sdf.format((UDate)0, str); 318 sdf.parse(str, status); 319 sdf.parse(str, ppos); 320 sdf.getNumberFormat(); 321 } else { 322 dataerrln("FAIL: Can't create SimpleDateFormat() - %s", u_errorName(status)); 323 } 324 } 325 326 // NumberFormat calling Format API 327 { 328 logln("NumberFormat"); 329 status = U_ZERO_ERROR; 330 NumberFormat *fmt = NumberFormat::createInstance(status); 331 if (fmt) { 332 fmt->format(numObj, str, status); 333 fmt->format(numObj, str, fpos, status); 334 delete fmt; 335 } else { 336 dataerrln("FAIL: Can't create NumberFormat()"); 337 } 338 } 339 340 // DecimalFormat calling Format & NumberFormat API 341 { 342 logln("DecimalFormat"); 343 status = U_ZERO_ERROR; 344 DecimalFormat fmt(status); 345 if(U_SUCCESS(status)) { 346 // Format API 347 fmt.format(numObj, str, status); 348 fmt.format(numObj, str, fpos, status); 349 // NumberFormat API 350 fmt.format(2.71828, str); 351 fmt.format((int32_t)1234567, str); 352 fmt.format(1.41421, str, fpos); 353 fmt.format((int32_t)9876543, str, fpos); 354 fmt.parse(str, obj, ppos); 355 fmt.parse(str, obj, status); 356 } else { 357 errcheckln(status, "FAIL: Couldn't instantiate DecimalFormat, error %s. Quitting test", u_errorName(status)); 358 } 359 } 360 361 // ChoiceFormat calling Format & NumberFormat API 362 { 363 logln("ChoiceFormat"); 364 status = U_ZERO_ERROR; 365 ChoiceFormat fmt("0#foo|1#foos|2#foos", status); 366 // Format API 367 fmt.format(numObj, str, status); 368 fmt.format(numObj, str, fpos, status); 369 // NumberFormat API 370 fmt.format(2.71828, str); 371 fmt.format((int32_t)1234567, str); 372 fmt.format(1.41421, str, fpos); 373 fmt.format((int32_t)9876543, str, fpos); 374 fmt.parse(str, obj, ppos); 375 fmt.parse(str, obj, status); 376 } 377 378 // MessageFormat calling Format API 379 { 380 logln("MessageFormat"); 381 status = U_ZERO_ERROR; 382 MessageFormat fmt("", status); 383 // Format API 384 // We use dateObj, which MessageFormat should reject. 385 // We're testing name hiding, not the format method. 386 fmt.format(dateObj, str, status); 387 fmt.format(dateObj, str, fpos, status); 388 } 389} 390 391#endif /* #if !UCONFIG_NO_FORMATTING */ 392