OLD | NEW |
(Empty) | |
| 1 /*********************************************************************** |
| 2 * COPYRIGHT: |
| 3 * Copyright (c) 1997-2009, International Business Machines Corporation |
| 4 * and others. All Rights Reserved. |
| 5 ***********************************************************************/ |
| 6 |
| 7 #include "unicode/utypes.h" |
| 8 |
| 9 #if !UCONFIG_NO_FORMATTING |
| 10 |
| 11 #include "msfmrgts.h" |
| 12 |
| 13 #include "unicode/format.h" |
| 14 #include "unicode/decimfmt.h" |
| 15 #include "unicode/locid.h" |
| 16 #include "unicode/msgfmt.h" |
| 17 #include "unicode/numfmt.h" |
| 18 #include "unicode/choicfmt.h" |
| 19 #include "unicode/gregocal.h" |
| 20 #include "putilimp.h" |
| 21 |
| 22 // ***************************************************************************** |
| 23 // class MessageFormatRegressionTest |
| 24 // ***************************************************************************** |
| 25 |
| 26 #define CASE(id,test) case id: name = #test; if (exec) { logln(#test "---"); log
ln((UnicodeString)""); test(); } break; |
| 27 |
| 28 void |
| 29 MessageFormatRegressionTest::runIndexedTest( int32_t index, UBool exec, const ch
ar* &name, char* /*par*/ ) |
| 30 { |
| 31 // if (exec) logln((UnicodeString)"TestSuite MessageFormatRegressionTest"); |
| 32 switch (index) { |
| 33 CASE(0,Test4074764) |
| 34 CASE(1,Test4058973) |
| 35 CASE(2,Test4031438) |
| 36 CASE(3,Test4052223) |
| 37 CASE(4,Test4104976) |
| 38 CASE(5,Test4106659) |
| 39 CASE(6,Test4106660) |
| 40 CASE(7,Test4111739) |
| 41 CASE(8,Test4114743) |
| 42 CASE(9,Test4116444) |
| 43 CASE(10,Test4114739) |
| 44 CASE(11,Test4113018) |
| 45 CASE(12,Test4106661) |
| 46 CASE(13,Test4094906) |
| 47 CASE(14,Test4118592) |
| 48 CASE(15,Test4118594) |
| 49 CASE(16,Test4105380) |
| 50 CASE(17,Test4120552) |
| 51 CASE(18,Test4142938) |
| 52 CASE(19,TestChoicePatternQuote) |
| 53 CASE(20,Test4112104) |
| 54 CASE(21,TestAPI) |
| 55 |
| 56 default: name = ""; break; |
| 57 } |
| 58 } |
| 59 |
| 60 UBool |
| 61 MessageFormatRegressionTest::failure(UErrorCode status, const char* msg, UBool p
ossibleDataError) |
| 62 { |
| 63 if(U_FAILURE(status)) { |
| 64 if (possibleDataError) { |
| 65 dataerrln(UnicodeString("FAIL: ") + msg + " failed, error " + u_erro
rName(status)); |
| 66 } else { |
| 67 errln(UnicodeString("FAIL: ") + msg + " failed, error " + u_errorNam
e(status)); |
| 68 } |
| 69 return TRUE; |
| 70 } |
| 71 |
| 72 return FALSE; |
| 73 } |
| 74 |
| 75 /* @bug 4074764 |
| 76 * Null exception when formatting pattern with MessageFormat |
| 77 * with no parameters. |
| 78 */ |
| 79 void MessageFormatRegressionTest::Test4074764() { |
| 80 UnicodeString pattern [] = { |
| 81 "Message without param", |
| 82 "Message with param:{0}", |
| 83 "Longer Message with param {0}" |
| 84 }; |
| 85 //difference between the two param strings are that |
| 86 //in the first one, the param position is within the |
| 87 //length of the string without param while it is not so |
| 88 //in the other case. |
| 89 |
| 90 UErrorCode status = U_ZERO_ERROR; |
| 91 MessageFormat *messageFormatter = new MessageFormat("", status); |
| 92 |
| 93 failure(status, "couldn't create MessageFormat"); |
| 94 |
| 95 //try { |
| 96 //Apply pattern with param and print the result |
| 97 messageFormatter->applyPattern(pattern[1], status); |
| 98 failure(status, "messageFormat->applyPattern"); |
| 99 //Object[] params = {new UnicodeString("BUG"), new Date()}; |
| 100 Formattable params [] = { |
| 101 Formattable(UnicodeString("BUG")), |
| 102 Formattable(0, Formattable::kIsDate) |
| 103 }; |
| 104 UnicodeString tempBuffer; |
| 105 FieldPosition pos(FieldPosition::DONT_CARE); |
| 106 tempBuffer = messageFormatter->format(params, 2, tempBuffer, pos, status
); |
| 107 if( tempBuffer != "Message with param:BUG" || failure(status, "messageFo
rmat->format")) |
| 108 errln("MessageFormat with one param test failed."); |
| 109 logln("Formatted with one extra param : " + tempBuffer); |
| 110 |
| 111 //Apply pattern without param and print the result |
| 112 messageFormatter->applyPattern(pattern[0], status); |
| 113 failure(status, "messageFormatter->applyPattern"); |
| 114 |
| 115 // {sfb} how much does this apply in C++? |
| 116 // do we want to verify that the Formattable* array is not NULL, |
| 117 // or is that the user's responsibility? |
| 118 // additionally, what should be the item count? |
| 119 // for bug testing purposes, assume that something was set to |
| 120 // NULL by mistake, and that the length should be non-zero |
| 121 |
| 122 //tempBuffer = messageFormatter->format(NULL, 1, tempBuffer, FieldPositi
on(FieldPosition::DONT_CARE), status); |
| 123 tempBuffer.remove(); |
| 124 tempBuffer = messageFormatter->format(NULL, 0, tempBuffer, pos, status); |
| 125 |
| 126 if( tempBuffer != "Message without param" || failure(status, "messageFor
mat->format")) |
| 127 errln("MessageFormat with no param test failed."); |
| 128 logln("Formatted with no params : " + tempBuffer); |
| 129 |
| 130 tempBuffer.remove(); |
| 131 tempBuffer = messageFormatter->format(params, 2, tempBuffer, pos, status
); |
| 132 if (tempBuffer != "Message without param" || failure(status, "messageFo
rmat->format")) |
| 133 errln("Formatted with arguments > subsitution failed. result = " + t
empBuffer); |
| 134 logln("Formatted with extra params : " + tempBuffer); |
| 135 //This statement gives an exception while formatting... |
| 136 //If we use pattern[1] for the message with param, |
| 137 //we get an NullPointerException in MessageFormat.java(617) |
| 138 //If we use pattern[2] for the message with param, |
| 139 //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(6
14) |
| 140 //Both are due to maxOffset not being reset to -1 |
| 141 //in applyPattern() when the pattern does not |
| 142 //contain any param. |
| 143 /*} catch (Exception foo) { |
| 144 errln("Exception when formatting with no params."); |
| 145 }*/ |
| 146 |
| 147 delete messageFormatter; |
| 148 } |
| 149 |
| 150 /* @bug 4058973 |
| 151 * MessageFormat.toPattern has weird rounding behavior. |
| 152 */ |
| 153 void MessageFormatRegressionTest::Test4058973() |
| 154 { |
| 155 UErrorCode status = U_ZERO_ERROR; |
| 156 MessageFormat *fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {
0,number,integer} files}", status); |
| 157 failure(status, "new MessageFormat"); |
| 158 |
| 159 UnicodeString pat; |
| 160 pat = fmt->toPattern(pat); |
| 161 UnicodeString exp("{0,choice,0#no files|1#one file|1< {0,number,integer} fil
es}"); |
| 162 if (pat != exp) { |
| 163 errln("MessageFormat.toPattern failed"); |
| 164 errln("Exp: " + exp); |
| 165 errln("Got: " + pat); |
| 166 } |
| 167 |
| 168 delete fmt; |
| 169 } |
| 170 /* @bug 4031438 |
| 171 * More robust message formats. |
| 172 */ |
| 173 void MessageFormatRegressionTest::Test4031438() |
| 174 { |
| 175 UErrorCode status = U_ZERO_ERROR; |
| 176 |
| 177 UnicodeString pattern1("Impossible {1} has occurred -- status code is {0} an
d message is {2}."); |
| 178 UnicodeString pattern2("Double '' Quotes {0} test and quoted '{1}' test plus
'other {2} stuff'."); |
| 179 |
| 180 MessageFormat *messageFormatter = new MessageFormat("", status); |
| 181 failure(status, "new MessageFormat"); |
| 182 |
| 183 const UBool possibleDataError = TRUE; |
| 184 |
| 185 //try { |
| 186 logln("Apply with pattern : " + pattern1); |
| 187 messageFormatter->applyPattern(pattern1, status); |
| 188 failure(status, "messageFormat->applyPattern"); |
| 189 //Object[] params = {new Integer(7)}; |
| 190 Formattable params []= { |
| 191 Formattable((int32_t)7) |
| 192 }; |
| 193 UnicodeString tempBuffer; |
| 194 FieldPosition pos(FieldPosition::DONT_CARE); |
| 195 tempBuffer = messageFormatter->format(params, 1, tempBuffer, pos, status
); |
| 196 if(tempBuffer != "Impossible {1} has occurred -- status code is 7 and me
ssage is {2}." || failure(status, "MessageFormat::format")) |
| 197 dataerrln("Tests arguments < substitution failed"); |
| 198 logln("Formatted with 7 : " + tempBuffer); |
| 199 ParsePosition pp(0); |
| 200 int32_t count = 0; |
| 201 Formattable *objs = messageFormatter->parse(tempBuffer, pp, count); |
| 202 //if(objs[7/*params.length*/] != NULL) |
| 203 // errln("Parse failed with more than expected arguments"); |
| 204 |
| 205 NumberFormat *fmt = 0; |
| 206 UnicodeString temp, temp1; |
| 207 |
| 208 for (int i = 0; i < count; i++) { |
| 209 |
| 210 // convert to string if not already |
| 211 Formattable obj = objs[i]; |
| 212 temp.remove(); |
| 213 if(obj.getType() == Formattable::kString) |
| 214 temp = obj.getString(temp); |
| 215 else { |
| 216 fmt = NumberFormat::createInstance(status); |
| 217 switch (obj.getType()) { |
| 218 case Formattable::kLong: fmt->format(obj.getLong(), temp); break
; |
| 219 case Formattable::kInt64: fmt->format(obj.getInt64(), temp); bre
ak; |
| 220 case Formattable::kDouble: fmt->format(obj.getDouble(), temp); b
reak; |
| 221 default: break; |
| 222 } |
| 223 } |
| 224 |
| 225 // convert to string if not already |
| 226 Formattable obj1 = params[i]; |
| 227 temp1.remove(); |
| 228 if(obj1.getType() == Formattable::kString) |
| 229 temp1 = obj1.getString(temp1); |
| 230 else { |
| 231 fmt = NumberFormat::createInstance(status); |
| 232 switch (obj1.getType()) { |
| 233 case Formattable::kLong: fmt->format(obj1.getLong(), temp1); bre
ak; |
| 234 case Formattable::kInt64: fmt->format(obj1.getInt64(), temp1); b
reak; |
| 235 case Formattable::kDouble: fmt->format(obj1.getDouble(), temp1);
break; |
| 236 default: break; |
| 237 } |
| 238 } |
| 239 |
| 240 //if (objs[i] != NULL && objs[i].getString(temp1) != params[i].getSt
ring(temp2)) { |
| 241 if (temp != temp1) { |
| 242 errln("Parse failed on object " + objs[i].getString(temp1) + " a
t index : " + i); |
| 243 } |
| 244 } |
| 245 |
| 246 delete fmt; |
| 247 delete [] objs; |
| 248 |
| 249 // {sfb} does this apply? no way to really pass a null Formattable, |
| 250 // only a null array |
| 251 |
| 252 /*tempBuffer = messageFormatter->format(null, tempBuffer, FieldPosition(
FieldPosition::DONT_CARE), status); |
| 253 if (tempBuffer != "Impossible {1} has occurred -- status code is {0} and
message is {2}." || failure(status, "messageFormat->format")) |
| 254 errln("Tests with no arguments failed"); |
| 255 logln("Formatted with null : " + tempBuffer);*/ |
| 256 logln("Apply with pattern : " + pattern2); |
| 257 messageFormatter->applyPattern(pattern2, status); |
| 258 failure(status, "messageFormatter->applyPattern", possibleDataError); |
| 259 tempBuffer.remove(); |
| 260 tempBuffer = messageFormatter->format(params, 1, tempBuffer, pos, status
); |
| 261 if (tempBuffer != "Double ' Quotes 7 test and quoted {1} test plus other
{2} stuff.") |
| 262 dataerrln("quote format test (w/ params) failed. - %s", u_errorName(
status)); |
| 263 logln("Formatted with params : " + tempBuffer); |
| 264 |
| 265 /*tempBuffer = messageFormatter->format(null); |
| 266 if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plu
s other {2} stuff.")) |
| 267 errln("quote format test (w/ null) failed."); |
| 268 logln("Formatted with null : " + tempBuffer); |
| 269 logln("toPattern : " + messageFormatter.toPattern());*/ |
| 270 /*} catch (Exception foo) { |
| 271 errln("Exception when formatting in bug 4031438. "+foo.getMessage()); |
| 272 }*/ |
| 273 delete messageFormatter; |
| 274 } |
| 275 |
| 276 void MessageFormatRegressionTest::Test4052223() |
| 277 { |
| 278 |
| 279 ParsePosition pos(0); |
| 280 if (pos.getErrorIndex() != -1) { |
| 281 errln("ParsePosition.getErrorIndex initialization failed."); |
| 282 } |
| 283 |
| 284 UErrorCode status = U_ZERO_ERROR; |
| 285 MessageFormat *fmt = new MessageFormat("There are {0} apples growing on the
{1} tree.", status); |
| 286 failure(status, "new MessageFormat"); |
| 287 UnicodeString str("There is one apple growing on the peach tree."); |
| 288 |
| 289 int32_t count = 0; |
| 290 fmt->parse(str, pos, count); |
| 291 |
| 292 logln(UnicodeString("unparsable string , should fail at ") + pos.getErrorInd
ex()); |
| 293 if (pos.getErrorIndex() == -1) |
| 294 errln("Bug 4052223 failed : parsing string " + str); |
| 295 pos.setErrorIndex(4); |
| 296 if (pos.getErrorIndex() != 4) |
| 297 errln(UnicodeString("setErrorIndex failed, got ") + pos.getErrorIndex()
+ " instead of 4"); |
| 298 |
| 299 ChoiceFormat *f = new ChoiceFormat( |
| 300 "-1#are negative|0#are no or fraction|1#is one|1.0<is 1+|2#are two|2<are
more than 2.", status); |
| 301 failure(status, "new ChoiceFormat"); |
| 302 pos.setIndex(0); |
| 303 pos.setErrorIndex(-1); |
| 304 Formattable obj; |
| 305 f->parse("are negative", obj, pos); |
| 306 if (pos.getErrorIndex() != -1 && obj.getDouble() == -1.0) |
| 307 errln(UnicodeString("Parse with \"are negative\" failed, at ") + pos.get
ErrorIndex()); |
| 308 pos.setIndex(0); |
| 309 pos.setErrorIndex(-1); |
| 310 f->parse("are no or fraction ", obj, pos); |
| 311 if (pos.getErrorIndex() != -1 && obj.getDouble() == 0.0) |
| 312 errln(UnicodeString("Parse with \"are no or fraction\" failed, at ") + p
os.getErrorIndex()); |
| 313 pos.setIndex(0); |
| 314 pos.setErrorIndex(-1); |
| 315 f->parse("go postal", obj, pos); |
| 316 if (pos.getErrorIndex() == -1 && ! uprv_isNaN(obj.getDouble())) |
| 317 errln(UnicodeString("Parse with \"go postal\" failed, at ") + pos.getErr
orIndex()); |
| 318 |
| 319 delete fmt; |
| 320 delete f; |
| 321 } |
| 322 /* @bug 4104976 |
| 323 * ChoiceFormat.equals(null) throws NullPointerException |
| 324 */ |
| 325 |
| 326 // {sfb} not really applicable in C++?? (kind of silly) |
| 327 |
| 328 void MessageFormatRegressionTest::Test4104976() |
| 329 { |
| 330 double limits [] = {1, 20}; |
| 331 UnicodeString formats [] = { |
| 332 UnicodeString("xyz"), |
| 333 UnicodeString("abc") |
| 334 }; |
| 335 int32_t formats_length = (int32_t)(sizeof(formats)/sizeof(formats[0])); |
| 336 UErrorCode status = U_ZERO_ERROR; |
| 337 ChoiceFormat *cf = new ChoiceFormat(limits, formats, formats_length); |
| 338 failure(status, "new ChoiceFormat"); |
| 339 //try { |
| 340 log("Compares to null is always false, returned : "); |
| 341 logln(cf == NULL ? "TRUE" : "FALSE"); |
| 342 /*} catch (Exception foo) { |
| 343 errln("ChoiceFormat.equals(null) throws exception."); |
| 344 }*/ |
| 345 |
| 346 delete cf; |
| 347 } |
| 348 |
| 349 /* @bug 4106659 |
| 350 * ChoiceFormat.ctor(double[], String[]) doesn't check |
| 351 * whether lengths of input arrays are equal. |
| 352 */ |
| 353 |
| 354 // {sfb} again, not really applicable in C++ |
| 355 |
| 356 void MessageFormatRegressionTest::Test4106659() |
| 357 { |
| 358 /* |
| 359 double limits [] = { |
| 360 1, 2, 3 |
| 361 }; |
| 362 UnicodeString formats [] = { |
| 363 "one", "two" |
| 364 }; |
| 365 ChoiceFormat *cf = NULL; |
| 366 //try { |
| 367 // cf = new ChoiceFormat(limits, formats, 3); |
| 368 //} catch (Exception foo) { |
| 369 // logln("ChoiceFormat constructor should check for the array lengths"); |
| 370 // cf = null; |
| 371 //} |
| 372 //if (cf != null) |
| 373 // errln(cf->format(5)); |
| 374 // |
| 375 delete cf; |
| 376 */ |
| 377 } |
| 378 |
| 379 /* @bug 4106660 |
| 380 * ChoiceFormat.ctor(double[], String[]) allows unordered double array. |
| 381 * This is not a bug, added javadoc to emphasize the use of limit |
| 382 * array must be in ascending order. |
| 383 */ |
| 384 void MessageFormatRegressionTest::Test4106660() |
| 385 { |
| 386 double limits [] = {3, 1, 2}; |
| 387 UnicodeString formats [] = { |
| 388 UnicodeString("Three"), |
| 389 UnicodeString("One"), |
| 390 UnicodeString("Two") |
| 391 }; |
| 392 ChoiceFormat *cf = new ChoiceFormat(limits, formats, 3); |
| 393 double d = 5.0; |
| 394 UnicodeString str; |
| 395 FieldPosition pos(FieldPosition::DONT_CARE); |
| 396 str = cf->format(d, str, pos); |
| 397 if (str != "Two") |
| 398 errln( (UnicodeString) "format(" + d + ") = " + str); |
| 399 |
| 400 delete cf; |
| 401 } |
| 402 |
| 403 /* @bug 4111739 |
| 404 * MessageFormat is incorrectly serialized/deserialized. |
| 405 */ |
| 406 |
| 407 // {sfb} doesn't apply in C++ |
| 408 |
| 409 void MessageFormatRegressionTest::Test4111739() |
| 410 { |
| 411 /*MessageFormat format1 = null; |
| 412 MessageFormat format2 = null; |
| 413 ObjectOutputStream ostream = null; |
| 414 ByteArrayOutputStream baos = null; |
| 415 ObjectInputStream istream = null; |
| 416 |
| 417 try { |
| 418 baos = new ByteArrayOutputStream(); |
| 419 ostream = new ObjectOutputStream(baos); |
| 420 } catch(IOException e) { |
| 421 errln("Unexpected exception : " + e.getMessage()); |
| 422 return; |
| 423 } |
| 424 |
| 425 try { |
| 426 format1 = new MessageFormat("pattern{0}"); |
| 427 ostream.writeObject(format1); |
| 428 ostream.flush(); |
| 429 |
| 430 byte bytes[] = baos.toByteArray(); |
| 431 |
| 432 istream = new ObjectInputStream(new ByteArrayInputStream(bytes)); |
| 433 format2 = (MessageFormat)istream.readObject(); |
| 434 } catch(Exception e) { |
| 435 errln("Unexpected exception : " + e.getMessage()); |
| 436 } |
| 437 |
| 438 if (!format1.equals(format2)) { |
| 439 errln("MessageFormats before and after serialization are not" + |
| 440 " equal\nformat1 = " + format1 + "(" + format1.toPattern() + ")\nfor
mat2 = " + |
| 441 format2 + "(" + format2.toPattern() + ")"); |
| 442 } else { |
| 443 logln("Serialization for MessageFormat is OK."); |
| 444 }*/ |
| 445 } |
| 446 /* @bug 4114743 |
| 447 * MessageFormat.applyPattern allows illegal patterns. |
| 448 */ |
| 449 void MessageFormatRegressionTest::Test4114743() |
| 450 { |
| 451 UnicodeString originalPattern("initial pattern"); |
| 452 UErrorCode status = U_ZERO_ERROR; |
| 453 MessageFormat *mf = new MessageFormat(originalPattern, status); |
| 454 failure(status, "new MessageFormat"); |
| 455 //try { |
| 456 UnicodeString illegalPattern("ab { '}' de"); |
| 457 mf->applyPattern(illegalPattern, status); |
| 458 if( ! U_FAILURE(status)) |
| 459 errln("illegal pattern: \"" + illegalPattern + "\""); |
| 460 /*} catch (IllegalArgumentException foo) { |
| 461 if (!originalPattern.equals(mf.toPattern())) |
| 462 errln("pattern after: \"" + mf.toPattern() + "\""); |
| 463 }*/ |
| 464 delete mf; |
| 465 } |
| 466 |
| 467 /* @bug 4116444 |
| 468 * MessageFormat.parse has different behavior in case of null. |
| 469 */ |
| 470 void MessageFormatRegressionTest::Test4116444() |
| 471 { |
| 472 UnicodeString patterns [] = { |
| 473 (UnicodeString)"", |
| 474 (UnicodeString)"one", |
| 475 (UnicodeString) "{0,date,short}" |
| 476 }; |
| 477 |
| 478 UErrorCode status = U_ZERO_ERROR; |
| 479 MessageFormat *mf = new MessageFormat("", status); |
| 480 failure(status, "new MessageFormat"); |
| 481 |
| 482 for (int i = 0; i < 3; i++) { |
| 483 UnicodeString pattern = patterns[i]; |
| 484 mf->applyPattern(pattern, status); |
| 485 failure(status, "mf->applyPattern", TRUE); |
| 486 |
| 487 //try { |
| 488 int32_t count = 0; |
| 489 ParsePosition pp(0); |
| 490 Formattable *array = mf->parse(UnicodeString(""), pp, count); |
| 491 logln("pattern: \"" + pattern + "\""); |
| 492 log(" parsedObjects: "); |
| 493 if (array != NULL) { |
| 494 log("{"); |
| 495 for (int j = 0; j < count; j++) { |
| 496 //if (array[j] != null) |
| 497 UnicodeString dummy; |
| 498 err("\"" + array[j].getString(dummy) + "\""); |
| 499 //else |
| 500 // log("null"); |
| 501 if (j < count- 1) |
| 502 log(","); |
| 503 } |
| 504 log("}") ; |
| 505 delete[] array; |
| 506 } else { |
| 507 log("null"); |
| 508 } |
| 509 logln(""); |
| 510 /*} catch (Exception e) { |
| 511 errln("pattern: \"" + pattern + "\""); |
| 512 errln(" Exception: " + e.getMessage()); |
| 513 }*/ |
| 514 } |
| 515 |
| 516 delete mf; |
| 517 } |
| 518 /* @bug 4114739 (FIX and add javadoc) |
| 519 * MessageFormat.format has undocumented behavior about empty format objects. |
| 520 */ |
| 521 |
| 522 // {sfb} doesn't apply in C++? |
| 523 void MessageFormatRegressionTest::Test4114739() |
| 524 { |
| 525 |
| 526 UErrorCode status = U_ZERO_ERROR; |
| 527 MessageFormat *mf = new MessageFormat("<{0}>", status); |
| 528 failure(status, "new MessageFormat"); |
| 529 |
| 530 Formattable *objs1 = NULL; |
| 531 //Formattable objs2 [] = {}; |
| 532 //Formattable *objs3 [] = {NULL}; |
| 533 //try { |
| 534 UnicodeString pat; |
| 535 UnicodeString res; |
| 536 logln("pattern: \"" + mf->toPattern(pat) + "\""); |
| 537 log("format(null) : "); |
| 538 FieldPosition pos(FieldPosition::DONT_CARE); |
| 539 logln("\"" + mf->format(objs1, 0, res, pos, status) + "\""); |
| 540 failure(status, "mf->format"); |
| 541 /*log("format({}) : "); |
| 542 logln("\"" + mf->format(objs2, 0, res, FieldPosition(FieldPosition::DONT
_CARE), status) + "\""); |
| 543 failure(status, "mf->format"); |
| 544 log("format({null}) :"); |
| 545 logln("\"" + mf->format(objs3, 0, res, FieldPosition(FieldPosition::DONT
_CARE), status) + "\""); |
| 546 failure(status, "mf->format");*/ |
| 547 /*} catch (Exception e) { |
| 548 errln("Exception thrown for null argument tests."); |
| 549 }*/ |
| 550 |
| 551 delete mf; |
| 552 } |
| 553 |
| 554 /* @bug 4113018 |
| 555 * MessageFormat.applyPattern works wrong with illegal patterns. |
| 556 */ |
| 557 void MessageFormatRegressionTest::Test4113018() |
| 558 { |
| 559 UnicodeString originalPattern("initial pattern"); |
| 560 UErrorCode status = U_ZERO_ERROR; |
| 561 MessageFormat *mf = new MessageFormat(originalPattern, status); |
| 562 failure(status, "new messageFormat"); |
| 563 UnicodeString illegalPattern("format: {0, xxxYYY}"); |
| 564 UnicodeString pat; |
| 565 logln("pattern before: \"" + mf->toPattern(pat) + "\""); |
| 566 logln("illegal pattern: \"" + illegalPattern + "\""); |
| 567 //try { |
| 568 mf->applyPattern(illegalPattern, status); |
| 569 if( ! U_FAILURE(status)) |
| 570 errln("Should have thrown IllegalArgumentException for pattern : " +
illegalPattern); |
| 571 /*} catch (IllegalArgumentException e) { |
| 572 if (!originalPattern.equals(mf.toPattern())) |
| 573 errln("pattern after: \"" + mf.toPattern() + "\""); |
| 574 }*/ |
| 575 delete mf; |
| 576 } |
| 577 |
| 578 /* @bug 4106661 |
| 579 * ChoiceFormat is silent about the pattern usage in javadoc. |
| 580 */ |
| 581 void MessageFormatRegressionTest::Test4106661() |
| 582 { |
| 583 UErrorCode status = U_ZERO_ERROR; |
| 584 ChoiceFormat *fmt = new ChoiceFormat( |
| 585 "-1#are negative| 0#are no or fraction | 1#is one |1.0<is 1+ |2#are two |2
<are more than 2.", status); |
| 586 failure(status, "new ChoiceFormat"); |
| 587 UnicodeString pat; |
| 588 logln("Formatter Pattern : " + fmt->toPattern(pat)); |
| 589 |
| 590 FieldPosition bogus(FieldPosition::DONT_CARE); |
| 591 UnicodeString str; |
| 592 |
| 593 // Will this work for -inf? |
| 594 logln("Format with -INF : " + fmt->format(Formattable(-uprv_getInfinity()),
str, bogus, status)); |
| 595 failure(status, "fmt->format"); |
| 596 str.remove(); |
| 597 logln("Format with -1.0 : " + fmt->format(Formattable(-1.0), str, bogus, sta
tus)); |
| 598 failure(status, "fmt->format"); |
| 599 str.remove(); |
| 600 logln("Format with -1.0 : " + fmt->format(Formattable(-1.0), str, bogus, sta
tus)); |
| 601 failure(status, "fmt->format"); |
| 602 str.remove(); |
| 603 logln("Format with 0 : " + fmt->format(Formattable((int32_t)0), str, bogus,
status)); |
| 604 failure(status, "fmt->format"); |
| 605 str.remove(); |
| 606 logln("Format with 0.9 : " + fmt->format(Formattable(0.9), str, bogus, statu
s)); |
| 607 failure(status, "fmt->format"); |
| 608 str.remove(); |
| 609 logln("Format with 1.0 : " + fmt->format(Formattable(1.0), str, bogus, statu
s)); |
| 610 failure(status, "fmt->format"); |
| 611 str.remove(); |
| 612 logln("Format with 1.5 : " + fmt->format(Formattable(1.5), str, bogus, statu
s)); |
| 613 failure(status, "fmt->format"); |
| 614 str.remove(); |
| 615 logln("Format with 2 : " + fmt->format(Formattable((int32_t)2), str, bogus,
status)); |
| 616 failure(status, "fmt->format"); |
| 617 str.remove(); |
| 618 logln("Format with 2.1 : " + fmt->format(Formattable(2.1), str, bogus, statu
s)); |
| 619 failure(status, "fmt->format"); |
| 620 str.remove(); |
| 621 logln("Format with NaN : " + fmt->format(Formattable(uprv_getNaN()), str, bo
gus, status)); |
| 622 failure(status, "fmt->format"); |
| 623 str.remove(); |
| 624 logln("Format with +INF : " + fmt->format(Formattable(uprv_getInfinity()), s
tr, bogus, status)); |
| 625 failure(status, "fmt->format"); |
| 626 |
| 627 delete fmt; |
| 628 } |
| 629 |
| 630 /* @bug 4094906 |
| 631 * ChoiceFormat should accept \u221E as eq. to INF. |
| 632 */ |
| 633 void MessageFormatRegressionTest::Test4094906() |
| 634 { |
| 635 UErrorCode status = U_ZERO_ERROR; |
| 636 UnicodeString pattern("-"); |
| 637 pattern += (UChar) 0x221E; |
| 638 pattern += "<are negative|0<are no or fraction|1#is one|1<is 1+|"; |
| 639 pattern += (UChar) 0x221E; |
| 640 pattern += "<are many."; |
| 641 |
| 642 ChoiceFormat *fmt = new ChoiceFormat(pattern, status); |
| 643 failure(status, "new ChoiceFormat"); |
| 644 UnicodeString pat; |
| 645 if (fmt->toPattern(pat) != pattern) { |
| 646 errln( (UnicodeString) "Formatter Pattern : " + pat); |
| 647 errln( (UnicodeString) "Expected Pattern : " + pattern); |
| 648 } |
| 649 FieldPosition bogus(FieldPosition::DONT_CARE); |
| 650 UnicodeString str; |
| 651 |
| 652 // Will this work for -inf? |
| 653 logln("Format with -INF : " + fmt->format(Formattable(-uprv_getInfinity()),
str, bogus, status)); |
| 654 failure(status, "fmt->format"); |
| 655 str.remove(); |
| 656 logln("Format with -1.0 : " + fmt->format(Formattable(-1.0), str, bogus, sta
tus)); |
| 657 failure(status, "fmt->format"); |
| 658 str.remove(); |
| 659 logln("Format with -1.0 : " + fmt->format(Formattable(-1.0), str, bogus, sta
tus)); |
| 660 failure(status, "fmt->format"); |
| 661 str.remove(); |
| 662 logln("Format with 0 : " + fmt->format(Formattable((int32_t)0), str, bogus,
status)); |
| 663 failure(status, "fmt->format"); |
| 664 str.remove(); |
| 665 logln("Format with 0.9 : " + fmt->format(Formattable(0.9), str, bogus, statu
s)); |
| 666 failure(status, "fmt->format"); |
| 667 str.remove(); |
| 668 logln("Format with 1.0 : " + fmt->format(Formattable(1.0), str, bogus, statu
s)); |
| 669 failure(status, "fmt->format"); |
| 670 str.remove(); |
| 671 logln("Format with 1.5 : " + fmt->format(Formattable(1.5), str, bogus, statu
s)); |
| 672 failure(status, "fmt->format"); |
| 673 str.remove(); |
| 674 logln("Format with 2 : " + fmt->format(Formattable((int32_t)2), str, bogus,
status)); |
| 675 failure(status, "fmt->format"); |
| 676 str.remove(); |
| 677 logln("Format with 2.1 : " + fmt->format(Formattable(2.1), str, bogus, statu
s)); |
| 678 failure(status, "fmt->format"); |
| 679 str.remove(); |
| 680 logln("Format with NaN : " + fmt->format(Formattable(uprv_getNaN()), str, bo
gus, status)); |
| 681 failure(status, "fmt->format"); |
| 682 str.remove(); |
| 683 logln("Format with +INF : " + fmt->format(Formattable(uprv_getInfinity()), s
tr, bogus, status)); |
| 684 failure(status, "fmt->format"); |
| 685 |
| 686 delete fmt; |
| 687 } |
| 688 |
| 689 /* @bug 4118592 |
| 690 * MessageFormat.parse fails with ChoiceFormat. |
| 691 */ |
| 692 void MessageFormatRegressionTest::Test4118592() |
| 693 { |
| 694 UErrorCode status = U_ZERO_ERROR; |
| 695 MessageFormat *mf = new MessageFormat("", status); |
| 696 failure(status, "new messageFormat"); |
| 697 UnicodeString pattern("{0,choice,1#YES|2#NO}"); |
| 698 UnicodeString prefix(""); |
| 699 Formattable *objs = 0; |
| 700 |
| 701 for (int i = 0; i < 5; i++) { |
| 702 UnicodeString formatted; |
| 703 formatted = prefix + "YES"; |
| 704 mf->applyPattern(prefix + pattern, status); |
| 705 failure(status, "mf->applyPattern"); |
| 706 prefix += "x"; |
| 707 //Object[] objs = mf.parse(formatted, new ParsePosition(0)); |
| 708 int32_t count = 0; |
| 709 ParsePosition pp(0); |
| 710 objs = mf->parse(formatted, pp, count); |
| 711 UnicodeString pat; |
| 712 logln(UnicodeString("") + i + ". pattern :\"" + mf->toPattern(pat) + "\"
"); |
| 713 log(" \"" + formatted + "\" parsed as "); |
| 714 if (objs == NULL) |
| 715 logln(" null"); |
| 716 else { |
| 717 UnicodeString temp; |
| 718 if(objs[0].getType() == Formattable::kString) |
| 719 logln((UnicodeString)" " + objs[0].getString(temp)); |
| 720 else |
| 721 logln((UnicodeString)" " + (objs[0].getType() == Formattable::k
Long ? objs[0].getLong() : objs[0].getDouble())); |
| 722 delete[] objs; |
| 723 |
| 724 } |
| 725 } |
| 726 |
| 727 delete mf; |
| 728 } |
| 729 /* @bug 4118594 |
| 730 * MessageFormat.parse fails for some patterns. |
| 731 */ |
| 732 void MessageFormatRegressionTest::Test4118594() |
| 733 { |
| 734 UErrorCode status = U_ZERO_ERROR; |
| 735 const UBool possibleDataError = TRUE; |
| 736 MessageFormat *mf = new MessageFormat("{0}, {0}, {0}", status); |
| 737 failure(status, "new MessageFormat"); |
| 738 UnicodeString forParsing("x, y, z"); |
| 739 //Object[] objs = mf.parse(forParsing, new ParsePosition(0)); |
| 740 int32_t count = 0; |
| 741 ParsePosition pp(0); |
| 742 Formattable *objs = mf->parse(forParsing, pp, count); |
| 743 UnicodeString pat; |
| 744 logln("pattern: \"" + mf->toPattern(pat) + "\""); |
| 745 logln("text for parsing: \"" + forParsing + "\""); |
| 746 UnicodeString str; |
| 747 if (objs[0].getString(str) != "z") |
| 748 errln("argument0: \"" + objs[0].getString(str) + "\""); |
| 749 mf->applyPattern("{0,number,#.##}, {0,number,#.#}", status); |
| 750 failure(status, "mf->applyPattern", possibleDataError); |
| 751 //Object[] oldobjs = {new Double(3.1415)}; |
| 752 Formattable oldobjs [] = {Formattable(3.1415)}; |
| 753 UnicodeString result; |
| 754 FieldPosition pos(FieldPosition::DONT_CARE); |
| 755 result = mf->format( oldobjs, 1, result, pos, status ); |
| 756 failure(status, "mf->format", possibleDataError); |
| 757 pat.remove(); |
| 758 logln("pattern: \"" + mf->toPattern(pat) + "\""); |
| 759 logln("text for parsing: \"" + result + "\""); |
| 760 // result now equals "3.14, 3.1" |
| 761 if (result != "3.14, 3.1") |
| 762 dataerrln("result = " + result + " - " + u_errorName(status)); |
| 763 //Object[] newobjs = mf.parse(result, new ParsePosition(0)); |
| 764 int32_t count1 = 0; |
| 765 pp.setIndex(0); |
| 766 Formattable *newobjs = mf->parse(result, pp, count1); |
| 767 // newobjs now equals {new Double(3.1)} |
| 768 if (newobjs == NULL) { |
| 769 dataerrln("Error calling MessageFormat::parse"); |
| 770 } else { |
| 771 if (newobjs[0].getDouble() != 3.1) |
| 772 errln( UnicodeString("newobjs[0] = ") + newobjs[0].getDouble()); |
| 773 } |
| 774 |
| 775 delete [] objs; |
| 776 delete [] newobjs; |
| 777 delete mf; |
| 778 } |
| 779 /* @bug 4105380 |
| 780 * When using ChoiceFormat, MessageFormat is not good for I18n. |
| 781 */ |
| 782 void MessageFormatRegressionTest::Test4105380() |
| 783 { |
| 784 UnicodeString patternText1("The disk \"{1}\" contains {0}."); |
| 785 UnicodeString patternText2("There are {0} on the disk \"{1}\""); |
| 786 UErrorCode status = U_ZERO_ERROR; |
| 787 const UBool possibleDataError = TRUE; |
| 788 MessageFormat *form1 = new MessageFormat(patternText1, status); |
| 789 failure(status, "new MessageFormat"); |
| 790 MessageFormat *form2 = new MessageFormat(patternText2, status); |
| 791 failure(status, "new MessageFormat"); |
| 792 double filelimits [] = {0,1,2}; |
| 793 UnicodeString filepart [] = { |
| 794 (UnicodeString)"no files", |
| 795 (UnicodeString)"one file", |
| 796 (UnicodeString)"{0,number} files" |
| 797 }; |
| 798 ChoiceFormat *fileform = new ChoiceFormat(filelimits, filepart, 3); |
| 799 form1->setFormat(1, *fileform); |
| 800 form2->setFormat(0, *fileform); |
| 801 //Object[] testArgs = {new Long(12373), "MyDisk"}; |
| 802 Formattable testArgs [] = { |
| 803 Formattable((int32_t)12373), |
| 804 Formattable((UnicodeString)"MyDisk") |
| 805 }; |
| 806 |
| 807 FieldPosition bogus(FieldPosition::DONT_CARE); |
| 808 |
| 809 UnicodeString result; |
| 810 logln(form1->format(testArgs, 2, result, bogus, status)); |
| 811 failure(status, "form1->format", possibleDataError); |
| 812 result.remove(); |
| 813 logln(form2->format(testArgs, 2, result, bogus, status)); |
| 814 failure(status, "form1->format", possibleDataError); |
| 815 |
| 816 delete form1; |
| 817 delete form2; |
| 818 delete fileform; |
| 819 } |
| 820 /* @bug 4120552 |
| 821 * MessageFormat.parse incorrectly sets errorIndex. |
| 822 */ |
| 823 void MessageFormatRegressionTest::Test4120552() |
| 824 { |
| 825 UErrorCode status = U_ZERO_ERROR; |
| 826 MessageFormat *mf = new MessageFormat("pattern", status); |
| 827 failure(status, "new MessageFormat"); |
| 828 UnicodeString texts[] = { |
| 829 (UnicodeString)"pattern", |
| 830 (UnicodeString)"pat", |
| 831 (UnicodeString)"1234" |
| 832 }; |
| 833 UnicodeString pat; |
| 834 logln("pattern: \"" + mf->toPattern(pat) + "\""); |
| 835 for (int i = 0; i < 3; i++) { |
| 836 ParsePosition pp(0); |
| 837 //Object[] objs = mf.parse(texts[i], pp); |
| 838 int32_t count = 0; |
| 839 Formattable *objs = mf->parse(texts[i], pp, count); |
| 840 log(" text for parsing: \"" + texts[i] + "\""); |
| 841 if (objs == NULL) { |
| 842 logln(" (incorrectly formatted string)"); |
| 843 if (pp.getErrorIndex() == -1) |
| 844 errln(UnicodeString("Incorrect error index: ") + pp.getErrorInde
x()); |
| 845 } else { |
| 846 logln(" (correctly formatted string)"); |
| 847 delete[] objs; |
| 848 } |
| 849 } |
| 850 delete mf; |
| 851 } |
| 852 |
| 853 /** |
| 854 * @bug 4142938 |
| 855 * MessageFormat handles single quotes in pattern wrong. |
| 856 * This is actually a problem in ChoiceFormat; it doesn't |
| 857 * understand single quotes. |
| 858 */ |
| 859 void MessageFormatRegressionTest::Test4142938() |
| 860 { |
| 861 UnicodeString pat = CharsToUnicodeString("''Vous'' {0,choice,0#n''|1#}avez s
\\u00E9lectionn\\u00E9 " |
| 862 "{0,choice,0#aucun|1#{0}} client{0,choice,0#s|1#|2#s} " |
| 863 "personnel{0,choice,0#s|1#|2#s}."); |
| 864 UErrorCode status = U_ZERO_ERROR; |
| 865 MessageFormat *mf = new MessageFormat(pat, status); |
| 866 failure(status, "new MessageFormat"); |
| 867 |
| 868 UnicodeString PREFIX [] = { |
| 869 CharsToUnicodeString("'Vous' n'avez s\\u00E9lectionn\\u00E9 aucun client
s personnels."), |
| 870 CharsToUnicodeString("'Vous' avez s\\u00E9lectionn\\u00E9 "), |
| 871 CharsToUnicodeString("'Vous' avez s\\u00E9lectionn\\u00E9 ") |
| 872 }; |
| 873 UnicodeString SUFFIX [] = { |
| 874 UnicodeString(), |
| 875 UNICODE_STRING(" client personnel.", 18), |
| 876 UNICODE_STRING(" clients personnels.", 20) |
| 877 }; |
| 878 |
| 879 for (int i=0; i<3; i++) { |
| 880 UnicodeString out; |
| 881 //out = mf->format(new Object[]{new Integer(i)}); |
| 882 Formattable objs [] = { |
| 883 Formattable((int32_t)i) |
| 884 }; |
| 885 FieldPosition pos(FieldPosition::DONT_CARE); |
| 886 out = mf->format(objs, 1, out, pos, status); |
| 887 if (!failure(status, "mf->format", TRUE)) { |
| 888 if (SUFFIX[i] == "") { |
| 889 if (out != PREFIX[i]) |
| 890 errln((UnicodeString)"" + i + ": Got \"" + out + "\"; Want \
"" + PREFIX[i] + "\""); |
| 891 } |
| 892 else { |
| 893 if (!out.startsWith(PREFIX[i]) || |
| 894 !out.endsWith(SUFFIX[i])) |
| 895 errln((UnicodeString)"" + i + ": Got \"" + out + "\"; Want \
"" + PREFIX[i] + "\"...\"" + |
| 896 SUFFIX[i] + "\""); |
| 897 } |
| 898 } |
| 899 } |
| 900 |
| 901 delete mf; |
| 902 } |
| 903 |
| 904 /** |
| 905 * @bug 4142938 |
| 906 * Test the applyPattern and toPattern handling of single quotes |
| 907 * by ChoiceFormat. (This is in here because this was a bug reported |
| 908 * against MessageFormat.) The single quote is used to quote the |
| 909 * pattern characters '|', '#', '<', and '\u2264'. Two quotes in a row |
| 910 * is a quote literal. |
| 911 */ |
| 912 void MessageFormatRegressionTest::TestChoicePatternQuote() |
| 913 { |
| 914 UnicodeString DATA [] = { |
| 915 // Pattern 0 value 1 value |
| 916 // {sfb} hacked - changed \u2264 to = (copied from Character Map) |
| 917 (UnicodeString)"0#can''t|1#can", (UnicodeString)"can't",
(UnicodeString)"can", |
| 918 (UnicodeString)"0#'pound(#)=''#'''|1#xyz", (UnicodeString)"pound(#)='#'"
, (UnicodeString)"xyz", |
| 919 (UnicodeString)"0#'1<2 | 1=1'|1#''", (UnicodeString)"1<2 | 1=1", (Unico
deString)"'", |
| 920 }; |
| 921 for (int i=0; i<9; i+=3) { |
| 922 //try { |
| 923 UErrorCode status = U_ZERO_ERROR; |
| 924 ChoiceFormat *cf = new ChoiceFormat(DATA[i], status); |
| 925 failure(status, "new ChoiceFormat"); |
| 926 for (int j=0; j<=1; ++j) { |
| 927 UnicodeString out; |
| 928 FieldPosition pos(FieldPosition::DONT_CARE); |
| 929 out = cf->format((double)j, out, pos); |
| 930 if (out != DATA[i+1+j]) |
| 931 errln("Fail: Pattern \"" + DATA[i] + "\" x "+j+" -> " + |
| 932 out + "; want \"" + DATA[i+1+j] + '"'); |
| 933 } |
| 934 UnicodeString pat; |
| 935 pat = cf->toPattern(pat); |
| 936 UnicodeString pat2; |
| 937 ChoiceFormat *cf2 = new ChoiceFormat(pat, status); |
| 938 pat2 = cf2->toPattern(pat2); |
| 939 if (pat != pat2) |
| 940 errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pa
t + '"'); |
| 941 else |
| 942 logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat
+ '"'); |
| 943 /*} |
| 944 catch (IllegalArgumentException e) { |
| 945 errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e); |
| 946 }*/ |
| 947 |
| 948 delete cf; |
| 949 delete cf2; |
| 950 } |
| 951 } |
| 952 |
| 953 /** |
| 954 * @bug 4112104 |
| 955 * MessageFormat.equals(null) throws a NullPointerException. The JLS states |
| 956 * that it should return false. |
| 957 */ |
| 958 void MessageFormatRegressionTest::Test4112104() |
| 959 { |
| 960 UErrorCode status = U_ZERO_ERROR; |
| 961 MessageFormat *format = new MessageFormat("", status); |
| 962 failure(status, "new MessageFormat"); |
| 963 //try { |
| 964 // This should NOT throw an exception |
| 965 if (format == NULL) { |
| 966 // It also should return false |
| 967 errln("MessageFormat.equals(null) returns false"); |
| 968 } |
| 969 /*} |
| 970 catch (NullPointerException e) { |
| 971 errln("MessageFormat.equals(null) throws " + e); |
| 972 }*/ |
| 973 delete format; |
| 974 } |
| 975 |
| 976 void MessageFormatRegressionTest::TestAPI() { |
| 977 UErrorCode status = U_ZERO_ERROR; |
| 978 MessageFormat *format = new MessageFormat("", status); |
| 979 failure(status, "new MessageFormat"); |
| 980 |
| 981 // Test adoptFormat |
| 982 MessageFormat *fmt = new MessageFormat("",status); |
| 983 format->adoptFormat("",fmt,status); |
| 984 failure(status, "adoptFormat"); |
| 985 |
| 986 // Test getFormat |
| 987 format->setFormat((int32_t)0,*fmt); |
| 988 format->getFormat("",status); |
| 989 failure(status, "getFormat"); |
| 990 delete format; |
| 991 } |
| 992 |
| 993 #endif /* #if !UCONFIG_NO_FORMATTING */ |
OLD | NEW |