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 TestCurrencyPreEuro(void);
41 static void TestCurrencyObject(void);
43 void addNumFrDepTest(TestNode
** root
)
45 addTest(root
, &TestPatterns
, "tsformat/cnmdptst/TestPatterns");
46 addTest(root
, &TestQuotes
, "tsformat/cnmdptst/TestQuotes");
47 addTest(root
, &TestExponential
, "tsformat/cnmdptst/TestExponential");
48 addTest(root
, &TestCurrencySign
, "tsformat/cnmdptst/TestCurrencySign");
49 addTest(root
, &TestCurrency
, "tsformat/cnmdptst/TestCurrency");
50 addTest(root
, &TestCurrencyPreEuro
, "tsformat/cnmdptst/TestCurrencyPreEuro");
51 addTest(root
, &TestCurrencyObject
, "tsformat/cnmdptst/TestCurrencyObject");
52 addTest(root
, &TestRounding487
, "tsformat/cnmdptst/TestRounding487");
53 addTest(root
, &TestDoubleAttribute
, "tsformat/cnmdptst/TestDoubleAttribute");
54 addTest(root
, &TestSecondaryGrouping
, "tsformat/cnmdptst/TestSecondaryGrouping");
55 addTest(root
, &TestCurrencyKeywords
, "tsformat/cnmdptst/TestCurrencyKeywords");
56 addTest(root
, &TestRounding5350
, "tsformat/cnmdptst/TestRounding5350");
57 addTest(root
, &TestGetKeywordValuesForLocale
, "tsformat/cnmdptst/TestGetKeywordValuesForLocale");
60 /*Test Various format patterns*/
61 static void TestPatterns(void)
63 int32_t pat_length
, i
, lneed
;
70 UErrorCode status
= U_ZERO_ERROR
;
71 const char* pat
[] = { "#.#", "#.", ".#", "#" };
72 const char* newpat
[] = { "#0.#", "#0.", "#.0", "#" };
73 const char* num
[] = { "0", "0.", ".0", "0" };
75 log_verbose("\nTesting different format patterns\n");
76 pat_length
= UPRV_LENGTHOF(pat
);
77 for (i
=0; i
< pat_length
; ++i
)
79 status
= U_ZERO_ERROR
;
80 u_uastrcpy(upat
, pat
[i
]);
81 fmt
= unum_open(UNUM_IGNORE
,upat
, u_strlen(upat
), "en_US",NULL
, &status
);
82 if (U_FAILURE(status
)) {
83 log_err_status(status
, "FAIL: Number format constructor failed for pattern %s -> %s\n", pat
[i
], u_errorName(status
));
87 lneed
=unum_toPattern(fmt
, FALSE
, NULL
, lneed
, &status
);
88 if(status
==U_BUFFER_OVERFLOW_ERROR
){
90 unewp
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
91 unum_toPattern(fmt
, FALSE
, unewp
, lneed
+1, &status
);
93 if(U_FAILURE(status
)){
94 log_err("FAIL: Number format extracting the pattern failed for %s\n", pat
[i
]);
96 u_uastrcpy(unewpat
, newpat
[i
]);
97 if(u_strcmp(unewp
, unewpat
) != 0)
98 log_err("FAIL: Pattern %s should be transmute to %s; %s seen instead\n", pat
[i
], newpat
[i
], austrdup(unewp
) );
101 lneed
=unum_format(fmt
, 0, NULL
, lneed
, NULL
, &status
);
102 if(status
==U_BUFFER_OVERFLOW_ERROR
){
104 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
105 unum_format(fmt
, 0, str
, lneed
+1, NULL
, &status
);
107 if(U_FAILURE(status
)) {
108 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
110 u_uastrcpy(unum
, num
[i
]);
111 if (u_strcmp(str
, unum
) != 0)
113 log_err("FAIL: Pattern %s should format zero as %s; %s Seen instead\n", pat
[i
], num
[i
], austrdup(str
) );
122 /* Test the handling of quotes*/
123 static void TestQuotes(void)
126 UErrorCode status
=U_ZERO_ERROR
;
132 log_verbose("\nTestting the handling of quotes in number format\n");
133 u_uastrcpy(pat
, "a'fo''o'b#");
134 fmt
=unum_open(UNUM_IGNORE
,pat
, u_strlen(pat
), "en_US",NULL
, &status
);
135 if(U_FAILURE(status
)){
136 log_err_status(status
, "Error in number format costruction using pattern \"a'fo''o'b#\" -> %s\n", u_errorName(status
));
139 lneed
=unum_format(fmt
, 123, NULL
, lneed
, NULL
, &status
);
140 if(status
==U_BUFFER_OVERFLOW_ERROR
){
142 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
143 unum_format(fmt
, 123, str
, lneed
+1, NULL
, &status
);
145 if(U_FAILURE(status
) || !str
) {
146 log_err_status(status
, "Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
149 log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf
, pat
) );
150 log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf
, str
) );
151 u_uastrcpy(res
, "afo'ob123");
152 if(u_strcmp(str
, res
) != 0)
153 log_err("FAIL: Expected afo'ob123");
160 u_uastrcpy(pat
, "a''b#");
163 fmt
=unum_open(UNUM_IGNORE
,pat
, u_strlen(pat
), "en_US",NULL
, &status
);
164 if(U_FAILURE(status
)){
165 log_err("Error in number format costruction using pattern \"a''b#\"\n");
168 lneed
=unum_format(fmt
, 123, NULL
, lneed
, NULL
, &status
);
169 if(status
==U_BUFFER_OVERFLOW_ERROR
){
171 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
172 unum_format(fmt
, 123, str
, lneed
+1, NULL
, &status
);
174 if(U_FAILURE(status
)) {
175 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
177 log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf
, pat
) );
178 log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf
, str
) );
180 u_uastrcpy(res
, "a'b123");
181 if(u_strcmp(str
, res
) != 0)
182 log_err("FAIL: Expected a'b123\n");
188 /* Test exponential pattern*/
189 static void TestExponential(void)
191 int32_t pat_length
, val_length
, lval_length
;
192 int32_t ival
, ilval
, p
, v
, lneed
;
198 UChar uvalfor
[20], ulvalfor
[20];
199 char tempMsgBug
[256];
201 UErrorCode status
= U_ZERO_ERROR
;
202 #if U_PLATFORM == U_PF_OS390
203 static const double val
[] = { 0.01234, 123456789, 1.23e75
, -3.141592653e-78 };
205 static const double val
[] = { 0.01234, 123456789, 1.23e300
, -3.141592653e-271 };
207 static const char* pat
[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
208 static const int32_t lval
[] = { 0, -1, 1, 123456789 };
210 static const char* valFormat
[] =
212 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
213 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
214 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
215 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
217 static const char* lvalFormat
[] =
219 "0E0", "-1E0", "1E0", "1.2346E8",
220 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
221 "0E000", "-1E000", "1E000", "123.4568E006",
222 "0E0", "[1E0]", "1E0", "1.235E8"
224 static const double valParse
[] =
226 #if U_PLATFORM == U_PF_OS390
227 0.01234, 123460000, 1.23E75
, -3.1416E-78,
228 0.01234, 123460000, 1.23E75
, -3.1416E-78,
229 0.01234, 123456800, 1.23E75
, -3.141593E-78,
230 0.01234, 123500000, 1.23E75
, -3.142E-78
232 /* We define the whole IEEE 754 number in the 4th column because
233 Visual Age 7 has a bug in rounding numbers. */
234 0.01234, 123460000, 1.23E300
, -3.1415999999999999E-271,
235 0.01234, 123460000, 1.23E300
, -3.1415999999999999E-271,
236 0.01234, 123456800, 1.23E300
, -3.1415929999999999E-271,
237 0.01234, 123500000, 1.23E300
, -3.1420000000000001E-271
240 static const int32_t lvalParse
[] =
249 pat_length
= UPRV_LENGTHOF(pat
);
250 val_length
= UPRV_LENGTHOF(val
);
251 lval_length
= UPRV_LENGTHOF(lval
);
254 for (p
=0; p
< pat_length
; ++p
)
256 upat
=(UChar
*)malloc(sizeof(UChar
) * (strlen(pat
[p
])+1) );
257 u_uastrcpy(upat
, pat
[p
]);
258 fmt
=unum_open(UNUM_IGNORE
,upat
, u_strlen(upat
), "en_US",NULL
, &status
);
259 if (U_FAILURE(status
)) {
260 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_PREEURO", "fr_FR_PREEURO"};
422 const char* result
[]={"1,50\\u00a0$", "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
);
458 * Test localized currency patterns for PREEURO variants.
460 static void TestCurrencyPreEuro(void)
462 UNumberFormat
*currencyFmt
;
463 UChar
*str
=NULL
, *res
=NULL
;
466 UErrorCode status
= U_ZERO_ERROR
;
468 const char* locale
[]={
469 "ca_ES_PREEURO", "de_LU_PREEURO", "en_IE_PREEURO", "fi_FI_PREEURO", "fr_LU_PREEURO", "it_IT_PREEURO",
470 "pt_PT_PREEURO", "de_AT_PREEURO", "el_GR_PREEURO", "es_ES_PREEURO", "fr_BE_PREEURO", "ga_IE_PREEURO",
471 "nl_BE_PREEURO", "de_DE_PREEURO", "en_BE_PREEURO", "eu_ES_PREEURO", "fr_FR_PREEURO", "gl_ES_PREEURO",
475 const char* result
[]={
476 "\\u20A7\\u00A02", "2\\u00A0F", "IEP1.50", "1,50\\u00A0mk", "2\\u00A0F", "ITL\\u00A02",
477 "1$50\\u00A0\\u200B", "\\u00F6S\\u00A01,50", "1,50\\u00A0\\u0394\\u03C1\\u03C7", "2\\u00A0\\u20A7", "1,50\\u00A0FB", "IEP1.50",
478 "1,50\\u00A0BEF", "1,50\\u00A0DM", "1,50\\u00A0BEF", "\\u20A7\\u00A02", "1,50\\u00A0F", "2\\u00A0\\u20A7",
482 log_verbose("\nTesting the number format with different currency patterns\n");
483 for(i
=0; i
< 19; i
++)
485 char curID
[256] = {0};
486 uloc_canonicalize(locale
[i
], curID
, 256, &status
);
487 if(U_FAILURE(status
)){
488 log_data_err("Could not canonicalize %s. Error: %s (Are you missing data?)\n", locale
[i
], u_errorName(status
));
491 currencyFmt
= unum_open(UNUM_CURRENCY
, NULL
,0,curID
,NULL
, &status
);
493 if(U_FAILURE(status
)){
494 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
495 myErrorName(status
));
498 lneed
= unum_formatDouble(currencyFmt
, 1.50, NULL
, lneed
, NULL
, &status
);
500 if(status
==U_BUFFER_OVERFLOW_ERROR
){
502 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
504 unum_formatDouble(currencyFmt
, 1.50, str
, lneed
+1, &pos
, &status
);
507 if(U_FAILURE(status
)) {
508 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
510 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(result
[i
])+1) );
511 u_unescape(result
[i
],res
,(int32_t)(strlen(result
[i
])+1));
513 if (u_strcmp(str
, res
) != 0){
514 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result
[i
],aescstrdup(str
, -1),locale
[i
]);
519 unum_close(currencyFmt
);
526 * Test currency "object" (we use this name to match the other C++
527 * test name and the Jave name). Actually, test ISO currency code
528 * support in the C API.
530 static void TestCurrencyObject(void)
532 UNumberFormat
*currencyFmt
;
533 UChar
*str
=NULL
, *res
=NULL
;
536 UErrorCode status
= U_ZERO_ERROR
;
538 const char* locale
[]={
543 const char* currency
[]={
548 const char* result
[]={
549 "1\\u00A0234,56\\u00A0\\u20AC",
550 "1\\u00A0235\\u00A0JPY",
553 log_verbose("\nTesting the number format with different currency codes\n");
557 UChar isoCode
[16]={0};
558 currencyFmt
= unum_open(UNUM_CURRENCY
, NULL
,0,locale
[i
],NULL
, &status
);
559 if(U_FAILURE(status
)){
560 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
561 myErrorName(status
));
564 u_uastrcpy(isoCode
, currency
[i
]);
565 unum_setTextAttribute(currencyFmt
, UNUM_CURRENCY_CODE
,
566 isoCode
, u_strlen(isoCode
), &status
);
568 if(U_FAILURE(status
)) {
569 log_err("FAIL: can't set currency code %s\n", myErrorName(status
) );
573 unum_getTextAttribute(currencyFmt
, UNUM_CURRENCY_CODE
,
574 isoCode
, sizeof(isoCode
), &status
);
576 if(U_FAILURE(status
)) {
577 log_err("FAIL: can't get currency code %s\n", myErrorName(status
) );
580 u_UCharsToChars(isoCode
,cStr
,u_strlen(isoCode
));
581 log_verbose("ISO code %s\n", cStr
);
582 if (*currency
[i
] && uprv_strcmp(cStr
, currency
[i
])) {
583 log_err("FAIL: currency should be %s, but is %s\n", currency
[i
], cStr
);
587 lneed
= unum_formatDouble(currencyFmt
, 1234.56, NULL
, lneed
, NULL
, &status
);
588 if(status
==U_BUFFER_OVERFLOW_ERROR
){
590 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
592 unum_formatDouble(currencyFmt
, 1234.56, str
, lneed
+1, &pos
, &status
);
594 if(U_FAILURE(status
)) {
595 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
597 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(result
[i
])+1) );
598 u_unescape(result
[i
],res
, (int32_t)(strlen(result
[i
])+1));
599 if (u_strcmp(str
, res
) != 0){
600 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result
[i
],aescstrdup(str
, -1),locale
[i
]);
605 unum_close(currencyFmt
);
612 * Test proper rounding by the format method.
614 static void TestRounding487(void)
617 UErrorCode status
= U_ZERO_ERROR
;
618 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
619 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
620 /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
621 nnf
= unum_open(UNUM_DEFAULT
, NULL
,0,"en_US",NULL
, &status
);
623 if(U_FAILURE(status
)){
624 log_data_err("FAIL: failure in the construction of number format: %s (Are you missing data?)\n", myErrorName(status
));
626 roundingTest(nnf
, 0.00159999, 4, "0.0016");
627 roundingTest(nnf
, 0.00995, 4, "0.01");
629 roundingTest(nnf
, 12.3995, 3, "12.4");
631 roundingTest(nnf
, 12.4999, 0, "12");
632 roundingTest(nnf
, - 19.5, 0, "-20");
638 /*-------------------------------------*/
640 static void roundingTest(UNumberFormat
* nf
, double x
, int32_t maxFractionDigits
, const char* expected
)
648 unum_setAttribute(nf
, UNUM_MAX_FRACTION_DIGITS
, maxFractionDigits
);
650 lneed
=unum_formatDouble(nf
, x
, NULL
, lneed
, NULL
, &status
);
651 if(status
==U_BUFFER_OVERFLOW_ERROR
){
653 out
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
655 unum_formatDouble(nf
, x
, out
, lneed
+1, &pos
, &status
);
657 if(U_FAILURE(status
)) {
658 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
660 /*Need to use log_verbose here. Problem with the float*/
661 /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
662 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(expected
)+1) );
663 u_uastrcpy(res
, expected
);
664 if (u_strcmp(out
, res
) != 0)
665 log_err("FAIL: Expected: %s or %s\n", expected
, austrdup(res
) );
673 * Testing unum_getDoubleAttribute and unum_setDoubleAttribute()
675 static void TestDoubleAttribute(void)
677 double mydata
[] = { 1.11, 22.22, 333.33, 4444.44, 55555.55, 666666.66, 7777777.77, 88888888.88, 999999999.99};
680 UErrorCode status
=U_ZERO_ERROR
;
681 UNumberFormatAttribute attr
;
682 UNumberFormatStyle style
= UNUM_DEFAULT
;
685 log_verbose("\nTesting get and set DoubleAttributes\n");
686 def
=unum_open(style
, NULL
,0,NULL
,NULL
, &status
);
688 if (U_FAILURE(status
)) {
689 log_data_err("Fail: error creating a default number formatter -> %s (Are you missing data?)\n", u_errorName(status
));
691 attr
=UNUM_ROUNDING_INCREMENT
;
692 dvalue
=unum_getDoubleAttribute(def
, attr
);
693 for (i
= 0; i
<9 ; i
++)
696 unum_setDoubleAttribute(def
, attr
, dvalue
);
697 if(unum_getDoubleAttribute(def
,attr
)!=mydata
[i
])
698 log_err("Fail: error in setting and getting double attributes for UNUM_ROUNDING_INCREMENT\n");
700 log_verbose("Pass: setting and getting double attributes for UNUM_ROUNDING_INCREMENT works fine\n");
708 * Test the functioning of the secondary grouping value.
710 static void TestSecondaryGrouping(void) {
711 UErrorCode status
= U_ZERO_ERROR
;
712 UNumberFormat
*f
= NULL
, *g
= NULL
;
713 UNumberFormat
*us
= unum_open(UNUM_DECIMAL
,NULL
,0, "en_US", NULL
,&status
);
715 UChar resultBuffer
[512];
716 int32_t l
= 1876543210L;
720 UBool expectGroup
= FALSE
, isGroup
= FALSE
;
722 u_uastrcpy(buffer
, "#,##,###");
723 f
= unum_open(UNUM_IGNORE
,buffer
, -1, "en_US",NULL
, &status
);
724 if (U_FAILURE(status
)) {
725 log_data_err("Error DecimalFormat ct -> %s (Are you missing data?)\n", u_errorName(status
));
730 unum_format(f
, (int32_t)123456789L, resultBuffer
, 512 , &pos
, &status
);
731 u_uastrcpy(buffer
, "12,34,56,789");
732 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
734 log_err("Fail: Formatting \"#,##,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer
, "12,34,56,789");
736 if (pos
.beginIndex
!= 0 && pos
.endIndex
!= 12) {
737 log_err("Fail: Formatting \"#,##,###\" pattern pos = (%d, %d) expected pos = (0, 12)\n", pos
.beginIndex
, pos
.endIndex
);
739 memset(resultBuffer
,0, sizeof(UChar
)*512);
740 unum_toPattern(f
, FALSE
, resultBuffer
, 512, &status
);
741 u_uastrcpy(buffer
, "#,##,###");
742 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
744 log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer
, "#,##,###");
746 memset(resultBuffer
,0, sizeof(UChar
)*512);
747 u_uastrcpy(buffer
, "#,###");
748 unum_applyPattern(f
, FALSE
, buffer
, -1,NULL
,NULL
);
749 if (U_FAILURE(status
))
751 log_err("Fail: applyPattern call failed\n");
753 unum_setAttribute(f
, UNUM_SECONDARY_GROUPING_SIZE
, 4);
754 unum_format(f
, (int32_t)123456789L, resultBuffer
, 512 , &pos
, &status
);
755 u_uastrcpy(buffer
, "12,3456,789");
756 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
758 log_err("Fail: Formatting \"#,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer
, "12,3456,789");
760 memset(resultBuffer
,0, sizeof(UChar
)*512);
761 unum_toPattern(f
, FALSE
, resultBuffer
, 512, &status
);
762 u_uastrcpy(buffer
, "#,####,###");
763 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
765 log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer
, "#,####,###");
767 memset(resultBuffer
,0, sizeof(UChar
)*512);
768 g
= unum_open(UNUM_DECIMAL
, NULL
,0,"hi_IN",NULL
, &status
);
769 if (U_FAILURE(status
))
771 log_err("Fail: Cannot create UNumberFormat for \"hi_IN\" locale.\n");
774 unum_format(g
, l
, resultBuffer
, 512, &pos
, &status
);
776 /* expect "1,87,65,43,210", but with Hindi digits */
778 if (u_strlen(resultBuffer
) != 14) {
781 for (i
=0; i
<u_strlen(resultBuffer
); ++i
) {
791 /* Later -- fix this to get the actual grouping */
792 /* character from the resource bundle. */
793 isGroup
= (UBool
)(resultBuffer
[i
] == 0x002C);
794 if (isGroup
!= expectGroup
) {
801 log_err("FAIL Expected %s x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got %s\n", "1876543210L", resultBuffer
);
807 static void TestCurrencyKeywords(void)
809 static const char * const currencies
[] = {
810 "ADD", "ADP", "AED", "AFA", "AFN", "AIF", "ALK", "ALL", "ALV", "ALX", "AMD",
811 "ANG", "AOA", "AOK", "AON", "AOR", "AOS", "ARA", "ARM", "ARP", "ARS", "ATS",
812 "AUD", "AUP", "AWG", "AZM", "BAD", "BAM", "BAN", "BBD", "BDT", "BEC", "BEF",
813 "BEL", "BGL", "BGM", "BGN", "BGO", "BGX", "BHD", "BIF", "BMD", "BMP", "BND",
814 "BOB", "BOL", "BOP", "BOV", "BRB", "BRC", "BRE", "BRL", "BRN", "BRR", "BRZ",
815 "BSD", "BSP", "BTN", "BTR", "BUK", "BUR", "BWP", "BYB", "BYL", "BYR", "BZD",
816 "BZH", "CAD", "CDF", "CDG", "CDL", "CFF", "CHF", "CKD", "CLC", "CLE", "CLF",
817 "CLP", "CMF", "CNP", "CNX", "CNY", "COB", "COF", "COP", "CRC", "CSC", "CSK",
818 "CUP", "CUX", "CVE", "CWG", "CYP", "CZK", "DDM", "DEM", "DES", "DJF", "DKK",
819 "DOP", "DZD", "DZF", "DZG", "ECS", "ECV", "EEK", "EGP", "ERN", "ESP", "ETB",
820 "ETD", "EUR", "FIM", "FIN", "FJD", "FJP", "FKP", "FOK", "FRF", "FRG", "GAF",
821 "GBP", "GEK", "GEL", "GHC", "GHO", "GHP", "GHR", "GIP", "GLK", "GMD", "GMP",
822 "GNF", "GNI", "GNS", "GPF", "GQE", "GQF", "GQP", "GRD", "GRN", "GTQ", "GUF",
823 "GWE", "GWM", "GWP", "GYD", "HKD", "HNL", "HRD", "HRK", "HTG", "HUF", "IBP",
824 "IDG", "IDJ", "IDN", "IDR", "IEP", "ILL", "ILP", "ILS", "IMP", "INR", "IQD",
825 "IRR", "ISK", "ITL", "JEP", "JMD", "JMP", "JOD", "JPY", "KES", "KGS", "KHO",
826 "KHR", "KID", "KMF", "KPP", "KPW", "KRH", "KRO", "KRW", "KWD", "KYD", "KZR",
827 "KZT", "LAK", "LBP", "LIF", "LKR", "LNR", "LRD", "LSL", "LTL", "LTT", "LUF",
828 "LVL", "LVR", "LYB", "LYD", "LYP", "MAD", "MAF", "MCF", "MCG", "MDC", "MDL",
829 "MDR", "MGA", "MGF", "MHD", "MKD", "MKN", "MLF", "MMK", "MMX", "MNT", "MOP",
830 "MQF", "MRO", "MTL", "MTP", "MUR", "MVP", "MVR", "MWK", "MWP", "MXN", "MXP",
831 "MXV", "MYR", "MZE", "MZM", "NAD", "NCF", "NGN", "NGP", "NHF", "NIC", "NIG",
832 "NIO", "NLG", "NOK", "NPR", "NZD", "NZP", "OMR", "OMS", "PAB", "PDK", "PDN",
833 "PDR", "PEI", "PEN", "PES", "PGK", "PHP", "PKR", "PLN", "PLX", "PLZ", "PSP",
834 "PTC", "PTE", "PYG", "QAR", "REF", "ROL", "RON", "RUB", "RUR", "RWF", "SAR",
835 "SAS", "SBD", "SCR", "SDD", "SDP", "SEK", "SGD", "SHP", "SIB", "SIT", "SKK",
836 "SLL", "SML", "SOS", "SQS", "SRG", "SSP", "STD", "STE", "SUN", "SUR", "SVC",
837 "SYP", "SZL", "TCC", "TDF", "THB", "TJR", "TJS", "TMM", "TND", "TOP", "TOS",
838 "TPE", "TPP", "TRL", "TTD", "TTO", "TVD", "TWD", "TZS", "UAH", "UAK", "UGS",
839 "UGX", "USD", "USN", "USS", "UYF", "UYP", "UYU", "UZC", "UZS", "VAL", "VDD",
840 "VDN", "VDP", "VEB", "VGD", "VND", "VNN", "VNR", "VNS", "VUV", "WSP", "WST",
841 "XAD", "XAF", "XAM", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XCF", "XDR",
842 "XEF", "XEU", "XFO", "XFU", "XID", "XMF", "XNF", "XOF", "XPF", "XPS", "XSS",
843 "XTR", "YDD", "YEI", "YER", "YUD", "YUF", "YUG", "YUM", "YUN", "YUO", "YUR",
844 "ZAL", "ZAP", "ZAR", "ZMK", "ZMP", "ZRN", "ZRZ", "ZWD"
847 UErrorCode status
= U_ZERO_ERROR
;
848 int32_t i
= 0, j
= 0;
849 int32_t noLocales
= uloc_countAvailable();
853 UChar currBuffer
[256];
856 for(i
= 0; i
< noLocales
; i
++) {
857 strcpy(currLoc
, uloc_getAvailable(i
));
858 for(j
= 0; j
< UPRV_LENGTHOF(currencies
); j
++) {
859 strcpy(locale
, currLoc
);
860 strcat(locale
, "@currency=");
861 strcat(locale
, currencies
[j
]);
862 ucurr_forLocale(locale
, result
, 4, &status
);
863 u_charsToUChars(currencies
[j
], currBuffer
, 3);
865 if(u_strcmp(currBuffer
, result
) != 0) {
866 log_err("Didn't get the right currency for %s\n", locale
);
873 static void TestGetKeywordValuesForLocale(void) {
874 #define PREFERRED_SIZE 15
875 #define MAX_NUMBER_OF_KEYWORDS 4
876 const char *PREFERRED
[PREFERRED_SIZE
][MAX_NUMBER_OF_KEYWORDS
] = {
877 { "root", "USD", "USN", NULL
},
878 { "und", "USD", "USN", NULL
},
879 /* { "und_ZZ", "USD", NULL, NULL }, -- temporarily remove as this locale now has 15 entries */
880 { "en_US", "USD", "USN", NULL
},
881 { "en_029", "USD", "USN", NULL
},
882 { "en_TH", "THB", NULL
, NULL
},
883 { "de", "EUR", NULL
, NULL
},
884 { "de_DE", "EUR", NULL
, NULL
},
885 { "ar", "EGP", NULL
, NULL
},
886 { "ar_PS", "ILS", "JOD", NULL
},
887 { "en@currency=CAD", "USD", "USN", NULL
},
888 { "fr@currency=zzz", "EUR", NULL
, NULL
},
889 { "de_DE@currency=DEM", "EUR", NULL
, NULL
},
890 { "en_US@rg=THZZZZ", "THB", NULL
, NULL
},
891 { "de@rg=USZZZZ", "USD", "USN", NULL
},
892 { "en_US@currency=CAD;rg=THZZZZ", "THB", NULL
, NULL
},
894 const int32_t EXPECTED_SIZE
[PREFERRED_SIZE
] = {
895 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1
897 /* ucurr_forLocale results for same locales; "" if no result expected */
898 const char *FORLOCALE
[PREFERRED_SIZE
] = {
900 "THB", "", "EUR", "",
901 "ILS", "CAD", "ZZZ", "DEM",
904 UErrorCode status
= U_ZERO_ERROR
;
906 UEnumeration
*pref
, *all
;
907 const char *loc
= NULL
;
908 UBool matchPref
, matchAll
;
909 const char *value
= NULL
;
910 int32_t valueLength
= 0;
912 UList
*ALLList
= NULL
;
914 UEnumeration
*ALL
= ucurr_getKeywordValuesForLocale("currency", uloc_getDefault(), FALSE
, &status
);
916 log_err_status(status
, "ERROR getting keyword value for default locale. -> %s\n", u_errorName(status
));
920 for (i
= 0; i
< PREFERRED_SIZE
; i
++) {
924 status
= U_ZERO_ERROR
;
927 loc
= PREFERRED
[i
][0];
928 pref
= ucurr_getKeywordValuesForLocale("currency", loc
, TRUE
, &status
);
932 size
= uenum_count(pref
, &status
);
934 if (size
== EXPECTED_SIZE
[i
]) {
936 for (j
= 0; j
< size
; j
++) {
937 if ((value
= uenum_next(pref
, &valueLength
, &status
)) != NULL
&& U_SUCCESS(status
)) {
938 if (uprv_strcmp(value
, PREFERRED
[i
][j
+1]) != 0) {
939 log_err("ERROR: locale %s got keywords #%d %s expected %s\n", loc
, j
, value
, PREFERRED
[i
][j
+1]);
946 log_err("ERROR getting keyword value for locale \"%s\"\n", loc
);
951 log_err("FAIL: size of locale \"%s\" %d does not match expected size %d\n", loc
, size
, EXPECTED_SIZE
[i
]);
955 log_err("FAIL: Preferred values for locale \"%s\" does not match expected.\n", loc
);
960 all
= ucurr_getKeywordValuesForLocale("currency", loc
, FALSE
, &status
);
962 size
= uenum_count(all
, &status
);
964 if (U_SUCCESS(status
) && size
== uenum_count(ALL
, &status
)) {
966 ALLList
= ulist_getListFromEnum(ALL
);
967 for (j
= 0; j
< size
; j
++) {
968 if ((value
= uenum_next(all
, &valueLength
, &status
)) != NULL
&& U_SUCCESS(status
)) {
969 if (!ulist_containsString(ALLList
, value
, uprv_strlen(value
))) {
970 log_err("Locale %s have %s not in ALL\n", loc
, value
);
976 log_err("ERROR getting \"all\" keyword value for locale \"%s\"\n", loc
);
981 log_err("FAIL: All values for locale \"%s\" does not match expected.\n", loc
);
984 if(U_FAILURE(status
)) {
985 log_err("ERROR: %s\n", u_errorName(status
));
986 } else if(size
!=uenum_count(ALL
, &status
)) {
987 log_err("ERROR: got size of %d, wanted %d\n", size
, uenum_count(ALL
, &status
));
993 status
= U_ZERO_ERROR
;
994 getCurrLen
= ucurr_forLocale(loc
, getCurrU
, 4, &status
);
995 if(U_FAILURE(status
)) {
996 if (FORLOCALE
[i
][0] != 0) {
997 log_err("ERROR: ucurr_forLocale %s, status %s\n", loc
, u_errorName(status
));
999 } else if (getCurrLen
!= 3) {
1000 if (FORLOCALE
[i
][0] != 0 || getCurrLen
!= -1) {
1001 log_err("ERROR: ucurr_forLocale %s, returned len %d\n", loc
, getCurrLen
);
1005 u_UCharsToChars(getCurrU
, getCurrB
, 4);
1006 if ( uprv_strncmp(getCurrB
, FORLOCALE
[i
], 4) != 0 ) {
1007 log_err("ERROR: ucurr_forLocale %s, expected %s, got %s\n", loc
, FORLOCALE
[i
], getCurrB
);
1017 * Test proper handling of rounding modes.
1019 static void TestRounding5350(void)
1022 UErrorCode status
= U_ZERO_ERROR
;
1023 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
1024 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
1025 /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
1026 nnf
= unum_open(UNUM_DEFAULT
, NULL
,0,"en_US",NULL
, &status
);
1028 if(U_FAILURE(status
)){
1029 log_data_err("FAIL: failure in the construction of number format: %s (Are you missing data?)\n", myErrorName(status
));
1033 unum_setAttribute(nnf
, UNUM_MAX_FRACTION_DIGITS
, 2);
1034 roundingTest2(nnf
, -0.125, UNUM_ROUND_CEILING
, "-0.12");
1035 roundingTest2(nnf
, -0.125, UNUM_ROUND_FLOOR
, "-0.13");
1036 roundingTest2(nnf
, -0.125, UNUM_ROUND_DOWN
, "-0.12");
1037 roundingTest2(nnf
, -0.125, UNUM_ROUND_UP
, "-0.13");
1038 roundingTest2(nnf
, 0.125, UNUM_FOUND_HALFEVEN
, "0.12");
1039 roundingTest2(nnf
, 0.135, UNUM_ROUND_HALFDOWN
, "0.13");
1040 roundingTest2(nnf
, 0.125, UNUM_ROUND_HALFUP
, "0.13");
1041 roundingTest2(nnf
, 0.135, UNUM_FOUND_HALFEVEN
, "0.14");
1042 /* The following are exactly represented, and shouldn't round */
1043 roundingTest2(nnf
, 1.00, UNUM_ROUND_UP
, "1");
1044 roundingTest2(nnf
, 24.25, UNUM_ROUND_UP
, "24.25");
1045 roundingTest2(nnf
, 24.25, UNUM_ROUND_CEILING
, "24.25");
1046 roundingTest2(nnf
, -24.25, UNUM_ROUND_UP
, "-24.25");
1048 /* Differences pretty far out there */
1049 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_CEILING
, "1.01");
1050 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_FLOOR
, "1");
1051 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_DOWN
, "1");
1052 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_UP
, "1.01");
1053 roundingTest2(nnf
, 1.0000001, UNUM_FOUND_HALFEVEN
, "1");
1054 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_HALFDOWN
, "1");
1055 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_HALFUP
, "1");
1057 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_CEILING
, "-1");
1058 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_FLOOR
, "-1.01");
1059 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_DOWN
, "-1");
1060 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_UP
, "-1.01");
1061 roundingTest2(nnf
, -1.0000001, UNUM_FOUND_HALFEVEN
, "-1");
1062 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_HALFDOWN
, "-1");
1063 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_HALFUP
, "-1");
1068 /*-------------------------------------*/
1070 static void roundingTest2(UNumberFormat
* nf
, double x
, int32_t roundingMode
, const char* expected
)
1077 status
=U_ZERO_ERROR
;
1078 unum_setAttribute(nf
, UNUM_ROUNDING_MODE
, roundingMode
);
1080 lneed
=unum_formatDouble(nf
, x
, NULL
, lneed
, NULL
, &status
);
1081 if(status
==U_BUFFER_OVERFLOW_ERROR
){
1082 status
=U_ZERO_ERROR
;
1083 out
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
1085 unum_formatDouble(nf
, x
, out
, lneed
+1, &pos
, &status
);
1087 if(U_FAILURE(status
)) {
1088 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
1090 /*Need to use log_verbose here. Problem with the float*/
1091 /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
1092 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(expected
)+1) );
1093 u_uastrcpy(res
, expected
);
1094 if (u_strcmp(out
, res
) != 0)
1095 log_err("FAIL: Expected: \"%s\" Got: \"%s\"\n", expected
, austrdup(out
) );
1102 #endif /* #if !UCONFIG_NO_FORMATTING */