1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 1997-2016, International Business Machines Corporation
6 * and others. All Rights Reserved.
7 ********************************************************************/
8 /*******************************************************************************
12 * Madhu Katragadda Creation
13 * Modification History:
15 * Date Name Description
16 * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
17 *******************************************************************************
20 /* C DEPTH TEST FOR NUMBER FORMAT */
22 #include "unicode/utypes.h"
24 #if !UCONFIG_NO_FORMATTING
26 #include "unicode/ucurr.h"
27 #include "unicode/uloc.h"
28 #include "unicode/unum.h"
29 #include "unicode/ustring.h"
30 #include "unicode/putil.h"
37 #define CHECK(status,str) if (U_FAILURE(status)) { log_err("FAIL: %s\n", str); return; }
39 void addNumFrDepTest(TestNode** root);
40 static void TestCurrencyObject(void);
42 void addNumFrDepTest(TestNode** root)
44 addTest(root, &TestPatterns, "tsformat/cnmdptst/TestPatterns");
45 addTest(root, &TestQuotes, "tsformat/cnmdptst/TestQuotes");
46 addTest(root, &TestExponential, "tsformat/cnmdptst/TestExponential");
47 addTest(root, &TestCurrencySign, "tsformat/cnmdptst/TestCurrencySign");
48 addTest(root, &TestCurrency, "tsformat/cnmdptst/TestCurrency");
49 addTest(root, &TestCurrencyObject, "tsformat/cnmdptst/TestCurrencyObject");
50 addTest(root, &TestRounding487, "tsformat/cnmdptst/TestRounding487");
51 addTest(root, &TestDoubleAttribute, "tsformat/cnmdptst/TestDoubleAttribute");
52 addTest(root, &TestSecondaryGrouping, "tsformat/cnmdptst/TestSecondaryGrouping");
53 addTest(root, &TestCurrencyKeywords, "tsformat/cnmdptst/TestCurrencyKeywords");
54 addTest(root, &TestRounding5350, "tsformat/cnmdptst/TestRounding5350");
55 addTest(root, &TestGetKeywordValuesForLocale, "tsformat/cnmdptst/TestGetKeywordValuesForLocale");
58 /*Test Various format patterns*/
59 static void TestPatterns(void)
61 int32_t pat_length, i, lneed;
68 UErrorCode status = U_ZERO_ERROR;
69 const char* pat[] = { "#.#", "#.", ".#", "#" };
70 const char* newpat[] = { "0.#", "0.", "#.0", "0" };
71 const char* num[] = { "0", "0.", ".0", "0" };
73 log_verbose("\nTesting different format patterns\n");
74 pat_length = UPRV_LENGTHOF(pat);
75 for (i=0; i < pat_length; ++i)
77 status = U_ZERO_ERROR;
78 u_uastrcpy(upat, pat[i]);
79 fmt= unum_open(UNUM_IGNORE,upat, u_strlen(upat), "en_US",NULL, &status);
80 if (U_FAILURE(status)) {
81 log_err_status(status, "FAIL: Number format constructor failed for pattern %s -> %s\n", pat[i], u_errorName(status));
85 lneed=unum_toPattern(fmt, FALSE, NULL, lneed, &status);
86 if(status==U_BUFFER_OVERFLOW_ERROR){
88 unewp=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
89 unum_toPattern(fmt, FALSE, unewp, lneed+1, &status);
91 if(U_FAILURE(status)){
92 log_err("FAIL: Number format extracting the pattern failed for %s\n", pat[i]);
94 u_uastrcpy(unewpat, newpat[i]);
95 if(u_strcmp(unewp, unewpat) != 0)
96 log_err("FAIL: Pattern %s should be transmuted to %s; %s seen instead\n", pat[i], newpat[i], austrdup(unewp) );
99 lneed=unum_format(fmt, 0, NULL, lneed, NULL, &status);
100 if(status==U_BUFFER_OVERFLOW_ERROR){
102 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
103 unum_format(fmt, 0, str, lneed+1, NULL, &status);
105 if(U_FAILURE(status)) {
106 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
108 u_uastrcpy(unum, num[i]);
109 if (u_strcmp(str, unum) != 0)
111 log_err("FAIL: Pattern %s should format zero as %s; %s Seen instead\n", pat[i], num[i], austrdup(str) );
120 /* Test the handling of quotes*/
121 static void TestQuotes(void)
124 UErrorCode status=U_ZERO_ERROR;
130 log_verbose("\nTestting the handling of quotes in number format\n");
131 u_uastrcpy(pat, "a'fo''o'b#");
132 fmt =unum_open(UNUM_IGNORE,pat, u_strlen(pat), "en_US",NULL, &status);
133 if(U_FAILURE(status)){
134 log_err_status(status, "Error in number format construction using pattern \"a'fo''o'b#\" -> %s\n", u_errorName(status));
137 lneed=unum_format(fmt, 123, NULL, lneed, NULL, &status);
138 if(status==U_BUFFER_OVERFLOW_ERROR){
140 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
141 unum_format(fmt, 123, str, lneed+1, NULL, &status);
143 if(U_FAILURE(status) || !str) {
144 log_err_status(status, "Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
147 log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf, pat) );
148 log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf, str) );
149 u_uastrcpy(res, "afo'ob123");
150 if(u_strcmp(str, res) != 0)
151 log_err("FAIL: Expected afo'ob123");
158 u_uastrcpy(pat, "a''b#");
161 fmt =unum_open(UNUM_IGNORE,pat, u_strlen(pat), "en_US",NULL, &status);
162 if(U_FAILURE(status)){
163 log_err("Error in number format construction using pattern \"a''b#\"\n");
166 lneed=unum_format(fmt, 123, NULL, lneed, NULL, &status);
167 if(status==U_BUFFER_OVERFLOW_ERROR){
169 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
170 unum_format(fmt, 123, str, lneed+1, NULL, &status);
172 if(U_FAILURE(status)) {
173 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
175 log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf, pat) );
176 log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf, str) );
178 u_uastrcpy(res, "a'b123");
179 if(u_strcmp(str, res) != 0)
180 log_err("FAIL: Expected a'b123\n");
186 /* Test exponential pattern*/
187 static void TestExponential(void)
189 int32_t pat_length, val_length, lval_length;
190 int32_t ival, ilval, p, v, lneed;
196 UChar uvalfor[20], ulvalfor[20];
197 char tempMsgBug[256];
199 UErrorCode status = U_ZERO_ERROR;
200 #if U_PLATFORM == U_PF_OS390
201 static const double val[] = { 0.01234, 123456789, 1.23e75, -3.141592653e-78 };
203 static const double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
205 static const char* pat[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
206 static const int32_t lval[] = { 0, -1, 1, 123456789 };
208 static const char* valFormat[] =
210 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
211 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
212 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
213 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
215 static const char* lvalFormat[] =
217 "0E0", "-1E0", "1E0", "1.2346E8",
218 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
219 "0E000", "-1E000", "1E000", "123.4568E006",
220 "0E0", "[1E0]", "1E0", "1.235E8"
222 static const double valParse[] =
224 #if U_PLATFORM == U_PF_OS390
225 0.01234, 123460000, 1.23E75, -3.1416E-78,
226 0.01234, 123460000, 1.23E75, -3.1416E-78,
227 0.01234, 123456800, 1.23E75, -3.141593E-78,
228 0.01234, 123500000, 1.23E75, -3.142E-78
230 /* We define the whole IEEE 754 number in the 4th column because
231 Visual Age 7 has a bug in rounding numbers. */
232 0.01234, 123460000, 1.23E300, -3.1415999999999999E-271,
233 0.01234, 123460000, 1.23E300, -3.1415999999999999E-271,
234 0.01234, 123456800, 1.23E300, -3.1415929999999999E-271,
235 0.01234, 123500000, 1.23E300, -3.1420000000000001E-271
238 static const int32_t lvalParse[] =
247 pat_length = UPRV_LENGTHOF(pat);
248 val_length = UPRV_LENGTHOF(val);
249 lval_length = UPRV_LENGTHOF(lval);
252 for (p=0; p < pat_length; ++p)
254 upat=(UChar*)malloc(sizeof(UChar) * (strlen(pat[p])+1) );
255 u_uastrcpy(upat, pat[p]);
256 fmt=unum_open(UNUM_IGNORE,upat, u_strlen(upat), "en_US",NULL, &status);
257 if (U_FAILURE(status)) {
258 log_err_status(status, "FAIL: Bad status returned by Number format construction with pattern %s -> %s\n", pat[p], u_errorName(status));
263 lneed= u_strlen(upat) + 1;
264 unum_toPattern(fmt, FALSE, pattern, lneed, &status);
265 log_verbose("Pattern \" %s \" -toPattern-> \" %s \" \n", upat, u_austrcpy(tempMsgBug, pattern) );
266 for (v=0; v<val_length; ++v)
270 lneed=unum_formatDouble(fmt, val[v], NULL, lneed, NULL, &status);
271 if(status==U_BUFFER_OVERFLOW_ERROR){
273 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
274 unum_formatDouble(fmt, val[v], str, lneed+1, NULL, &status);
276 if(U_FAILURE(status)) {
277 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
282 u_uastrcpy(uvalfor, valFormat[v+ival]);
283 if(u_strcmp(str, uvalfor) != 0)
284 log_verbose("FAIL: Expected %s ( %s )\n", valFormat[v+ival], u_austrcpy(tempMsgBug, uvalfor) );
288 a=unum_parseDouble(fmt, str, u_strlen(str), &ppos, &status);
289 if (ppos== u_strlen(str)) {
290 if (a != valParse[v+ival])
291 log_err("FAIL: Expected: %e, Got: %g\n", valParse[v+ival], a);
294 log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos, a);
298 for (v=0; v<lval_length; ++v)
302 lneed=unum_formatDouble(fmt, lval[v], NULL, lneed, NULL, &status);
303 if(status==U_BUFFER_OVERFLOW_ERROR){
305 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
306 unum_formatDouble(fmt, lval[v], str, lneed+1, NULL, &status);
308 if(U_FAILURE(status)) {
309 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
311 /*printf(" Format %e -> %s\n", lval[v], austrdup(str) );*/
312 u_uastrcpy(ulvalfor, lvalFormat[v+ilval]);
313 if(u_strcmp(str, ulvalfor) != 0)
314 log_err("FAIL: Expected %s ( %s )\n", valFormat[v+ilval], austrdup(ulvalfor) );
318 a=unum_parseDouble(fmt, str, u_strlen(str), &ppos, &status);
319 if (ppos== u_strlen(str)) {
320 /*printf(" Parse -> %e\n", a);*/
321 if (a != lvalParse[v+ilval])
322 log_err("FAIL: Expected : %e\n", valParse[v+ival]);
325 log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos, a);
331 ilval += lval_length;
338 * Test the handling of the currency symbol in patterns.
340 static void TestCurrencySign(void)
348 UErrorCode status = U_ZERO_ERROR;
351 pattern=(UChar*)malloc(sizeof(UChar) * (strlen("*#,##0.00;-*#,##0.00") + 1) );
352 u_uastrcpy(pattern, "*#,##0.00;-*#,##0.00");
353 pattern[0]=pattern[11]=0xa4; /* insert latin-1 currency symbol */
354 fmt = unum_open(UNUM_IGNORE,pattern, u_strlen(pattern), "en_US",NULL, &status);
355 if(U_FAILURE(status)){
356 log_err_status(status, "Error in number format construction with pattern \"\\xA4#,##0.00;-\\xA4#,##0.00\\\" -> %s\n", u_errorName(status));
359 lneed=unum_formatDouble(fmt, 1234.56, NULL, lneed, NULL, &status);
360 if(status==U_BUFFER_OVERFLOW_ERROR){
362 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
363 unum_formatDouble(fmt, 1234.56, str, lneed+1, NULL, &status);
365 if(U_FAILURE(status)) {
366 log_err_status(status, "Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
369 lneed=unum_toPattern(fmt, FALSE, NULL, lneed, &status);
370 if(status==U_BUFFER_OVERFLOW_ERROR){
372 pat=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
373 unum_formatDouble(fmt, FALSE, pat, lneed+1, NULL, &status);
375 log_verbose("Pattern \" %s \" \n", u_austrcpy(tempBuf, pat));
376 log_verbose("Format 1234.56 -> %s\n", u_austrcpy(tempBuf, str) );
377 if(U_SUCCESS(status) && str) {
378 res=(UChar*)malloc(sizeof(UChar) * (strlen("$1,234.56")+1) );
379 u_uastrcpy(res, "$1,234.56");
380 if (u_strcmp(str, res) !=0) log_data_err("FAIL: Expected $1,234.56\n");
382 log_err_status(status, "Error formatting -> %s\n", u_errorName(status));
389 lneed=unum_formatDouble(fmt, -1234.56, NULL, lneed, NULL, &status);
390 if(status==U_BUFFER_OVERFLOW_ERROR){
392 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
393 unum_formatDouble(fmt, -1234.56, str, lneed+1, NULL, &status);
395 if(U_FAILURE(status)) {
396 log_err_status(status, "Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
399 res=(UChar*)malloc(sizeof(UChar) * (strlen("-$1,234.56")+1) );
400 u_uastrcpy(res, "-$1,234.56");
401 if (u_strcmp(str, res) != 0) log_data_err("FAIL: Expected -$1,234.56\n");
411 * Test localized currency patterns.
413 static void TestCurrency(void)
415 UNumberFormat *currencyFmt;
420 UErrorCode status = U_ZERO_ERROR;
421 const char* locale[]={"fr_CA", "de_DE@currency=DEM", "fr_FR@currency=FRF"};
422 const char* result[]={"1,50\\u00a0$\\u00a0CA", "1,50\\u00a0DM", "1,50\\u00a0F"};
423 log_verbose("\nTesting the number format with different currency patterns\n");
427 currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,locale[i],NULL, &status);
429 if(U_FAILURE(status)){
430 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
431 myErrorName(status));
434 lneed= unum_formatDouble(currencyFmt, 1.50, NULL, lneed, NULL, &status);
435 if(status==U_BUFFER_OVERFLOW_ERROR){
437 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
439 unum_formatDouble(currencyFmt, 1.50, str, lneed+1, &pos, &status);
442 if(U_FAILURE(status)) {
443 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
445 u_unescape(result[i], res, (int32_t)strlen(result[i])+1);
447 if (u_strcmp(str, res) != 0){
448 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i], aescstrdup(str, -1), locale[i]);
453 unum_close(currencyFmt);
459 * Test currency "object" (we use this name to match the other C++
460 * test name and the Jave name). Actually, test ISO currency code
461 * support in the C API.
463 static void TestCurrencyObject(void)
465 UNumberFormat *currencyFmt;
466 UChar *str=NULL, *res=NULL;
469 UErrorCode status = U_ZERO_ERROR;
471 const char* locale[]={
476 const char* currency[]={
481 const char* result[]={
482 "1\\u202F234,56\\u00A0\\u20AC",
483 "1\\u202F235\\u00A0JPY",
486 log_verbose("\nTesting the number format with different currency codes\n");
490 UChar isoCode[16]={0};
491 currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,locale[i],NULL, &status);
492 if(U_FAILURE(status)){
493 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
494 myErrorName(status));
497 u_uastrcpy(isoCode, currency[i]);
498 unum_setTextAttribute(currencyFmt, UNUM_CURRENCY_CODE,
499 isoCode, u_strlen(isoCode), &status);
501 if(U_FAILURE(status)) {
502 log_err("FAIL: can't set currency code %s\n", myErrorName(status) );
506 unum_getTextAttribute(currencyFmt, UNUM_CURRENCY_CODE,
507 isoCode, sizeof(isoCode), &status);
509 if(U_FAILURE(status)) {
510 log_err("FAIL: can't get currency code %s\n", myErrorName(status) );
513 u_UCharsToChars(isoCode,cStr,u_strlen(isoCode));
514 log_verbose("ISO code %s\n", cStr);
515 if (*currency[i] && uprv_strcmp(cStr, currency[i])) {
516 log_err("FAIL: currency should be %s, but is %s\n", currency[i], cStr);
520 lneed= unum_formatDouble(currencyFmt, 1234.56, NULL, lneed, NULL, &status);
521 if(status==U_BUFFER_OVERFLOW_ERROR){
523 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
525 unum_formatDouble(currencyFmt, 1234.56, str, lneed+1, &pos, &status);
527 if(U_FAILURE(status)) {
528 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
530 res=(UChar*)malloc(sizeof(UChar) * (strlen(result[i])+1) );
531 u_unescape(result[i],res, (int32_t)(strlen(result[i])+1));
532 if (u_strcmp(str, res) != 0){
533 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result[i],aescstrdup(str, -1),locale[i]);
538 unum_close(currencyFmt);
545 * Test proper rounding by the format method.
547 static void TestRounding487(void)
550 UErrorCode status = U_ZERO_ERROR;
551 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
552 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
553 /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
554 nnf = unum_open(UNUM_DEFAULT, NULL,0,"en_US",NULL, &status);
556 if(U_FAILURE(status)){
557 log_data_err("FAIL: failure in the construction of number format: %s (Are you missing data?)\n", myErrorName(status));
559 roundingTest(nnf, 0.00159999, 4, "0.0016");
560 roundingTest(nnf, 0.00995, 4, "0.01");
562 roundingTest(nnf, 12.3995, 3, "12.4");
564 roundingTest(nnf, 12.4999, 0, "12");
565 roundingTest(nnf, - 19.5, 0, "-20");
571 /*-------------------------------------*/
573 static void roundingTest(UNumberFormat* nf, double x, int32_t maxFractionDigits, const char* expected)
581 unum_setAttribute(nf, UNUM_MAX_FRACTION_DIGITS, maxFractionDigits);
583 lneed=unum_formatDouble(nf, x, NULL, lneed, NULL, &status);
584 if(status==U_BUFFER_OVERFLOW_ERROR){
586 out=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
588 unum_formatDouble(nf, x, out, lneed+1, &pos, &status);
590 if(U_FAILURE(status)) {
591 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
593 /*Need to use log_verbose here. Problem with the float*/
594 /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
595 res=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1) );
596 u_uastrcpy(res, expected);
597 if (u_strcmp(out, res) != 0)
598 log_err("FAIL: Expected: %s or %s\n", expected, austrdup(res) );
606 * Testing unum_getDoubleAttribute and unum_setDoubleAttribute()
608 static void TestDoubleAttribute(void)
610 double mydata[] = { 1.11, 22.22, 333.33, 4444.44, 55555.55, 666666.66, 7777777.77, 88888888.88, 999999999.99};
613 UErrorCode status=U_ZERO_ERROR;
614 UNumberFormatAttribute attr;
615 UNumberFormatStyle style= UNUM_DEFAULT;
618 log_verbose("\nTesting get and set DoubleAttributes\n");
619 def=unum_open(style, NULL,0,NULL,NULL, &status);
621 if (U_FAILURE(status)) {
622 log_data_err("Fail: error creating a default number formatter -> %s (Are you missing data?)\n", u_errorName(status));
624 attr=UNUM_ROUNDING_INCREMENT;
625 dvalue=unum_getDoubleAttribute(def, attr);
626 for (i = 0; i<9 ; i++)
629 unum_setDoubleAttribute(def, attr, dvalue);
630 if(unum_getDoubleAttribute(def,attr)!=mydata[i])
631 log_err("Fail: error in setting and getting double attributes for UNUM_ROUNDING_INCREMENT\n");
633 log_verbose("Pass: setting and getting double attributes for UNUM_ROUNDING_INCREMENT works fine\n");
641 * Test the functioning of the secondary grouping value.
643 static void TestSecondaryGrouping(void) {
644 UErrorCode status = U_ZERO_ERROR;
645 UNumberFormat *f = NULL, *g= NULL;
646 UNumberFormat *us = unum_open(UNUM_DECIMAL,NULL,0, "en_US", NULL,&status);
648 UChar resultBuffer[512];
649 int32_t l = 1876543210L;
653 UBool expectGroup = FALSE, isGroup = FALSE;
655 u_uastrcpy(buffer, "#,##,###");
656 f = unum_open(UNUM_IGNORE,buffer, -1, "en_US",NULL, &status);
657 if (U_FAILURE(status)) {
658 log_data_err("Error DecimalFormat ct -> %s (Are you missing data?)\n", u_errorName(status));
663 unum_format(f, (int32_t)123456789L, resultBuffer, 512 , &pos, &status);
664 u_uastrcpy(buffer, "12,34,56,789");
665 if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status))
667 log_err("Fail: Formatting \"#,##,###\" pattern with 123456789 got %s, expected %s\n", austrdup(resultBuffer), "12,34,56,789");
669 if (pos.beginIndex != 0 && pos.endIndex != 12) {
670 log_err("Fail: Formatting \"#,##,###\" pattern pos = (%d, %d) expected pos = (0, 12)\n", pos.beginIndex, pos.endIndex);
672 memset(resultBuffer,0, sizeof(UChar)*512);
673 unum_toPattern(f, FALSE, resultBuffer, 512, &status);
674 u_uastrcpy(buffer, "#,##,##0");
675 if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status))
677 log_err("Fail: toPattern() got %s, expected %s\n", austrdup(resultBuffer), "#,##,##0");
679 memset(resultBuffer,0, sizeof(UChar)*512);
680 u_uastrcpy(buffer, "#,###");
681 unum_applyPattern(f, FALSE, buffer, -1,NULL,NULL);
682 if (U_FAILURE(status))
684 log_err("Fail: applyPattern call failed\n");
686 unum_setAttribute(f, UNUM_SECONDARY_GROUPING_SIZE, 4);
687 unum_format(f, (int32_t)123456789L, resultBuffer, 512 , &pos, &status);
688 u_uastrcpy(buffer, "12,3456,789");
689 if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status))
691 log_err("Fail: Formatting \"#,###\" pattern with 123456789 got %s, expected %s\n", austrdup(resultBuffer), "12,3456,789");
693 memset(resultBuffer,0, sizeof(UChar)*512);
694 unum_toPattern(f, FALSE, resultBuffer, 512, &status);
695 u_uastrcpy(buffer, "#,####,##0");
696 if ((u_strcmp(resultBuffer, buffer) != 0) || U_FAILURE(status))
698 log_err("Fail: toPattern() got %s, expected %s\n", austrdup(resultBuffer), "#,####,##0");
700 memset(resultBuffer,0, sizeof(UChar)*512);
701 g = unum_open(UNUM_DECIMAL, NULL,0,"hi_IN",NULL, &status);
702 if (U_FAILURE(status))
704 log_err("Fail: Cannot create UNumberFormat for \"hi_IN\" locale.\n");
707 unum_format(g, l, resultBuffer, 512, &pos, &status);
709 /* expect "1,87,65,43,210", but with Hindi digits */
711 if (u_strlen(resultBuffer) != 14) {
714 for (i=0; i<u_strlen(resultBuffer); ++i) {
724 /* Later -- fix this to get the actual grouping */
725 /* character from the resource bundle. */
726 isGroup = (UBool)(resultBuffer[i] == 0x002C);
727 if (isGroup != expectGroup) {
734 log_err("FAIL Expected %s x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got %s\n", "1876543210L", resultBuffer);
740 static void TestCurrencyKeywords(void)
742 static const char * const currencies[] = {
743 "ADD", "ADP", "AED", "AFA", "AFN", "AIF", "ALK", "ALL", "ALV", "ALX", "AMD",
744 "ANG", "AOA", "AOK", "AON", "AOR", "AOS", "ARA", "ARM", "ARP", "ARS", "ATS",
745 "AUD", "AUP", "AWG", "AZM", "BAD", "BAM", "BAN", "BBD", "BDT", "BEC", "BEF",
746 "BEL", "BGL", "BGM", "BGN", "BGO", "BGX", "BHD", "BIF", "BMD", "BMP", "BND",
747 "BOB", "BOL", "BOP", "BOV", "BRB", "BRC", "BRE", "BRL", "BRN", "BRR", "BRZ",
748 "BSD", "BSP", "BTN", "BTR", "BUK", "BUR", "BWP", "BYB", "BYL", "BYR", "BZD",
749 "BZH", "CAD", "CDF", "CDG", "CDL", "CFF", "CHF", "CKD", "CLC", "CLE", "CLF",
750 "CLP", "CMF", "CNP", "CNX", "CNY", "COB", "COF", "COP", "CRC", "CSC", "CSK",
751 "CUP", "CUX", "CVE", "CWG", "CYP", "CZK", "DDM", "DEM", "DES", "DJF", "DKK",
752 "DOP", "DZD", "DZF", "DZG", "ECS", "ECV", "EEK", "EGP", "ERN", "ESP", "ETB",
753 "ETD", "EUR", "FIM", "FIN", "FJD", "FJP", "FKP", "FOK", "FRF", "FRG", "GAF",
754 "GBP", "GEK", "GEL", "GHC", "GHO", "GHP", "GHR", "GIP", "GLK", "GMD", "GMP",
755 "GNF", "GNI", "GNS", "GPF", "GQE", "GQF", "GQP", "GRD", "GRN", "GTQ", "GUF",
756 "GWE", "GWM", "GWP", "GYD", "HKD", "HNL", "HRD", "HRK", "HTG", "HUF", "IBP",
757 "IDG", "IDJ", "IDN", "IDR", "IEP", "ILL", "ILP", "ILS", "IMP", "INR", "IQD",
758 "IRR", "ISK", "ITL", "JEP", "JMD", "JMP", "JOD", "JPY", "KES", "KGS", "KHO",
759 "KHR", "KID", "KMF", "KPP", "KPW", "KRH", "KRO", "KRW", "KWD", "KYD", "KZR",
760 "KZT", "LAK", "LBP", "LIF", "LKR", "LNR", "LRD", "LSL", "LTL", "LTT", "LUF",
761 "LVL", "LVR", "LYB", "LYD", "LYP", "MAD", "MAF", "MCF", "MCG", "MDC", "MDL",
762 "MDR", "MGA", "MGF", "MHD", "MKD", "MKN", "MLF", "MMK", "MMX", "MNT", "MOP",
763 "MQF", "MRO", "MTL", "MTP", "MUR", "MVP", "MVR", "MWK", "MWP", "MXN", "MXP",
764 "MXV", "MYR", "MZE", "MZM", "NAD", "NCF", "NGN", "NGP", "NHF", "NIC", "NIG",
765 "NIO", "NLG", "NOK", "NPR", "NZD", "NZP", "OMR", "OMS", "PAB", "PDK", "PDN",
766 "PDR", "PEI", "PEN", "PES", "PGK", "PHP", "PKR", "PLN", "PLX", "PLZ", "PSP",
767 "PTC", "PTE", "PYG", "QAR", "REF", "ROL", "RON", "RUB", "RUR", "RWF", "SAR",
768 "SAS", "SBD", "SCR", "SDD", "SDP", "SEK", "SGD", "SHP", "SIB", "SIT", "SKK",
769 "SLL", "SML", "SOS", "SQS", "SRG", "SSP", "STD", "STE", "SUN", "SUR", "SVC",
770 "SYP", "SZL", "TCC", "TDF", "THB", "TJR", "TJS", "TMM", "TND", "TOP", "TOS",
771 "TPE", "TPP", "TRL", "TTD", "TTO", "TVD", "TWD", "TZS", "UAH", "UAK", "UGS",
772 "UGX", "USD", "USN", "USS", "UYF", "UYP", "UYU", "UZC", "UZS", "VAL", "VDD",
773 "VDN", "VDP", "VEB", "VGD", "VND", "VNN", "VNR", "VNS", "VUV", "WSP", "WST",
774 "XAD", "XAF", "XAM", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XCF", "XDR",
775 "XEF", "XEU", "XFO", "XFU", "XID", "XMF", "XNF", "XOF", "XPF", "XPS", "XSS",
776 "XTR", "YDD", "YEI", "YER", "YUD", "YUF", "YUG", "YUM", "YUN", "YUO", "YUR",
777 "ZAL", "ZAP", "ZAR", "ZMK", "ZMP", "ZRN", "ZRZ", "ZWD"
780 UErrorCode status = U_ZERO_ERROR;
781 int32_t i = 0, j = 0;
782 int32_t noLocales = uloc_countAvailable();
786 UChar currBuffer[256];
789 for(i = 0; i < noLocales; i++) {
790 strcpy(currLoc, uloc_getAvailable(i));
791 for(j = 0; j < UPRV_LENGTHOF(currencies); j++) {
792 strcpy(locale, currLoc);
793 strcat(locale, "@currency=");
794 strcat(locale, currencies[j]);
795 ucurr_forLocale(locale, result, 4, &status);
796 u_charsToUChars(currencies[j], currBuffer, 3);
798 if(u_strcmp(currBuffer, result) != 0) {
799 log_err("Didn't get the right currency for %s\n", locale);
806 static void TestGetKeywordValuesForLocale(void) {
807 #define PREFERRED_SIZE 15
808 #define MAX_NUMBER_OF_KEYWORDS 4
809 const char *PREFERRED[PREFERRED_SIZE][MAX_NUMBER_OF_KEYWORDS] = {
810 { "root", "USD", "USN", NULL },
811 { "und", "USD", "USN", NULL },
812 /* { "und_ZZ", "USD", NULL, NULL }, -- temporarily remove as this locale now has 15 entries */
813 { "en_US", "USD", "USN", NULL },
814 { "en_029", "USD", "USN", NULL },
815 { "en_TH", "THB", NULL, NULL },
816 { "de", "EUR", NULL, NULL },
817 { "de_DE", "EUR", NULL, NULL },
818 { "ar", "EGP", NULL, NULL },
819 { "ar_PS", "ILS", "JOD", NULL },
820 { "en@currency=CAD", "USD", "USN", NULL },
821 { "fr@currency=zzz", "EUR", NULL, NULL },
822 { "de_DE@currency=DEM", "EUR", NULL, NULL },
823 { "en_US@rg=THZZZZ", "THB", NULL, NULL },
824 { "de@rg=USZZZZ", "USD", "USN", NULL },
825 { "en_US@currency=CAD;rg=THZZZZ", "THB", NULL, NULL },
827 const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = {
828 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1
830 /* ucurr_forLocale results for same locales; "" if no result expected */
831 const char *FORLOCALE[PREFERRED_SIZE] = {
833 "THB", "", "EUR", "",
834 "ILS", "CAD", "ZZZ", "DEM",
837 UErrorCode status = U_ZERO_ERROR;
839 UEnumeration *pref, *all;
840 const char *loc = NULL;
841 UBool matchPref, matchAll;
842 const char *value = NULL;
843 int32_t valueLength = 0;
845 UList *ALLList = NULL;
847 UEnumeration *ALL = ucurr_getKeywordValuesForLocale("currency", uloc_getDefault(), FALSE, &status);
849 log_err_status(status, "ERROR getting keyword value for default locale. -> %s\n", u_errorName(status));
853 for (i = 0; i < PREFERRED_SIZE; i++) {
857 status = U_ZERO_ERROR;
860 loc = PREFERRED[i][0];
861 pref = ucurr_getKeywordValuesForLocale("currency", loc, TRUE, &status);
865 size = uenum_count(pref, &status);
867 if (size == EXPECTED_SIZE[i]) {
869 for (j = 0; j < size; j++) {
870 if ((value = uenum_next(pref, &valueLength, &status)) != NULL && U_SUCCESS(status)) {
871 if (uprv_strcmp(value, PREFERRED[i][j+1]) != 0) {
872 log_err("ERROR: locale %s got keywords #%d %s expected %s\n", loc, j, value, PREFERRED[i][j+1]);
879 log_err("ERROR getting keyword value for locale \"%s\"\n", loc);
884 log_err("FAIL: size of locale \"%s\" %d does not match expected size %d\n", loc, size, EXPECTED_SIZE[i]);
888 log_err("FAIL: Preferred values for locale \"%s\" does not match expected.\n", loc);
893 all = ucurr_getKeywordValuesForLocale("currency", loc, FALSE, &status);
895 size = uenum_count(all, &status);
897 if (U_SUCCESS(status) && size == uenum_count(ALL, &status)) {
899 ALLList = ulist_getListFromEnum(ALL);
900 for (j = 0; j < size; j++) {
901 if ((value = uenum_next(all, &valueLength, &status)) != NULL && U_SUCCESS(status)) {
902 if (!ulist_containsString(ALLList, value, (int32_t)uprv_strlen(value))) {
903 log_err("Locale %s have %s not in ALL\n", loc, value);
909 log_err("ERROR getting \"all\" keyword value for locale \"%s\"\n", loc);
914 log_err("FAIL: All values for locale \"%s\" does not match expected.\n", loc);
917 if(U_FAILURE(status)) {
918 log_err("ERROR: %s\n", u_errorName(status));
919 } else if(size!=uenum_count(ALL, &status)) {
920 log_err("ERROR: got size of %d, wanted %d\n", size, uenum_count(ALL, &status));
926 status = U_ZERO_ERROR;
927 getCurrLen = ucurr_forLocale(loc, getCurrU, 4, &status);
928 if(U_FAILURE(status)) {
929 if (FORLOCALE[i][0] != 0) {
930 log_err("ERROR: ucurr_forLocale %s, status %s\n", loc, u_errorName(status));
932 } else if (getCurrLen != 3) {
933 if (FORLOCALE[i][0] != 0 || getCurrLen != -1) {
934 log_err("ERROR: ucurr_forLocale %s, returned len %d\n", loc, getCurrLen);
938 u_UCharsToChars(getCurrU, getCurrB, 4);
939 if ( uprv_strncmp(getCurrB, FORLOCALE[i], 4) != 0 ) {
940 log_err("ERROR: ucurr_forLocale %s, expected %s, got %s\n", loc, FORLOCALE[i], getCurrB);
950 * Test proper handling of rounding modes.
952 static void TestRounding5350(void)
955 UErrorCode status = U_ZERO_ERROR;
956 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
957 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
958 /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
959 nnf = unum_open(UNUM_DEFAULT, NULL,0,"en_US",NULL, &status);
961 if(U_FAILURE(status)){
962 log_data_err("FAIL: failure in the construction of number format: %s (Are you missing data?)\n", myErrorName(status));
966 unum_setAttribute(nnf, UNUM_MAX_FRACTION_DIGITS, 2);
967 roundingTest2(nnf, -0.125, UNUM_ROUND_CEILING, "-0.12");
968 roundingTest2(nnf, -0.125, UNUM_ROUND_FLOOR, "-0.13");
969 roundingTest2(nnf, -0.125, UNUM_ROUND_DOWN, "-0.12");
970 roundingTest2(nnf, -0.125, UNUM_ROUND_UP, "-0.13");
971 roundingTest2(nnf, 0.125, UNUM_FOUND_HALFEVEN, "0.12");
972 roundingTest2(nnf, 0.135, UNUM_ROUND_HALFDOWN, "0.13");
973 roundingTest2(nnf, 0.125, UNUM_ROUND_HALFUP, "0.13");
974 roundingTest2(nnf, 0.135, UNUM_FOUND_HALFEVEN, "0.14");
975 /* The following are exactly represented, and shouldn't round */
976 roundingTest2(nnf, 1.00, UNUM_ROUND_UP, "1");
977 roundingTest2(nnf, 24.25, UNUM_ROUND_UP, "24.25");
978 roundingTest2(nnf, 24.25, UNUM_ROUND_CEILING, "24.25");
979 roundingTest2(nnf, -24.25, UNUM_ROUND_UP, "-24.25");
981 /* Differences pretty far out there */
982 roundingTest2(nnf, 1.0000001, UNUM_ROUND_CEILING, "1.01");
983 roundingTest2(nnf, 1.0000001, UNUM_ROUND_FLOOR, "1");
984 roundingTest2(nnf, 1.0000001, UNUM_ROUND_DOWN, "1");
985 roundingTest2(nnf, 1.0000001, UNUM_ROUND_UP, "1.01");
986 roundingTest2(nnf, 1.0000001, UNUM_FOUND_HALFEVEN, "1");
987 roundingTest2(nnf, 1.0000001, UNUM_ROUND_HALFDOWN, "1");
988 roundingTest2(nnf, 1.0000001, UNUM_ROUND_HALFUP, "1");
990 roundingTest2(nnf, -1.0000001, UNUM_ROUND_CEILING, "-1");
991 roundingTest2(nnf, -1.0000001, UNUM_ROUND_FLOOR, "-1.01");
992 roundingTest2(nnf, -1.0000001, UNUM_ROUND_DOWN, "-1");
993 roundingTest2(nnf, -1.0000001, UNUM_ROUND_UP, "-1.01");
994 roundingTest2(nnf, -1.0000001, UNUM_FOUND_HALFEVEN, "-1");
995 roundingTest2(nnf, -1.0000001, UNUM_ROUND_HALFDOWN, "-1");
996 roundingTest2(nnf, -1.0000001, UNUM_ROUND_HALFUP, "-1");
1001 /*-------------------------------------*/
1003 static void roundingTest2(UNumberFormat* nf, double x, int32_t roundingMode, const char* expected)
1010 status=U_ZERO_ERROR;
1011 unum_setAttribute(nf, UNUM_ROUNDING_MODE, roundingMode);
1013 lneed=unum_formatDouble(nf, x, NULL, lneed, NULL, &status);
1014 if(status==U_BUFFER_OVERFLOW_ERROR){
1015 status=U_ZERO_ERROR;
1016 out=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
1018 unum_formatDouble(nf, x, out, lneed+1, &pos, &status);
1020 if(U_FAILURE(status)) {
1021 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
1023 /*Need to use log_verbose here. Problem with the float*/
1024 /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
1025 res=(UChar*)malloc(sizeof(UChar) * (strlen(expected)+1) );
1026 u_uastrcpy(res, expected);
1027 if (u_strcmp(out, res) != 0)
1028 log_err("FAIL: Expected: \"%s\" Got: \"%s\"\n", expected, austrdup(out) );
1035 #endif /* #if !UCONFIG_NO_FORMATTING */