1 /********************************************************************
3 * Copyright (c) 1997-2011, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ********************************************************************/
6 /*******************************************************************************
10 * Madhu Katragadda Creation
11 * Modification History:
13 * Date Name Description
14 * 06/24/99 helena Integrated Alan's NF enhancements and Java2 bug fixes
15 *******************************************************************************
18 /* C DEPTH TEST FOR NUMBER FORMAT */
20 #include "unicode/utypes.h"
22 #if !UCONFIG_NO_FORMATTING
24 #include "unicode/ucurr.h"
25 #include "unicode/uloc.h"
26 #include "unicode/unum.h"
27 #include "unicode/ustring.h"
34 #define CHECK(status,str) if (U_FAILURE(status)) { log_err("FAIL: %s\n", str); return; }
36 void addNumFrDepTest(TestNode
** root
);
37 static void TestCurrencyPreEuro(void);
38 static void TestCurrencyObject(void);
40 void addNumFrDepTest(TestNode
** root
)
42 addTest(root
, &TestPatterns
, "tsformat/cnmdptst/TestPatterns");
43 addTest(root
, &TestQuotes
, "tsformat/cnmdptst/TestQuotes");
44 addTest(root
, &TestExponential
, "tsformat/cnmdptst/TestExponential");
45 addTest(root
, &TestCurrencySign
, "tsformat/cnmdptst/TestCurrencySign");
46 addTest(root
, &TestCurrency
, "tsformat/cnmdptst/TestCurrency");
47 addTest(root
, &TestCurrencyPreEuro
, "tsformat/cnmdptst/TestCurrencyPreEuro");
48 addTest(root
, &TestCurrencyObject
, "tsformat/cnmdptst/TestCurrencyObject");
49 addTest(root
, &TestRounding487
, "tsformat/cnmdptst/TestRounding487");
50 addTest(root
, &TestDoubleAttribute
, "tsformat/cnmdptst/TestDoubleAttribute");
51 addTest(root
, &TestSecondaryGrouping
, "tsformat/cnmdptst/TestSecondaryGrouping");
52 addTest(root
, &TestCurrencyKeywords
, "tsformat/cnmdptst/TestCurrencyKeywords");
53 addTest(root
, &TestRounding5350
, "tsformat/cnmdptst/TestRounding5350");
54 addTest(root
, &TestGetKeywordValuesForLocale
, "tsformat/cnmdptst/TestGetKeywordValuesForLocale");
57 /*Test Various format patterns*/
58 static void TestPatterns(void)
60 int32_t pat_length
, i
, lneed
;
67 UErrorCode status
= U_ZERO_ERROR
;
68 const char* pat
[] = { "#.#", "#.", ".#", "#" };
69 const char* newpat
[] = { "#0.#", "#0.", "#.0", "#" };
70 const char* num
[] = { "0", "0.", ".0", "0" };
72 log_verbose("\nTesting different format patterns\n");
73 pat_length
= sizeof(pat
) / sizeof(pat
[0]);
74 for (i
=0; i
< pat_length
; ++i
)
76 status
= U_ZERO_ERROR
;
77 u_uastrcpy(upat
, pat
[i
]);
78 fmt
= unum_open(UNUM_IGNORE
,upat
, u_strlen(upat
), "en_US",NULL
, &status
);
79 if (U_FAILURE(status
)) {
80 log_err_status(status
, "FAIL: Number format constructor failed for pattern %s -> %s\n", pat
[i
], u_errorName(status
));
84 lneed
=unum_toPattern(fmt
, FALSE
, NULL
, lneed
, &status
);
85 if(status
==U_BUFFER_OVERFLOW_ERROR
){
87 unewp
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
88 unum_toPattern(fmt
, FALSE
, unewp
, lneed
+1, &status
);
90 if(U_FAILURE(status
)){
91 log_err("FAIL: Number format extracting the pattern failed for %s\n", pat
[i
]);
93 u_uastrcpy(unewpat
, newpat
[i
]);
94 if(u_strcmp(unewp
, unewpat
) != 0)
95 log_err("FAIL: Pattern %s should be transmute to %s; %s seen instead\n", pat
[i
], newpat
[i
], austrdup(unewp
) );
98 lneed
=unum_format(fmt
, 0, NULL
, lneed
, NULL
, &status
);
99 if(status
==U_BUFFER_OVERFLOW_ERROR
){
101 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
102 unum_format(fmt
, 0, str
, lneed
+1, NULL
, &status
);
104 if(U_FAILURE(status
)) {
105 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
107 u_uastrcpy(unum
, num
[i
]);
108 if (u_strcmp(str
, unum
) != 0)
110 log_err("FAIL: Pattern %s should format zero as %s; %s Seen instead\n", pat
[i
], num
[i
], austrdup(str
) );
119 /* Test the handling of quotes*/
120 static void TestQuotes(void)
123 UErrorCode status
=U_ZERO_ERROR
;
129 log_verbose("\nTestting the handling of quotes in number format\n");
130 u_uastrcpy(pat
, "a'fo''o'b#");
131 fmt
=unum_open(UNUM_IGNORE
,pat
, u_strlen(pat
), "en_US",NULL
, &status
);
132 if(U_FAILURE(status
)){
133 log_err_status(status
, "Error in number format costruction using pattern \"a'fo''o'b#\" -> %s\n", u_errorName(status
));
136 lneed
=unum_format(fmt
, 123, NULL
, lneed
, NULL
, &status
);
137 if(status
==U_BUFFER_OVERFLOW_ERROR
){
139 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
140 unum_format(fmt
, 123, str
, lneed
+1, NULL
, &status
);
142 if(U_FAILURE(status
) || !str
) {
143 log_err_status(status
, "Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
146 log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf
, pat
) );
147 log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf
, str
) );
148 u_uastrcpy(res
, "afo'ob123");
149 if(u_strcmp(str
, res
) != 0)
150 log_err("FAIL: Expected afo'ob123");
157 u_uastrcpy(pat
, "a''b#");
160 fmt
=unum_open(UNUM_IGNORE
,pat
, u_strlen(pat
), "en_US",NULL
, &status
);
161 if(U_FAILURE(status
)){
162 log_err("Error in number format costruction using pattern \"a''b#\"\n");
165 lneed
=unum_format(fmt
, 123, NULL
, lneed
, NULL
, &status
);
166 if(status
==U_BUFFER_OVERFLOW_ERROR
){
168 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
169 unum_format(fmt
, 123, str
, lneed
+1, NULL
, &status
);
171 if(U_FAILURE(status
)) {
172 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
174 log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf
, pat
) );
175 log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf
, str
) );
177 u_uastrcpy(res
, "a'b123");
178 if(u_strcmp(str
, res
) != 0)
179 log_err("FAIL: Expected a'b123\n");
185 /* Test exponential pattern*/
186 static void TestExponential(void)
188 int32_t pat_length
, val_length
, lval_length
;
189 int32_t ival
, ilval
, p
, v
, lneed
;
195 UChar uvalfor
[20], ulvalfor
[20];
196 char tempMsgBug
[256];
198 UErrorCode status
= U_ZERO_ERROR
;
199 #if U_PLATFORM == U_PF_OS390
200 static const double val
[] = { 0.01234, 123456789, 1.23e75
, -3.141592653e-78 };
202 static const double val
[] = { 0.01234, 123456789, 1.23e300
, -3.141592653e-271 };
204 static const char* pat
[] = { "0.####E0", "00.000E00", "##0.######E000", "0.###E0;[0.###E0]" };
205 static const int32_t lval
[] = { 0, -1, 1, 123456789 };
207 static const char* valFormat
[] =
209 "1.234E-2", "1.2346E8", "1.23E300", "-3.1416E-271",
210 "12.340E-03", "12.346E07", "12.300E299", "-31.416E-272",
211 "12.34E-003", "123.4568E006", "1.23E300", "-314.1593E-273",
212 "1.234E-2", "1.235E8", "1.23E300", "[3.142E-271]"
214 static const char* lvalFormat
[] =
216 "0E0", "-1E0", "1E0", "1.2346E8",
217 "00.000E00", "-10.000E-01", "10.000E-01", "12.346E07",
218 "0E000", "-1E000", "1E000", "123.4568E006",
219 "0E0", "[1E0]", "1E0", "1.235E8"
221 static const double valParse
[] =
223 #if U_PLATFORM == U_PF_OS390
224 0.01234, 123460000, 1.23E75
, -3.1416E-78,
225 0.01234, 123460000, 1.23E75
, -3.1416E-78,
226 0.01234, 123456800, 1.23E75
, -3.141593E-78,
227 0.01234, 123500000, 1.23E75
, -3.142E-78
229 /* We define the whole IEEE 754 number in the 4th column because
230 Visual Age 7 has a bug in rounding numbers. */
231 0.01234, 123460000, 1.23E300
, -3.1415999999999999E-271,
232 0.01234, 123460000, 1.23E300
, -3.1415999999999999E-271,
233 0.01234, 123456800, 1.23E300
, -3.1415929999999999E-271,
234 0.01234, 123500000, 1.23E300
, -3.1420000000000001E-271
237 static const int32_t lvalParse
[] =
246 pat_length
= sizeof(pat
) / sizeof(pat
[0]);
247 val_length
= sizeof(val
) / sizeof(val
[0]);
248 lval_length
= sizeof(lval
) / sizeof(lval
[0]);
251 for (p
=0; p
< pat_length
; ++p
)
253 upat
=(UChar
*)malloc(sizeof(UChar
) * (strlen(pat
[p
])+1) );
254 u_uastrcpy(upat
, pat
[p
]);
255 fmt
=unum_open(UNUM_IGNORE
,upat
, u_strlen(upat
), "en_US",NULL
, &status
);
256 if (U_FAILURE(status
)) {
257 log_err_status(status
, "FAIL: Bad status returned by Number format construction with pattern %s -> %s\n", pat
[p
], u_errorName(status
));
260 lneed
= u_strlen(upat
) + 1;
261 unum_toPattern(fmt
, FALSE
, pattern
, lneed
, &status
);
262 log_verbose("Pattern \" %s \" -toPattern-> \" %s \" \n", upat
, u_austrcpy(tempMsgBug
, pattern
) );
263 for (v
=0; v
<val_length
; ++v
)
267 lneed
=unum_formatDouble(fmt
, val
[v
], NULL
, lneed
, NULL
, &status
);
268 if(status
==U_BUFFER_OVERFLOW_ERROR
){
270 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
271 unum_formatDouble(fmt
, val
[v
], str
, lneed
+1, NULL
, &status
);
273 if(U_FAILURE(status
)) {
274 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
279 u_uastrcpy(uvalfor
, valFormat
[v
+ival
]);
280 if(u_strcmp(str
, uvalfor
) != 0)
281 log_verbose("FAIL: Expected %s ( %s )\n", valFormat
[v
+ival
], u_austrcpy(tempMsgBug
, uvalfor
) );
285 a
=unum_parseDouble(fmt
, str
, u_strlen(str
), &ppos
, &status
);
286 if (ppos
== u_strlen(str
)) {
287 if (a
!= valParse
[v
+ival
])
288 log_err("FAIL: Expected: %e, Got: %g\n", valParse
[v
+ival
], a
);
291 log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos
, a
);
295 for (v
=0; v
<lval_length
; ++v
)
299 lneed
=unum_formatDouble(fmt
, lval
[v
], NULL
, lneed
, NULL
, &status
);
300 if(status
==U_BUFFER_OVERFLOW_ERROR
){
302 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
303 unum_formatDouble(fmt
, lval
[v
], str
, lneed
+1, NULL
, &status
);
305 if(U_FAILURE(status
)) {
306 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
308 /*printf(" Format %e -> %s\n", lval[v], austrdup(str) );*/
309 u_uastrcpy(ulvalfor
, lvalFormat
[v
+ilval
]);
310 if(u_strcmp(str
, ulvalfor
) != 0)
311 log_err("FAIL: Expected %s ( %s )\n", valFormat
[v
+ilval
], austrdup(ulvalfor
) );
315 a
=unum_parseDouble(fmt
, str
, u_strlen(str
), &ppos
, &status
);
316 if (ppos
== u_strlen(str
)) {
317 /*printf(" Parse -> %e\n", a);*/
318 if (a
!= lvalParse
[v
+ilval
])
319 log_err("FAIL: Expected : %e\n", valParse
[v
+ival
]);
322 log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos
, a
);
328 ilval
+= lval_length
;
335 * Test the handling of the currency symbol in patterns.
337 static void TestCurrencySign(void)
345 UErrorCode status
= U_ZERO_ERROR
;
348 pattern
=(UChar
*)malloc(sizeof(UChar
) * (strlen("*#,##0.00;-*#,##0.00") + 1) );
349 u_uastrcpy(pattern
, "*#,##0.00;-*#,##0.00");
350 pattern
[0]=pattern
[11]=0xa4; /* insert latin-1 currency symbol */
351 fmt
= unum_open(UNUM_IGNORE
,pattern
, u_strlen(pattern
), "en_US",NULL
, &status
);
352 if(U_FAILURE(status
)){
353 log_err_status(status
, "Error in number format construction with pattern \"\\xA4#,##0.00;-\\xA4#,##0.00\\\" -> %s\n", u_errorName(status
));
356 lneed
=unum_formatDouble(fmt
, 1234.56, NULL
, lneed
, NULL
, &status
);
357 if(status
==U_BUFFER_OVERFLOW_ERROR
){
359 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
360 unum_formatDouble(fmt
, 1234.56, str
, lneed
+1, NULL
, &status
);
362 if(U_FAILURE(status
)) {
363 log_err_status(status
, "Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
366 lneed
=unum_toPattern(fmt
, FALSE
, NULL
, lneed
, &status
);
367 if(status
==U_BUFFER_OVERFLOW_ERROR
){
369 pat
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
370 unum_formatDouble(fmt
, FALSE
, pat
, lneed
+1, NULL
, &status
);
372 log_verbose("Pattern \" %s \" \n", u_austrcpy(tempBuf
, pat
));
373 log_verbose("Format 1234.56 -> %s\n", u_austrcpy(tempBuf
, str
) );
374 if(U_SUCCESS(status
) && str
) {
375 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen("$1,234.56")+1) );
376 u_uastrcpy(res
, "$1,234.56");
377 if (u_strcmp(str
, res
) !=0) log_data_err("FAIL: Expected $1,234.56\n");
379 log_err_status(status
, "Error formatting -> %s\n", u_errorName(status
));
386 lneed
=unum_formatDouble(fmt
, -1234.56, NULL
, lneed
, NULL
, &status
);
387 if(status
==U_BUFFER_OVERFLOW_ERROR
){
389 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
390 unum_formatDouble(fmt
, -1234.56, str
, lneed
+1, NULL
, &status
);
392 if(U_FAILURE(status
)) {
393 log_err_status(status
, "Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
396 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen("-$1,234.56")+1) );
397 u_uastrcpy(res
, "-$1,234.56");
398 if (u_strcmp(str
, res
) != 0) log_data_err("FAIL: Expected -$1,234.56\n");
408 * Test localized currency patterns.
410 static void TestCurrency(void)
412 UNumberFormat
*currencyFmt
;
417 UErrorCode status
= U_ZERO_ERROR
;
418 const char* locale
[]={"fr_CA", "de_DE_PREEURO", "fr_FR_PREEURO"};
419 const char* result
[]={"1,50\\u00a0$", "1,50\\u00a0DEM", "1,50\\u00a0F"};
420 log_verbose("\nTesting the number format with different currency patterns\n");
424 currencyFmt
= unum_open(UNUM_CURRENCY
, NULL
,0,locale
[i
],NULL
, &status
);
426 if(U_FAILURE(status
)){
427 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
428 myErrorName(status
));
431 lneed
= unum_formatDouble(currencyFmt
, 1.50, NULL
, lneed
, NULL
, &status
);
432 if(status
==U_BUFFER_OVERFLOW_ERROR
){
434 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
436 unum_formatDouble(currencyFmt
, 1.50, str
, lneed
+1, &pos
, &status
);
439 if(U_FAILURE(status
)) {
440 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
442 u_unescape(result
[i
], res
, (int32_t)strlen(result
[i
])+1);
444 if (u_strcmp(str
, res
) != 0){
445 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result
[i
], aescstrdup(str
, -1), locale
[i
]);
450 unum_close(currencyFmt
);
455 * Test localized currency patterns for PREEURO variants.
457 static void TestCurrencyPreEuro(void)
459 UNumberFormat
*currencyFmt
;
460 UChar
*str
=NULL
, *res
=NULL
;
463 UErrorCode status
= U_ZERO_ERROR
;
465 const char* locale
[]={
466 "ca_ES_PREEURO", "de_LU_PREEURO", "en_IE_PREEURO", "fi_FI_PREEURO", "fr_LU_PREEURO", "it_IT_PREEURO",
467 "pt_PT_PREEURO", "de_AT_PREEURO", "el_GR_PREEURO", "es_ES_PREEURO", "fr_BE_PREEURO", "ga_IE_PREEURO",
468 "nl_BE_PREEURO", "de_DE_PREEURO", "en_BE_PREEURO", "eu_ES_PREEURO", "fr_FR_PREEURO", "gl_ES_PREEURO",
472 const char* result
[]={
473 "2\\u00A0\\u20A7", "2\\u00A0F", "IEP1.50", "1,50\\u00A0FIM", "2\\u00A0F", "ITL\\u00A02",
474 "1$50\\u00A0Esc.", "\\u00F6S\\u00A01,50", "1,50\\u00A0\\u0394\\u03C1\\u03C7", "2\\u00A0\\u20A7", "1,50\\u00A0FB", "IEP1.50",
475 "1,50\\u00A0BEF", "1,50\\u00A0DEM", "1,50\\u00A0BEF", "2\\u00A0\\u20A7", "1,50\\u00A0F", "2\\u00A0\\u20A7",
479 log_verbose("\nTesting the number format with different currency patterns\n");
480 for(i
=0; i
< 19; i
++)
482 char curID
[256] = {0};
483 uloc_canonicalize(locale
[i
], curID
, 256, &status
);
484 if(U_FAILURE(status
)){
485 log_data_err("Could not canonicalize %s. Error: %s (Are you missing data?)\n", locale
[i
], u_errorName(status
));
488 currencyFmt
= unum_open(UNUM_CURRENCY
, NULL
,0,curID
,NULL
, &status
);
490 if(U_FAILURE(status
)){
491 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
492 myErrorName(status
));
495 lneed
= unum_formatDouble(currencyFmt
, 1.50, NULL
, lneed
, NULL
, &status
);
497 if(status
==U_BUFFER_OVERFLOW_ERROR
){
499 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
501 unum_formatDouble(currencyFmt
, 1.50, str
, lneed
+1, &pos
, &status
);
504 if(U_FAILURE(status
)) {
505 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
507 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(result
[i
])+1) );
508 u_unescape(result
[i
],res
,(int32_t)(strlen(result
[i
])+1));
510 if (u_strcmp(str
, res
) != 0){
511 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result
[i
],aescstrdup(str
, -1),locale
[i
]);
516 unum_close(currencyFmt
);
523 * Test currency "object" (we use this name to match the other C++
524 * test name and the Jave name). Actually, test ISO currency code
525 * support in the C API.
527 static void TestCurrencyObject(void)
529 UNumberFormat
*currencyFmt
;
530 UChar
*str
=NULL
, *res
=NULL
;
533 UErrorCode status
= U_ZERO_ERROR
;
535 const char* locale
[]={
540 const char* currency
[]={
545 const char* result
[]={
546 "1\\u00A0234,56\\u00A0\\u20AC",
547 "1\\u00A0235\\u00A0\\u00A5JP",
550 log_verbose("\nTesting the number format with different currency codes\n");
554 UChar isoCode
[16]={0};
555 currencyFmt
= unum_open(UNUM_CURRENCY
, NULL
,0,locale
[i
],NULL
, &status
);
556 if(U_FAILURE(status
)){
557 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
558 myErrorName(status
));
561 u_uastrcpy(isoCode
, currency
[i
]);
562 unum_setTextAttribute(currencyFmt
, UNUM_CURRENCY_CODE
,
563 isoCode
, u_strlen(isoCode
), &status
);
565 if(U_FAILURE(status
)) {
566 log_err("FAIL: can't set currency code %s\n", myErrorName(status
) );
570 unum_getTextAttribute(currencyFmt
, UNUM_CURRENCY_CODE
,
571 isoCode
, sizeof(isoCode
), &status
);
573 if(U_FAILURE(status
)) {
574 log_err("FAIL: can't get currency code %s\n", myErrorName(status
) );
577 u_UCharsToChars(isoCode
,cStr
,u_strlen(isoCode
));
578 log_verbose("ISO code %s\n", cStr
);
579 if (*currency
[i
] && uprv_strcmp(cStr
, currency
[i
])) {
580 log_err("FAIL: currency should be %s, but is %s\n", currency
[i
], cStr
);
584 lneed
= unum_formatDouble(currencyFmt
, 1234.56, NULL
, lneed
, NULL
, &status
);
585 if(status
==U_BUFFER_OVERFLOW_ERROR
){
587 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
589 unum_formatDouble(currencyFmt
, 1234.56, str
, lneed
+1, &pos
, &status
);
591 if(U_FAILURE(status
)) {
592 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
594 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(result
[i
])+1) );
595 u_unescape(result
[i
],res
, (int32_t)(strlen(result
[i
])+1));
596 if (u_strcmp(str
, res
) != 0){
597 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result
[i
],aescstrdup(str
, -1),locale
[i
]);
602 unum_close(currencyFmt
);
609 * Test proper rounding by the format method.
611 static void TestRounding487(void)
614 UErrorCode status
= U_ZERO_ERROR
;
615 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
616 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
617 /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
618 nnf
= unum_open(UNUM_DEFAULT
, NULL
,0,"en_US",NULL
, &status
);
620 if(U_FAILURE(status
)){
621 log_data_err("FAIL: failure in the construction of number format: %s (Are you missing data?)\n", myErrorName(status
));
623 roundingTest(nnf
, 0.00159999, 4, "0.0016");
624 roundingTest(nnf
, 0.00995, 4, "0.01");
626 roundingTest(nnf
, 12.3995, 3, "12.4");
628 roundingTest(nnf
, 12.4999, 0, "12");
629 roundingTest(nnf
, - 19.5, 0, "-20");
635 /*-------------------------------------*/
637 static void roundingTest(UNumberFormat
* nf
, double x
, int32_t maxFractionDigits
, const char* expected
)
645 unum_setAttribute(nf
, UNUM_MAX_FRACTION_DIGITS
, maxFractionDigits
);
647 lneed
=unum_formatDouble(nf
, x
, NULL
, lneed
, NULL
, &status
);
648 if(status
==U_BUFFER_OVERFLOW_ERROR
){
650 out
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
652 unum_formatDouble(nf
, x
, out
, lneed
+1, &pos
, &status
);
654 if(U_FAILURE(status
)) {
655 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
657 /*Need to use log_verbose here. Problem with the float*/
658 /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
659 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(expected
)+1) );
660 u_uastrcpy(res
, expected
);
661 if (u_strcmp(out
, res
) != 0)
662 log_err("FAIL: Expected: %s or %s\n", expected
, austrdup(res
) );
670 * Testing unum_getDoubleAttribute and unum_setDoubleAttribute()
672 static void TestDoubleAttribute(void)
674 double mydata
[] = { 1.11, 22.22, 333.33, 4444.44, 55555.55, 666666.66, 7777777.77, 88888888.88, 999999999.99};
677 UErrorCode status
=U_ZERO_ERROR
;
678 UNumberFormatAttribute attr
;
679 UNumberFormatStyle style
= UNUM_DEFAULT
;
682 log_verbose("\nTesting get and set DoubleAttributes\n");
683 def
=unum_open(style
, NULL
,0,NULL
,NULL
, &status
);
685 if (U_FAILURE(status
)) {
686 log_data_err("Fail: error creating a default number formatter -> %s (Are you missing data?)\n", u_errorName(status
));
688 attr
=UNUM_ROUNDING_INCREMENT
;
689 dvalue
=unum_getDoubleAttribute(def
, attr
);
690 for (i
= 0; i
<9 ; i
++)
693 unum_setDoubleAttribute(def
, attr
, dvalue
);
694 if(unum_getDoubleAttribute(def
,attr
)!=mydata
[i
])
695 log_err("Fail: error in setting and getting double attributes for UNUM_ROUNDING_INCREMENT\n");
697 log_verbose("Pass: setting and getting double attributes for UNUM_ROUNDING_INCREMENT works fine\n");
705 * Test the functioning of the secondary grouping value.
707 static void TestSecondaryGrouping(void) {
708 UErrorCode status
= U_ZERO_ERROR
;
709 UNumberFormat
*f
= NULL
, *g
= NULL
;
710 UNumberFormat
*us
= unum_open(UNUM_DECIMAL
,NULL
,0, "en_US", NULL
,&status
);
712 UChar resultBuffer
[512];
713 int32_t l
= 1876543210L;
717 UBool expectGroup
= FALSE
, isGroup
= FALSE
;
719 u_uastrcpy(buffer
, "#,##,###");
720 f
= unum_open(UNUM_IGNORE
,buffer
, -1, "en_US",NULL
, &status
);
721 if (U_FAILURE(status
)) {
722 log_data_err("Error DecimalFormat ct -> %s (Are you missing data?)\n", u_errorName(status
));
727 unum_format(f
, (int32_t)123456789L, resultBuffer
, 512 , &pos
, &status
);
728 u_uastrcpy(buffer
, "12,34,56,789");
729 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
731 log_err("Fail: Formatting \"#,##,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer
, "12,34,56,789");
733 if (pos
.beginIndex
!= 0 && pos
.endIndex
!= 12) {
734 log_err("Fail: Formatting \"#,##,###\" pattern pos = (%d, %d) expected pos = (0, 12)\n", pos
.beginIndex
, pos
.endIndex
);
736 memset(resultBuffer
,0, sizeof(UChar
)*512);
737 unum_toPattern(f
, FALSE
, resultBuffer
, 512, &status
);
738 u_uastrcpy(buffer
, "#,##,###");
739 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
741 log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer
, "#,##,###");
743 memset(resultBuffer
,0, sizeof(UChar
)*512);
744 u_uastrcpy(buffer
, "#,###");
745 unum_applyPattern(f
, FALSE
, buffer
, -1,NULL
,NULL
);
746 if (U_FAILURE(status
))
748 log_err("Fail: applyPattern call failed\n");
750 unum_setAttribute(f
, UNUM_SECONDARY_GROUPING_SIZE
, 4);
751 unum_format(f
, (int32_t)123456789L, resultBuffer
, 512 , &pos
, &status
);
752 u_uastrcpy(buffer
, "12,3456,789");
753 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
755 log_err("Fail: Formatting \"#,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer
, "12,3456,789");
757 memset(resultBuffer
,0, sizeof(UChar
)*512);
758 unum_toPattern(f
, FALSE
, resultBuffer
, 512, &status
);
759 u_uastrcpy(buffer
, "#,####,###");
760 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
762 log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer
, "#,####,###");
764 memset(resultBuffer
,0, sizeof(UChar
)*512);
765 g
= unum_open(UNUM_DECIMAL
, NULL
,0,"hi_IN",NULL
, &status
);
766 if (U_FAILURE(status
))
768 log_err("Fail: Cannot create UNumberFormat for \"hi_IN\" locale.\n");
771 unum_format(g
, l
, resultBuffer
, 512, &pos
, &status
);
773 /* expect "1,87,65,43,210", but with Hindi digits */
775 if (u_strlen(resultBuffer
) != 14) {
778 for (i
=0; i
<u_strlen(resultBuffer
); ++i
) {
788 /* Later -- fix this to get the actual grouping */
789 /* character from the resource bundle. */
790 isGroup
= (UBool
)(resultBuffer
[i
] == 0x002C);
791 if (isGroup
!= expectGroup
) {
798 log_err("FAIL Expected %s x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got %s\n", "1876543210L", resultBuffer
);
804 static void TestCurrencyKeywords(void)
806 static const char * const currencies
[] = {
807 "ADD", "ADP", "AED", "AFA", "AFN", "AIF", "ALK", "ALL", "ALV", "ALX", "AMD",
808 "ANG", "AOA", "AOK", "AON", "AOR", "AOS", "ARA", "ARM", "ARP", "ARS", "ATS",
809 "AUD", "AUP", "AWG", "AZM", "BAD", "BAM", "BAN", "BBD", "BDT", "BEC", "BEF",
810 "BEL", "BGL", "BGM", "BGN", "BGO", "BGX", "BHD", "BIF", "BMD", "BMP", "BND",
811 "BOB", "BOL", "BOP", "BOV", "BRB", "BRC", "BRE", "BRL", "BRN", "BRR", "BRZ",
812 "BSD", "BSP", "BTN", "BTR", "BUK", "BUR", "BWP", "BYB", "BYL", "BYR", "BZD",
813 "BZH", "CAD", "CDF", "CDG", "CDL", "CFF", "CHF", "CKD", "CLC", "CLE", "CLF",
814 "CLP", "CMF", "CNP", "CNX", "CNY", "COB", "COF", "COP", "CRC", "CSC", "CSK",
815 "CUP", "CUX", "CVE", "CWG", "CYP", "CZK", "DDM", "DEM", "DES", "DJF", "DKK",
816 "DOP", "DZD", "DZF", "DZG", "ECS", "ECV", "EEK", "EGP", "ERN", "ESP", "ETB",
817 "ETD", "EUR", "FIM", "FIN", "FJD", "FJP", "FKP", "FOK", "FRF", "FRG", "GAF",
818 "GBP", "GEK", "GEL", "GHC", "GHO", "GHP", "GHR", "GIP", "GLK", "GMD", "GMP",
819 "GNF", "GNI", "GNS", "GPF", "GQE", "GQF", "GQP", "GRD", "GRN", "GTQ", "GUF",
820 "GWE", "GWM", "GWP", "GYD", "HKD", "HNL", "HRD", "HRK", "HTG", "HUF", "IBP",
821 "IDG", "IDJ", "IDN", "IDR", "IEP", "ILL", "ILP", "ILS", "IMP", "INR", "IQD",
822 "IRR", "ISK", "ITL", "JEP", "JMD", "JMP", "JOD", "JPY", "KES", "KGS", "KHO",
823 "KHR", "KID", "KMF", "KPP", "KPW", "KRH", "KRO", "KRW", "KWD", "KYD", "KZR",
824 "KZT", "LAK", "LBP", "LIF", "LKR", "LNR", "LRD", "LSL", "LTL", "LTT", "LUF",
825 "LVL", "LVR", "LYB", "LYD", "LYP", "MAD", "MAF", "MCF", "MCG", "MDC", "MDL",
826 "MDR", "MGA", "MGF", "MHD", "MKD", "MKN", "MLF", "MMK", "MMX", "MNT", "MOP",
827 "MQF", "MRO", "MTL", "MTP", "MUR", "MVP", "MVR", "MWK", "MWP", "MXN", "MXP",
828 "MXV", "MYR", "MZE", "MZM", "NAD", "NCF", "NGN", "NGP", "NHF", "NIC", "NIG",
829 "NIO", "NLG", "NOK", "NPR", "NZD", "NZP", "OMR", "OMS", "PAB", "PDK", "PDN",
830 "PDR", "PEI", "PEN", "PES", "PGK", "PHP", "PKR", "PLN", "PLX", "PLZ", "PSP",
831 "PTC", "PTE", "PYG", "QAR", "REF", "ROL", "RON", "RUB", "RUR", "RWF", "SAR",
832 "SAS", "SBD", "SCR", "SDD", "SDP", "SEK", "SGD", "SHP", "SIB", "SIT", "SKK",
833 "SLL", "SML", "SOS", "SQS", "SRG", "SSP", "STD", "STE", "SUN", "SUR", "SVC",
834 "SYP", "SZL", "TCC", "TDF", "THB", "TJR", "TJS", "TMM", "TND", "TOP", "TOS",
835 "TPE", "TPP", "TRL", "TTD", "TTO", "TVD", "TWD", "TZS", "UAH", "UAK", "UGS",
836 "UGX", "USD", "USN", "USS", "UYF", "UYP", "UYU", "UZC", "UZS", "VAL", "VDD",
837 "VDN", "VDP", "VEB", "VGD", "VND", "VNN", "VNR", "VNS", "VUV", "WSP", "WST",
838 "XAD", "XAF", "XAM", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XCF", "XDR",
839 "XEF", "XEU", "XFO", "XFU", "XID", "XMF", "XNF", "XOF", "XPF", "XPS", "XSS",
840 "XTR", "YDD", "YEI", "YER", "YUD", "YUF", "YUG", "YUM", "YUN", "YUO", "YUR",
841 "ZAL", "ZAP", "ZAR", "ZMK", "ZMP", "ZRN", "ZRZ", "ZWD"
844 UErrorCode status
= U_ZERO_ERROR
;
845 int32_t i
= 0, j
= 0;
846 int32_t noLocales
= uloc_countAvailable();
850 UChar currBuffer
[256];
853 for(i
= 0; i
< noLocales
; i
++) {
854 strcpy(currLoc
, uloc_getAvailable(i
));
855 for(j
= 0; j
< sizeof(currencies
)/sizeof(currencies
[0]); j
++) {
856 strcpy(locale
, currLoc
);
857 strcat(locale
, "@currency=");
858 strcat(locale
, currencies
[j
]);
859 ucurr_forLocale(locale
, result
, 4, &status
);
860 u_charsToUChars(currencies
[j
], currBuffer
, 3);
862 if(u_strcmp(currBuffer
, result
) != 0) {
863 log_err("Didn't get the right currency for %s\n", locale
);
870 static void TestGetKeywordValuesForLocale(void) {
871 #define PREFERRED_SIZE 12
872 #define MAX_NUMBER_OF_KEYWORDS 4
873 const char *PREFERRED
[PREFERRED_SIZE
][MAX_NUMBER_OF_KEYWORDS
] = {
874 { "root", "USD", "USN", "USS" },
875 { "und", "USD", "USN", "USS" },
876 /* { "und_ZZ", "USD", NULL, NULL }, -- temporaary remove as this locale now has 15 entries */
877 { "en_US", "USD", "USN", "USS" },
878 { "en_029", "USD", "USN", "USS" },
879 { "en_TH", "THB", NULL
, NULL
},
880 { "de", "EUR", NULL
, NULL
},
881 { "de_DE", "EUR", NULL
, NULL
},
882 { "ar", "EGP", NULL
, NULL
},
883 { "ar_PS", "JOD", "ILS", NULL
},
884 { "en@currency=CAD", "USD", "USN", "USS" },
885 { "fr@currency=zzz", "EUR", NULL
, NULL
},
886 { "de_DE@currency=DEM", "EUR", NULL
, NULL
},
888 const int32_t EXPECTED_SIZE
[PREFERRED_SIZE
] = {
889 3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1
891 UErrorCode status
= U_ZERO_ERROR
;
893 UEnumeration
*pref
, *all
;
894 const char *loc
= NULL
;
895 UBool matchPref
, matchAll
;
896 const char *value
= NULL
;
897 int32_t valueLength
= 0;
899 UList
*ALLList
= NULL
;
901 UEnumeration
*ALL
= ucurr_getKeywordValuesForLocale("currency", uloc_getDefault(), FALSE
, &status
);
903 log_err_status(status
, "ERROR getting keyword value for default locale. -> %s\n", u_errorName(status
));
907 for (i
= 0; i
< PREFERRED_SIZE
; i
++) {
910 loc
= PREFERRED
[i
][0];
911 pref
= ucurr_getKeywordValuesForLocale("currency", loc
, TRUE
, &status
);
915 size
= uenum_count(pref
, &status
);
917 if (size
== EXPECTED_SIZE
[i
]) {
919 for (j
= 0; j
< size
; j
++) {
920 if ((value
= uenum_next(pref
, &valueLength
, &status
)) != NULL
&& U_SUCCESS(status
)) {
921 if (uprv_strcmp(value
, PREFERRED
[i
][j
+1]) != 0) {
922 log_err("ERROR: locale %s got keywords #%d %s expected %s\n", loc
, j
, value
, PREFERRED
[i
][j
+1]);
929 log_err("ERROR getting keyword value for locale \"%s\"\n", loc
);
934 log_err("FAIL: size of locale \"%s\" %d does not match expected size %d\n", loc
, size
, EXPECTED_SIZE
[i
]);
938 log_err("FAIL: Preferred values for locale \"%s\" does not match expected.\n", loc
);
943 all
= ucurr_getKeywordValuesForLocale("currency", loc
, FALSE
, &status
);
945 size
= uenum_count(all
, &status
);
947 if (U_SUCCESS(status
) && size
== uenum_count(ALL
, &status
)) {
949 ALLList
= ulist_getListFromEnum(ALL
);
950 for (j
= 0; j
< size
; j
++) {
951 if ((value
= uenum_next(all
, &valueLength
, &status
)) != NULL
&& U_SUCCESS(status
)) {
952 if (!ulist_containsString(ALLList
, value
, uprv_strlen(value
))) {
953 log_err("Locale %s have %s not in ALL\n", loc
, value
);
959 log_err("ERROR getting \"all\" keyword value for locale \"%s\"\n", loc
);
964 log_err("FAIL: All values for locale \"%s\" does not match expected.\n", loc
);
967 if(U_FAILURE(status
)) {
968 log_err("ERROR: %s\n", u_errorName(status
));
969 } else if(size
!=uenum_count(ALL
, &status
)) {
970 log_err("ERROR: got size of %d, wanted %d\n", size
, uenum_count(ALL
, &status
));
982 * Test proper handling of rounding modes.
984 static void TestRounding5350(void)
987 UErrorCode status
= U_ZERO_ERROR
;
988 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
989 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
990 /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
991 nnf
= unum_open(UNUM_DEFAULT
, NULL
,0,"en_US",NULL
, &status
);
993 if(U_FAILURE(status
)){
994 log_data_err("FAIL: failure in the construction of number format: %s (Are you missing data?)\n", myErrorName(status
));
998 unum_setAttribute(nnf
, UNUM_MAX_FRACTION_DIGITS
, 2);
999 roundingTest2(nnf
, -0.125, UNUM_ROUND_CEILING
, "-0.12");
1000 roundingTest2(nnf
, -0.125, UNUM_ROUND_FLOOR
, "-0.13");
1001 roundingTest2(nnf
, -0.125, UNUM_ROUND_DOWN
, "-0.12");
1002 roundingTest2(nnf
, -0.125, UNUM_ROUND_UP
, "-0.13");
1003 roundingTest2(nnf
, 0.125, UNUM_FOUND_HALFEVEN
, "0.12");
1004 roundingTest2(nnf
, 0.135, UNUM_ROUND_HALFDOWN
, "0.13");
1005 roundingTest2(nnf
, 0.125, UNUM_ROUND_HALFUP
, "0.13");
1006 roundingTest2(nnf
, 0.135, UNUM_FOUND_HALFEVEN
, "0.14");
1007 /* The following are exactly represented, and shouldn't round */
1008 roundingTest2(nnf
, 1.00, UNUM_ROUND_UP
, "1");
1009 roundingTest2(nnf
, 24.25, UNUM_ROUND_UP
, "24.25");
1010 roundingTest2(nnf
, 24.25, UNUM_ROUND_CEILING
, "24.25");
1011 roundingTest2(nnf
, -24.25, UNUM_ROUND_UP
, "-24.25");
1013 /* Differences pretty far out there */
1014 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_CEILING
, "1.01");
1015 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_FLOOR
, "1");
1016 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_DOWN
, "1");
1017 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_UP
, "1.01");
1018 roundingTest2(nnf
, 1.0000001, UNUM_FOUND_HALFEVEN
, "1");
1019 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_HALFDOWN
, "1");
1020 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_HALFUP
, "1");
1022 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_CEILING
, "-1");
1023 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_FLOOR
, "-1.01");
1024 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_DOWN
, "-1");
1025 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_UP
, "-1.01");
1026 roundingTest2(nnf
, -1.0000001, UNUM_FOUND_HALFEVEN
, "-1");
1027 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_HALFDOWN
, "-1");
1028 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_HALFUP
, "-1");
1033 /*-------------------------------------*/
1035 static void roundingTest2(UNumberFormat
* nf
, double x
, int32_t roundingMode
, const char* expected
)
1042 status
=U_ZERO_ERROR
;
1043 unum_setAttribute(nf
, UNUM_ROUNDING_MODE
, roundingMode
);
1045 lneed
=unum_formatDouble(nf
, x
, NULL
, lneed
, NULL
, &status
);
1046 if(status
==U_BUFFER_OVERFLOW_ERROR
){
1047 status
=U_ZERO_ERROR
;
1048 out
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
1050 unum_formatDouble(nf
, x
, out
, lneed
+1, &pos
, &status
);
1052 if(U_FAILURE(status
)) {
1053 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
1055 /*Need to use log_verbose here. Problem with the float*/
1056 /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
1057 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(expected
)+1) );
1058 u_uastrcpy(res
, expected
);
1059 if (u_strcmp(out
, res
) != 0)
1060 log_err("FAIL: Expected: \"%s\" Got: \"%s\"\n", expected
, austrdup(out
) );
1067 #endif /* #if !UCONFIG_NO_FORMATTING */