1/* 2******************************************************************************* 3* Copyright (C) 1997-2015, International Business Machines Corporation and * 4* others. All Rights Reserved. * 5******************************************************************************* 6* 7* File COMPACTDECIMALFORMATTEST.CPP 8* 9******************************************************************************** 10*/ 11#include <stdio.h> 12#include <stdlib.h> 13 14#include "intltest.h" 15 16#if !UCONFIG_NO_FORMATTING 17 18#include "unicode/compactdecimalformat.h" 19#include "unicode/unum.h" 20#include "cmemory.h" 21 22typedef struct ExpectedResult { 23 double value; 24 const char *expected; 25} ExpectedResult; 26 27static const char *kShortStr = "Short"; 28static const char *kLongStr = "Long"; 29 30static ExpectedResult kEnglishShort[] = { 31 {0.0, "0"}, 32 {0.17, "0.17"}, 33 {1.0, "1"}, 34 {1234.0, "1.2K"}, 35 {12345.0, "12K"}, 36 {123456.0, "120K"}, 37 {1234567.0, "1.2M"}, 38 {12345678.0, "12M"}, 39 {123456789.0, "120M"}, 40 {1.23456789E9, "1.2B"}, 41 {1.23456789E10, "12B"}, 42 {1.23456789E11, "120B"}, 43 {1.23456789E12, "1.2T"}, 44 {1.23456789E13, "12T"}, 45 {1.23456789E14, "120T"}, 46 {1.23456789E15, "1200T"}}; 47 48static ExpectedResult kSerbianShort[] = { 49 {1234.0, "1,2\\u00a0\\u0445\\u0438\\u0459."}, 50 {12345.0, "12\\u00a0\\u0445\\u0438\\u0459."}, 51 {20789.0, "21\\u00a0\\u0445\\u0438\\u0459."}, 52 {123456.0, "120\\u00a0\\u0445\\u0438\\u0459."}, 53 {1234567.0, "1,2\\u00A0\\u043C\\u0438\\u043B."}, 54 {12345678.0, "12\\u00A0\\u043C\\u0438\\u043B."}, 55 {123456789.0, "120\\u00A0\\u043C\\u0438\\u043B."}, 56 {1.23456789E9, "1,2\\u00A0\\u043C\\u043B\\u0440\\u0434."}, 57 {1.23456789E10, "12\\u00A0\\u043C\\u043B\\u0440\\u0434."}, 58 {1.23456789E11, "120\\u00A0\\u043C\\u043B\\u0440\\u0434."}, 59 {1.23456789E12, "1,2\\u00A0\\u0431\\u0438\\u043B."}, 60 {1.23456789E13, "12\\u00A0\\u0431\\u0438\\u043B."}, 61 {1.23456789E14, "120\\u00A0\\u0431\\u0438\\u043B."}, 62 {1.23456789E15, "1200\\u00A0\\u0431\\u0438\\u043B."}}; 63 64static ExpectedResult kSerbianLong[] = { 65 {1234.0, "1,2 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"}, // 10^3 few 66 {12345.0, "12 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"}, // 10^3 other 67 {21789.0, "22 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"}, // 10^3 few 68 {123456.0, "120 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"}, // 10^3 other 69 {999999.0, "1 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D"}, // 10^6 one 70 {1234567.0, "1,2 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^6 few 71 {12345678.0, "12 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^6 other 72 {123456789.0, "120 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^6 other 73 {1.23456789E9, "1,2 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"}, // 10^9 few 74 {1.23456789E10, "12 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"}, // 10^9 other 75 {2.08901234E10, "21 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0430"}, // 10^9 one 76 {2.18901234E10, "22 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"}, // 10^9 few 77 {1.23456789E11, "120 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"}, // 10^9 other 78 {1.23456789E12, "1,2 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^12 few 79 {1.23456789E13, "12 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^12 other 80 {1.23456789E14, "120 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^12 other 81 {1.23456789E15, "1200 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}}; // 10^12 other 82 83static ExpectedResult kSerbianLongNegative[] = { 84 {-1234.0, "-1,2 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"}, 85 {-12345.0, "-12 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"}, 86 {-21789.0, "-22 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"}, 87 {-123456.0, "-120 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"}, 88 {-999999.0, "-1 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D"}, 89 {-1234567.0, "-1,2 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, 90 {-12345678.0, "-12 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, 91 {-123456789.0, "-120 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, 92 {-1.23456789E9, "-1,2 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"}, 93 {-1.23456789E10, "-12 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"}, 94 {-2.08901234E10, "-21 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0430"}, 95 {-2.18901234E10, "-22 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"}, 96 {-1.23456789E11, "-120 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"}, 97 {-1.23456789E12, "-1,2 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, 98 {-1.23456789E13, "-12 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, 99 {-1.23456789E14, "-120 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, 100 {-1.23456789E15, "-1200 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}}; 101 102static ExpectedResult kJapaneseShort[] = { 103 {1234.0, "1200"}, 104 {12345.0, "1.2\\u4E07"}, 105 {123456.0, "12\\u4E07"}, 106 {1234567.0, "120\\u4E07"}, 107 {12345678.0, "1200\\u4E07"}, 108 {123456789.0, "1.2\\u5104"}, 109 {1.23456789E9, "12\\u5104"}, 110 {1.23456789E10, "120\\u5104"}, 111 {1.23456789E11, "1200\\u5104"}, 112 {1.23456789E12, "1.2\\u5146"}, 113 {1.23456789E13, "12\\u5146"}, 114 {1.23456789E14, "120\\u5146"}}; 115 116static ExpectedResult kSwahiliShort[] = { 117 {1234.0, "elfu\\u00a01.2"}, 118 {12345.0, "elfu\\u00a012"}, 119 {123456.0, "elfu\\u00a0120"}, 120 {1234567.0, "M1.2"}, 121 {12345678.0, "M12"}, 122 {123456789.0, "M120"}, 123 {1.23456789E9, "B1.2"}, 124 {1.23456789E10, "B12"}, 125 {1.23456789E11, "B120"}, 126 {1.23456789E12, "T1.2"}, 127 {1.23456789E13, "T12"}, 128 {1.23456789E15, "T1200"}}; 129 130static ExpectedResult kCsShort[] = { 131 {1000.0, "1\\u00a0tis."}, 132 {1500.0, "1,5\\u00a0tis."}, 133 {5000.0, "5\\u00a0tis."}, 134 {23000.0, "23\\u00a0tis."}, 135 {127123.0, "130\\u00a0tis."}, 136 {1271234.0, "1,3\\u00a0mil."}, 137 {12712345.0, "13\\u00a0mil."}, 138 {127123456.0, "130\\u00a0mil."}, 139 {1.27123456E9, "1,3\\u00a0mld."}, 140 {1.27123456E10, "13\\u00a0mld."}, 141 {1.27123456E11, "130\\u00a0mld."}, 142 {1.27123456E12, "1,3\\u00a0bil."}, 143 {1.27123456E13, "13\\u00a0bil."}, 144 {1.27123456E14, "130\\u00a0bil."}}; 145 146static ExpectedResult kSkLong[] = { 147 {1000.0, "1 tis\\u00edc"}, 148 {1572.0, "1,6 tis\\u00edca"}, 149 {5184.0, "5,2 tis\\u00edca"}}; 150 151static ExpectedResult kSwahiliShortNegative[] = { 152 {-1234.0, "elfu\\u00a0-1.2"}, 153 {-12345.0, "elfu\\u00a0-12"}, 154 {-123456.0, "elfu\\u00a0-120"}, 155 {-1234567.0, "M-1.2"}, 156 {-12345678.0, "M-12"}, 157 {-123456789.0, "M-120"}, 158 {-1.23456789E9, "B-1.2"}, 159 {-1.23456789E10, "B-12"}, 160 {-1.23456789E11, "B-120"}, 161 {-1.23456789E12, "T-1.2"}, 162 {-1.23456789E13, "T-12"}, 163 {-1.23456789E15, "T-1200"}}; 164 165static ExpectedResult kArabicLong[] = { 166 {-5300.0, "\\u200F-\\u0665\\u066B\\u0663 \\u0623\\u0644\\u0641"}}; 167 168 169class CompactDecimalFormatTest : public IntlTest { 170public: 171 CompactDecimalFormatTest() { 172 } 173 174 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0); 175private: 176 void TestEnglishShort(); 177 void TestSerbianShort(); 178 void TestSerbianLong(); 179 void TestSerbianLongNegative(); 180 void TestJapaneseShort(); 181 void TestSwahiliShort(); 182 void TestCsShort(); 183 void TestSkLong(); 184 void TestSwahiliShortNegative(); 185 void TestArabicLong(); 186 void TestFieldPosition(); 187 void TestSignificantDigits(); 188 void TestAPIVariants(); 189 void CheckLocale( 190 const Locale& locale, UNumberCompactStyle style, 191 const ExpectedResult* expectedResult, int32_t expectedResultLength); 192 void CheckExpectedResult( 193 const CompactDecimalFormat* cdf, const ExpectedResult* expectedResult, 194 const char* description); 195 CompactDecimalFormat* createCDFInstance(const Locale& locale, UNumberCompactStyle style, UErrorCode& status); 196 static const char *StyleStr(UNumberCompactStyle style); 197}; 198 199void CompactDecimalFormatTest::runIndexedTest( 200 int32_t index, UBool exec, const char *&name, char *) { 201 if (exec) { 202 logln("TestSuite CompactDecimalFormatTest: "); 203 } 204 TESTCASE_AUTO_BEGIN; 205 TESTCASE_AUTO(TestEnglishShort); 206 TESTCASE_AUTO(TestSerbianShort); 207 TESTCASE_AUTO(TestSerbianLong); 208 TESTCASE_AUTO(TestSerbianLongNegative); 209 TESTCASE_AUTO(TestJapaneseShort); 210 TESTCASE_AUTO(TestSwahiliShort); 211 TESTCASE_AUTO(TestCsShort); 212 TESTCASE_AUTO(TestSkLong); 213 TESTCASE_AUTO(TestSwahiliShortNegative); 214 TESTCASE_AUTO(TestArabicLong); 215 TESTCASE_AUTO(TestFieldPosition); 216 TESTCASE_AUTO(TestSignificantDigits); 217 TESTCASE_AUTO(TestAPIVariants); 218 TESTCASE_AUTO_END; 219} 220 221void CompactDecimalFormatTest::TestEnglishShort() { 222 CheckLocale("en", UNUM_SHORT, kEnglishShort, UPRV_LENGTHOF(kEnglishShort)); 223} 224 225void CompactDecimalFormatTest::TestSerbianShort() { 226 CheckLocale("sr", UNUM_SHORT, kSerbianShort, UPRV_LENGTHOF(kSerbianShort)); 227} 228 229void CompactDecimalFormatTest::TestSerbianLong() { 230 CheckLocale("sr", UNUM_LONG, kSerbianLong, UPRV_LENGTHOF(kSerbianLong)); 231} 232 233void CompactDecimalFormatTest::TestSerbianLongNegative() { 234 CheckLocale("sr", UNUM_LONG, kSerbianLongNegative, UPRV_LENGTHOF(kSerbianLongNegative)); 235} 236 237void CompactDecimalFormatTest::TestJapaneseShort() { 238 CheckLocale(Locale::getJapan(), UNUM_SHORT, kJapaneseShort, UPRV_LENGTHOF(kJapaneseShort)); 239} 240 241void CompactDecimalFormatTest::TestSwahiliShort() { 242 CheckLocale("sw", UNUM_SHORT, kSwahiliShort, UPRV_LENGTHOF(kSwahiliShort)); 243} 244 245void CompactDecimalFormatTest::TestFieldPosition() { 246 // Swahili uses prefixes which forces offsets in field position to change 247 UErrorCode status = U_ZERO_ERROR; 248 LocalPointer<CompactDecimalFormat> cdf(createCDFInstance("sw", UNUM_SHORT, status)); 249 if (U_FAILURE(status)) { 250 dataerrln("Unable to create format object - %s", u_errorName(status)); 251 return; 252 } 253 FieldPosition fp(UNUM_INTEGER_FIELD); 254 UnicodeString result; 255 cdf->format(1234567.0, result, fp); 256 UnicodeString subString = result.tempSubString(fp.getBeginIndex(), fp.getEndIndex() - fp.getBeginIndex()); 257 if (subString != UnicodeString("1", -1, US_INV)) { 258 errln(UnicodeString("Expected 1, got ") + subString); 259 } 260} 261 262void CompactDecimalFormatTest::TestCsShort() { 263 CheckLocale("cs", UNUM_SHORT, kCsShort, UPRV_LENGTHOF(kCsShort)); 264} 265 266void CompactDecimalFormatTest::TestSkLong() { 267 // In CLDR we have: 268 // 1000 { 269 // few{"0"} 270 // one{"0"} 271 // other{"0"} 272 CheckLocale("sk", UNUM_LONG, kSkLong, UPRV_LENGTHOF(kSkLong)); 273} 274 275void CompactDecimalFormatTest::TestSwahiliShortNegative() { 276 CheckLocale("sw", UNUM_SHORT, kSwahiliShortNegative, UPRV_LENGTHOF(kSwahiliShortNegative)); 277} 278 279void CompactDecimalFormatTest::TestArabicLong() { 280 CheckLocale("ar", UNUM_LONG, kArabicLong, UPRV_LENGTHOF(kArabicLong)); 281} 282 283void CompactDecimalFormatTest::TestSignificantDigits() { 284 UErrorCode status = U_ZERO_ERROR; 285 LocalPointer<CompactDecimalFormat> cdf(CompactDecimalFormat::createInstance("en", UNUM_SHORT, status)); 286 if (U_FAILURE(status)) { 287 dataerrln("Unable to create format object - %s", u_errorName(status)); 288 return; 289 } 290 UnicodeString actual; 291 cdf->format(123456.0, actual); 292 // We expect 3 significant digits by default 293 UnicodeString expected("123K", -1, US_INV); 294 if (actual != expected) { 295 errln(UnicodeString("Fail: Expected: ") + expected + UnicodeString(" Got: ") + actual); 296 } 297} 298 299void CompactDecimalFormatTest::TestAPIVariants() { 300 UErrorCode status = U_ZERO_ERROR; 301 LocalPointer<CompactDecimalFormat> cdf(CompactDecimalFormat::createInstance("en", UNUM_SHORT, status)); 302 if (U_FAILURE(status)) { 303 dataerrln("Unable to create format object - %s", u_errorName(status)); 304 return; 305 } 306 UnicodeString actual; 307 FieldPosition pos; 308 FieldPositionIterator posIter; 309 UnicodeString expected("123K", -1, US_INV); 310 pos.setField(UNUM_INTEGER_FIELD); 311 312 actual.remove(); 313 pos.setBeginIndex(0); 314 pos.setEndIndex(0); 315 cdf->format((double)123456.0, actual, pos); 316 if (actual != expected || pos.getEndIndex() != 3) { 317 errln(UnicodeString("Fail format(double,UnicodeString&,FieldPosition&): Expected: \"") + expected + "\", pos 3; " + 318 "Got: \"" + actual + "\", pos " + pos.getEndIndex()); 319 } 320 321 actual.remove(); 322 pos.setBeginIndex(0); 323 pos.setEndIndex(0); 324 status = U_ZERO_ERROR; 325 cdf->format((double)123456.0, actual, pos, status); 326 if (actual != expected || pos.getEndIndex() != 3 || status != U_ZERO_ERROR) { 327 errln(UnicodeString("Fail format(double,UnicodeString&,FieldPosition&,UErrorCode&): Expected: \"") + expected + "\", pos 3, status U_ZERO_ERROR; " + 328 "Got: \"" + actual + "\", pos " + pos.getEndIndex() + ", status " + u_errorName(status)); 329 } 330 331 actual.remove(); 332 status = U_ZERO_ERROR; 333 cdf->format((double)123456.0, actual, &posIter, status); 334 if (status != U_UNSUPPORTED_ERROR) { 335 errln(UnicodeString("Fail format(double,UnicodeString&,FieldPositionIterator*,UErrorCode&): Expected status U_UNSUPPORTED_ERROR;") + 336 "Got status " + u_errorName(status)); 337 } 338 339 actual.remove(); 340 pos.setBeginIndex(0); 341 pos.setEndIndex(0); 342 cdf->format((int32_t)123456, actual, pos); 343 if (actual != expected || pos.getEndIndex() != 3) { 344 errln(UnicodeString("Fail format(int32_t,UnicodeString&,FieldPosition&): Expected: \"") + expected + "\", pos 3; " + 345 "Got: \"" + actual + "\", pos " + pos.getEndIndex()); 346 } 347 348 actual.remove(); 349 pos.setBeginIndex(0); 350 pos.setEndIndex(0); 351 status = U_ZERO_ERROR; 352 cdf->format((int32_t)123456, actual, pos, status); 353 if (actual != expected || pos.getEndIndex() != 3 || status != U_ZERO_ERROR) { 354 errln(UnicodeString("Fail format(int32_t,UnicodeString&,FieldPosition&,UErrorCode&): Expected: \"") + expected + "\", pos 3, status U_ZERO_ERROR; " + 355 "Got: \"" + actual + "\", pos " + pos.getEndIndex() + ", status " + u_errorName(status)); 356 } 357 358 actual.remove(); 359 status = U_ZERO_ERROR; 360 cdf->format((int32_t)123456, actual, &posIter, status); 361 if (status != U_UNSUPPORTED_ERROR) { 362 errln(UnicodeString("Fail format(int32_t,UnicodeString&,FieldPositionIterator*,UErrorCode&): Expected status U_UNSUPPORTED_ERROR;") + 363 "Got status " + u_errorName(status)); 364 } 365 366 actual.remove(); 367 pos.setBeginIndex(0); 368 pos.setEndIndex(0); 369 cdf->format((int64_t)123456, actual, pos); 370 if (actual != expected || pos.getEndIndex() != 3) { 371 errln(UnicodeString("Fail format(int64_t,UnicodeString&,FieldPosition&): Expected: \"") + expected + "\", pos 3; " + 372 "Got: \"" + actual + "\", pos " + pos.getEndIndex()); 373 } 374 375 actual.remove(); 376 pos.setBeginIndex(0); 377 pos.setEndIndex(0); 378 status = U_ZERO_ERROR; 379 cdf->format((int64_t)123456, actual, pos, status); 380 if (actual != expected || pos.getEndIndex() != 3 || status != U_ZERO_ERROR) { 381 errln(UnicodeString("Fail format(int64_t,UnicodeString&,FieldPosition&,UErrorCode&): Expected: \"") + expected + "\", pos 3, status U_ZERO_ERROR; " + 382 "Got: \"" + actual + "\", pos " + pos.getEndIndex() + ", status " + u_errorName(status)); 383 } 384 385 actual.remove(); 386 status = U_ZERO_ERROR; 387 cdf->format((int64_t)123456, actual, &posIter, status); 388 if (status != U_UNSUPPORTED_ERROR) { 389 errln(UnicodeString("Fail format(int64_t,UnicodeString&,FieldPositionIterator*,UErrorCode&): Expected status U_UNSUPPORTED_ERROR;") + 390 "Got status " + u_errorName(status)); 391 } 392 393} 394 395void CompactDecimalFormatTest::CheckLocale(const Locale& locale, UNumberCompactStyle style, const ExpectedResult* expectedResults, int32_t expectedResultLength) { 396 UErrorCode status = U_ZERO_ERROR; 397 LocalPointer<CompactDecimalFormat> cdf(createCDFInstance(locale, style, status)); 398 if (U_FAILURE(status)) { 399 dataerrln("Unable to create format object - %s", u_errorName(status)); 400 return; 401 } 402 char description[256]; 403 sprintf(description,"%s - %s", locale.getName(), StyleStr(style)); 404 for (int32_t i = 0; i < expectedResultLength; i++) { 405 CheckExpectedResult(cdf.getAlias(), &expectedResults[i], description); 406 } 407} 408 409void CompactDecimalFormatTest::CheckExpectedResult( 410 const CompactDecimalFormat* cdf, const ExpectedResult* expectedResult, const char* description) { 411 UnicodeString actual; 412 cdf->format(expectedResult->value, actual); 413 UnicodeString expected(expectedResult->expected, -1, US_INV); 414 expected = expected.unescape(); 415 if (actual != expected) { 416 errln(UnicodeString("Fail: Expected: ") + expected 417 + UnicodeString(" Got: ") + actual 418 + UnicodeString(" for: ") + UnicodeString(description)); 419 } 420} 421 422CompactDecimalFormat* 423CompactDecimalFormatTest::createCDFInstance(const Locale& locale, UNumberCompactStyle style, UErrorCode& status) { 424 CompactDecimalFormat* result = CompactDecimalFormat::createInstance(locale, style, status); 425 if (U_FAILURE(status)) { 426 return NULL; 427 } 428 // All tests are written for two significant digits, so we explicitly set here 429 // in case default significant digits change. 430 result->setMaximumSignificantDigits(2); 431 return result; 432} 433 434const char *CompactDecimalFormatTest::StyleStr(UNumberCompactStyle style) { 435 if (style == UNUM_SHORT) { 436 return kShortStr; 437 } 438 return kLongStr; 439} 440 441extern IntlTest *createCompactDecimalFormatTest() { 442 return new CompactDecimalFormatTest(); 443} 444 445#endif 446