1 /********************************************************************
3 * Copyright (c) 1997-2016, 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"
28 #include "unicode/putil.h"
35 #define CHECK(status,str) if (U_FAILURE(status)) { log_err("FAIL: %s\n", str); return; }
37 void addNumFrDepTest(TestNode
** root
);
38 static void TestCurrencyPreEuro(void);
39 static void TestCurrencyObject(void);
41 void addNumFrDepTest(TestNode
** root
)
43 addTest(root
, &TestPatterns
, "tsformat/cnmdptst/TestPatterns");
44 addTest(root
, &TestQuotes
, "tsformat/cnmdptst/TestQuotes");
45 addTest(root
, &TestExponential
, "tsformat/cnmdptst/TestExponential");
46 addTest(root
, &TestCurrencySign
, "tsformat/cnmdptst/TestCurrencySign");
47 addTest(root
, &TestCurrency
, "tsformat/cnmdptst/TestCurrency");
48 addTest(root
, &TestCurrencyPreEuro
, "tsformat/cnmdptst/TestCurrencyPreEuro");
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", "#" };
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 transmute 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 costruction 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 costruction 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
));
261 lneed
= u_strlen(upat
) + 1;
262 unum_toPattern(fmt
, FALSE
, pattern
, lneed
, &status
);
263 log_verbose("Pattern \" %s \" -toPattern-> \" %s \" \n", upat
, u_austrcpy(tempMsgBug
, pattern
) );
264 for (v
=0; v
<val_length
; ++v
)
268 lneed
=unum_formatDouble(fmt
, val
[v
], NULL
, lneed
, NULL
, &status
);
269 if(status
==U_BUFFER_OVERFLOW_ERROR
){
271 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
272 unum_formatDouble(fmt
, val
[v
], str
, lneed
+1, NULL
, &status
);
274 if(U_FAILURE(status
)) {
275 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
280 u_uastrcpy(uvalfor
, valFormat
[v
+ival
]);
281 if(u_strcmp(str
, uvalfor
) != 0)
282 log_verbose("FAIL: Expected %s ( %s )\n", valFormat
[v
+ival
], u_austrcpy(tempMsgBug
, uvalfor
) );
286 a
=unum_parseDouble(fmt
, str
, u_strlen(str
), &ppos
, &status
);
287 if (ppos
== u_strlen(str
)) {
288 if (a
!= valParse
[v
+ival
])
289 log_err("FAIL: Expected: %e, Got: %g\n", valParse
[v
+ival
], a
);
292 log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos
, a
);
296 for (v
=0; v
<lval_length
; ++v
)
300 lneed
=unum_formatDouble(fmt
, lval
[v
], NULL
, lneed
, NULL
, &status
);
301 if(status
==U_BUFFER_OVERFLOW_ERROR
){
303 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
304 unum_formatDouble(fmt
, lval
[v
], str
, lneed
+1, NULL
, &status
);
306 if(U_FAILURE(status
)) {
307 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
309 /*printf(" Format %e -> %s\n", lval[v], austrdup(str) );*/
310 u_uastrcpy(ulvalfor
, lvalFormat
[v
+ilval
]);
311 if(u_strcmp(str
, ulvalfor
) != 0)
312 log_err("FAIL: Expected %s ( %s )\n", valFormat
[v
+ilval
], austrdup(ulvalfor
) );
316 a
=unum_parseDouble(fmt
, str
, u_strlen(str
), &ppos
, &status
);
317 if (ppos
== u_strlen(str
)) {
318 /*printf(" Parse -> %e\n", a);*/
319 if (a
!= lvalParse
[v
+ilval
])
320 log_err("FAIL: Expected : %e\n", valParse
[v
+ival
]);
323 log_err(" FAIL: Partial parse ( %d chars ) -> %e\n", ppos
, a
);
329 ilval
+= lval_length
;
336 * Test the handling of the currency symbol in patterns.
338 static void TestCurrencySign(void)
346 UErrorCode status
= U_ZERO_ERROR
;
349 pattern
=(UChar
*)malloc(sizeof(UChar
) * (strlen("*#,##0.00;-*#,##0.00") + 1) );
350 u_uastrcpy(pattern
, "*#,##0.00;-*#,##0.00");
351 pattern
[0]=pattern
[11]=0xa4; /* insert latin-1 currency symbol */
352 fmt
= unum_open(UNUM_IGNORE
,pattern
, u_strlen(pattern
), "en_US",NULL
, &status
);
353 if(U_FAILURE(status
)){
354 log_err_status(status
, "Error in number format construction with pattern \"\\xA4#,##0.00;-\\xA4#,##0.00\\\" -> %s\n", u_errorName(status
));
357 lneed
=unum_formatDouble(fmt
, 1234.56, NULL
, lneed
, NULL
, &status
);
358 if(status
==U_BUFFER_OVERFLOW_ERROR
){
360 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
361 unum_formatDouble(fmt
, 1234.56, str
, lneed
+1, NULL
, &status
);
363 if(U_FAILURE(status
)) {
364 log_err_status(status
, "Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
367 lneed
=unum_toPattern(fmt
, FALSE
, NULL
, lneed
, &status
);
368 if(status
==U_BUFFER_OVERFLOW_ERROR
){
370 pat
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
371 unum_formatDouble(fmt
, FALSE
, pat
, lneed
+1, NULL
, &status
);
373 log_verbose("Pattern \" %s \" \n", u_austrcpy(tempBuf
, pat
));
374 log_verbose("Format 1234.56 -> %s\n", u_austrcpy(tempBuf
, str
) );
375 if(U_SUCCESS(status
) && str
) {
376 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen("$1,234.56")+1) );
377 u_uastrcpy(res
, "$1,234.56");
378 if (u_strcmp(str
, res
) !=0) log_data_err("FAIL: Expected $1,234.56\n");
380 log_err_status(status
, "Error formatting -> %s\n", u_errorName(status
));
387 lneed
=unum_formatDouble(fmt
, -1234.56, NULL
, lneed
, NULL
, &status
);
388 if(status
==U_BUFFER_OVERFLOW_ERROR
){
390 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
391 unum_formatDouble(fmt
, -1234.56, str
, lneed
+1, NULL
, &status
);
393 if(U_FAILURE(status
)) {
394 log_err_status(status
, "Error in formatting using unum_format(.....): %s\n", myErrorName(status
) );
397 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen("-$1,234.56")+1) );
398 u_uastrcpy(res
, "-$1,234.56");
399 if (u_strcmp(str
, res
) != 0) log_data_err("FAIL: Expected -$1,234.56\n");
409 * Test localized currency patterns.
411 static void TestCurrency(void)
413 UNumberFormat
*currencyFmt
;
418 UErrorCode status
= U_ZERO_ERROR
;
419 const char* locale
[]={"fr_CA", "de_DE_PREEURO", "fr_FR_PREEURO"};
420 const char* result
[]={"1,50\\u00a0$", "1,50\\u00a0DM", "1,50\\u00a0F"};
421 log_verbose("\nTesting the number format with different currency patterns\n");
425 currencyFmt
= unum_open(UNUM_CURRENCY
, NULL
,0,locale
[i
],NULL
, &status
);
427 if(U_FAILURE(status
)){
428 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
429 myErrorName(status
));
432 lneed
= unum_formatDouble(currencyFmt
, 1.50, NULL
, lneed
, NULL
, &status
);
433 if(status
==U_BUFFER_OVERFLOW_ERROR
){
435 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
437 unum_formatDouble(currencyFmt
, 1.50, str
, lneed
+1, &pos
, &status
);
440 if(U_FAILURE(status
)) {
441 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
443 u_unescape(result
[i
], res
, (int32_t)strlen(result
[i
])+1);
445 if (u_strcmp(str
, res
) != 0){
446 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result
[i
], aescstrdup(str
, -1), locale
[i
]);
451 unum_close(currencyFmt
);
456 * Test localized currency patterns for PREEURO variants.
458 static void TestCurrencyPreEuro(void)
460 UNumberFormat
*currencyFmt
;
461 UChar
*str
=NULL
, *res
=NULL
;
464 UErrorCode status
= U_ZERO_ERROR
;
466 const char* locale
[]={
467 "ca_ES_PREEURO", "de_LU_PREEURO", "en_IE_PREEURO", "fi_FI_PREEURO", "fr_LU_PREEURO", "it_IT_PREEURO",
468 "pt_PT_PREEURO", "de_AT_PREEURO", "el_GR_PREEURO", "es_ES_PREEURO", "fr_BE_PREEURO", "ga_IE_PREEURO",
469 "nl_BE_PREEURO", "de_DE_PREEURO", "en_BE_PREEURO", "eu_ES_PREEURO", "fr_FR_PREEURO", "gl_ES_PREEURO",
473 const char* result
[]={
474 "\\u20A7\\u00A02", "2\\u00A0F", "IEP1.50", "1,50\\u00A0mk", "2\\u00A0F", "ITL\\u00A02",
475 "1$50\\u00A0\\u200B", "\\u00F6S\\u00A01,50", "1,50\\u00A0\\u0394\\u03C1\\u03C7", "2\\u00A0\\u20A7", "1,50\\u00A0FB", "IEP1.50",
476 "1,50\\u00A0BEF", "1,50\\u00A0DM", "1,50\\u00A0BEF", "\\u20A7\\u00A02", "1,50\\u00A0F", "2\\u00A0\\u20A7",
480 log_verbose("\nTesting the number format with different currency patterns\n");
481 for(i
=0; i
< 19; i
++)
483 char curID
[256] = {0};
484 uloc_canonicalize(locale
[i
], curID
, 256, &status
);
485 if(U_FAILURE(status
)){
486 log_data_err("Could not canonicalize %s. Error: %s (Are you missing data?)\n", locale
[i
], u_errorName(status
));
489 currencyFmt
= unum_open(UNUM_CURRENCY
, NULL
,0,curID
,NULL
, &status
);
491 if(U_FAILURE(status
)){
492 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
493 myErrorName(status
));
496 lneed
= unum_formatDouble(currencyFmt
, 1.50, NULL
, lneed
, NULL
, &status
);
498 if(status
==U_BUFFER_OVERFLOW_ERROR
){
500 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
502 unum_formatDouble(currencyFmt
, 1.50, str
, lneed
+1, &pos
, &status
);
505 if(U_FAILURE(status
)) {
506 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
508 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(result
[i
])+1) );
509 u_unescape(result
[i
],res
,(int32_t)(strlen(result
[i
])+1));
511 if (u_strcmp(str
, res
) != 0){
512 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result
[i
],aescstrdup(str
, -1),locale
[i
]);
517 unum_close(currencyFmt
);
524 * Test currency "object" (we use this name to match the other C++
525 * test name and the Jave name). Actually, test ISO currency code
526 * support in the C API.
528 static void TestCurrencyObject(void)
530 UNumberFormat
*currencyFmt
;
531 UChar
*str
=NULL
, *res
=NULL
;
534 UErrorCode status
= U_ZERO_ERROR
;
536 const char* locale
[]={
541 const char* currency
[]={
546 const char* result
[]={
547 "1\\u00A0234,56\\u00A0\\u20AC",
548 "1\\u00A0235\\u00A0JPY",
551 log_verbose("\nTesting the number format with different currency codes\n");
555 UChar isoCode
[16]={0};
556 currencyFmt
= unum_open(UNUM_CURRENCY
, NULL
,0,locale
[i
],NULL
, &status
);
557 if(U_FAILURE(status
)){
558 log_data_err("Error in the construction of number format with style currency: %s (Are you missing data?)\n",
559 myErrorName(status
));
562 u_uastrcpy(isoCode
, currency
[i
]);
563 unum_setTextAttribute(currencyFmt
, UNUM_CURRENCY_CODE
,
564 isoCode
, u_strlen(isoCode
), &status
);
566 if(U_FAILURE(status
)) {
567 log_err("FAIL: can't set currency code %s\n", myErrorName(status
) );
571 unum_getTextAttribute(currencyFmt
, UNUM_CURRENCY_CODE
,
572 isoCode
, sizeof(isoCode
), &status
);
574 if(U_FAILURE(status
)) {
575 log_err("FAIL: can't get currency code %s\n", myErrorName(status
) );
578 u_UCharsToChars(isoCode
,cStr
,u_strlen(isoCode
));
579 log_verbose("ISO code %s\n", cStr
);
580 if (*currency
[i
] && uprv_strcmp(cStr
, currency
[i
])) {
581 log_err("FAIL: currency should be %s, but is %s\n", currency
[i
], cStr
);
585 lneed
= unum_formatDouble(currencyFmt
, 1234.56, NULL
, lneed
, NULL
, &status
);
586 if(status
==U_BUFFER_OVERFLOW_ERROR
){
588 str
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
590 unum_formatDouble(currencyFmt
, 1234.56, str
, lneed
+1, &pos
, &status
);
592 if(U_FAILURE(status
)) {
593 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
595 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(result
[i
])+1) );
596 u_unescape(result
[i
],res
, (int32_t)(strlen(result
[i
])+1));
597 if (u_strcmp(str
, res
) != 0){
598 log_err("FAIL: Expected %s Got: %s for locale: %s\n", result
[i
],aescstrdup(str
, -1),locale
[i
]);
603 unum_close(currencyFmt
);
610 * Test proper rounding by the format method.
612 static void TestRounding487(void)
615 UErrorCode status
= U_ZERO_ERROR
;
616 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
617 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
618 /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
619 nnf
= unum_open(UNUM_DEFAULT
, NULL
,0,"en_US",NULL
, &status
);
621 if(U_FAILURE(status
)){
622 log_data_err("FAIL: failure in the construction of number format: %s (Are you missing data?)\n", myErrorName(status
));
624 roundingTest(nnf
, 0.00159999, 4, "0.0016");
625 roundingTest(nnf
, 0.00995, 4, "0.01");
627 roundingTest(nnf
, 12.3995, 3, "12.4");
629 roundingTest(nnf
, 12.4999, 0, "12");
630 roundingTest(nnf
, - 19.5, 0, "-20");
636 /*-------------------------------------*/
638 static void roundingTest(UNumberFormat
* nf
, double x
, int32_t maxFractionDigits
, const char* expected
)
646 unum_setAttribute(nf
, UNUM_MAX_FRACTION_DIGITS
, maxFractionDigits
);
648 lneed
=unum_formatDouble(nf
, x
, NULL
, lneed
, NULL
, &status
);
649 if(status
==U_BUFFER_OVERFLOW_ERROR
){
651 out
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
653 unum_formatDouble(nf
, x
, out
, lneed
+1, &pos
, &status
);
655 if(U_FAILURE(status
)) {
656 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
658 /*Need to use log_verbose here. Problem with the float*/
659 /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
660 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(expected
)+1) );
661 u_uastrcpy(res
, expected
);
662 if (u_strcmp(out
, res
) != 0)
663 log_err("FAIL: Expected: %s or %s\n", expected
, austrdup(res
) );
671 * Testing unum_getDoubleAttribute and unum_setDoubleAttribute()
673 static void TestDoubleAttribute(void)
675 double mydata
[] = { 1.11, 22.22, 333.33, 4444.44, 55555.55, 666666.66, 7777777.77, 88888888.88, 999999999.99};
678 UErrorCode status
=U_ZERO_ERROR
;
679 UNumberFormatAttribute attr
;
680 UNumberFormatStyle style
= UNUM_DEFAULT
;
683 log_verbose("\nTesting get and set DoubleAttributes\n");
684 def
=unum_open(style
, NULL
,0,NULL
,NULL
, &status
);
686 if (U_FAILURE(status
)) {
687 log_data_err("Fail: error creating a default number formatter -> %s (Are you missing data?)\n", u_errorName(status
));
689 attr
=UNUM_ROUNDING_INCREMENT
;
690 dvalue
=unum_getDoubleAttribute(def
, attr
);
691 for (i
= 0; i
<9 ; i
++)
694 unum_setDoubleAttribute(def
, attr
, dvalue
);
695 if(unum_getDoubleAttribute(def
,attr
)!=mydata
[i
])
696 log_err("Fail: error in setting and getting double attributes for UNUM_ROUNDING_INCREMENT\n");
698 log_verbose("Pass: setting and getting double attributes for UNUM_ROUNDING_INCREMENT works fine\n");
706 * Test the functioning of the secondary grouping value.
708 static void TestSecondaryGrouping(void) {
709 UErrorCode status
= U_ZERO_ERROR
;
710 UNumberFormat
*f
= NULL
, *g
= NULL
;
711 UNumberFormat
*us
= unum_open(UNUM_DECIMAL
,NULL
,0, "en_US", NULL
,&status
);
713 UChar resultBuffer
[512];
714 int32_t l
= 1876543210L;
718 UBool expectGroup
= FALSE
, isGroup
= FALSE
;
720 u_uastrcpy(buffer
, "#,##,###");
721 f
= unum_open(UNUM_IGNORE
,buffer
, -1, "en_US",NULL
, &status
);
722 if (U_FAILURE(status
)) {
723 log_data_err("Error DecimalFormat ct -> %s (Are you missing data?)\n", u_errorName(status
));
728 unum_format(f
, (int32_t)123456789L, resultBuffer
, 512 , &pos
, &status
);
729 u_uastrcpy(buffer
, "12,34,56,789");
730 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
732 log_err("Fail: Formatting \"#,##,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer
, "12,34,56,789");
734 if (pos
.beginIndex
!= 0 && pos
.endIndex
!= 12) {
735 log_err("Fail: Formatting \"#,##,###\" pattern pos = (%d, %d) expected pos = (0, 12)\n", pos
.beginIndex
, pos
.endIndex
);
737 memset(resultBuffer
,0, sizeof(UChar
)*512);
738 unum_toPattern(f
, FALSE
, resultBuffer
, 512, &status
);
739 u_uastrcpy(buffer
, "#,##,###");
740 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
742 log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer
, "#,##,###");
744 memset(resultBuffer
,0, sizeof(UChar
)*512);
745 u_uastrcpy(buffer
, "#,###");
746 unum_applyPattern(f
, FALSE
, buffer
, -1,NULL
,NULL
);
747 if (U_FAILURE(status
))
749 log_err("Fail: applyPattern call failed\n");
751 unum_setAttribute(f
, UNUM_SECONDARY_GROUPING_SIZE
, 4);
752 unum_format(f
, (int32_t)123456789L, resultBuffer
, 512 , &pos
, &status
);
753 u_uastrcpy(buffer
, "12,3456,789");
754 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
756 log_err("Fail: Formatting \"#,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer
, "12,3456,789");
758 memset(resultBuffer
,0, sizeof(UChar
)*512);
759 unum_toPattern(f
, FALSE
, resultBuffer
, 512, &status
);
760 u_uastrcpy(buffer
, "#,####,###");
761 if ((u_strcmp(resultBuffer
, buffer
) != 0) || U_FAILURE(status
))
763 log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer
, "#,####,###");
765 memset(resultBuffer
,0, sizeof(UChar
)*512);
766 g
= unum_open(UNUM_DECIMAL
, NULL
,0,"hi_IN",NULL
, &status
);
767 if (U_FAILURE(status
))
769 log_err("Fail: Cannot create UNumberFormat for \"hi_IN\" locale.\n");
772 unum_format(g
, l
, resultBuffer
, 512, &pos
, &status
);
774 /* expect "1,87,65,43,210", but with Hindi digits */
776 if (u_strlen(resultBuffer
) != 14) {
779 for (i
=0; i
<u_strlen(resultBuffer
); ++i
) {
789 /* Later -- fix this to get the actual grouping */
790 /* character from the resource bundle. */
791 isGroup
= (UBool
)(resultBuffer
[i
] == 0x002C);
792 if (isGroup
!= expectGroup
) {
799 log_err("FAIL Expected %s x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got %s\n", "1876543210L", resultBuffer
);
805 static void TestCurrencyKeywords(void)
807 static const char * const currencies
[] = {
808 "ADD", "ADP", "AED", "AFA", "AFN", "AIF", "ALK", "ALL", "ALV", "ALX", "AMD",
809 "ANG", "AOA", "AOK", "AON", "AOR", "AOS", "ARA", "ARM", "ARP", "ARS", "ATS",
810 "AUD", "AUP", "AWG", "AZM", "BAD", "BAM", "BAN", "BBD", "BDT", "BEC", "BEF",
811 "BEL", "BGL", "BGM", "BGN", "BGO", "BGX", "BHD", "BIF", "BMD", "BMP", "BND",
812 "BOB", "BOL", "BOP", "BOV", "BRB", "BRC", "BRE", "BRL", "BRN", "BRR", "BRZ",
813 "BSD", "BSP", "BTN", "BTR", "BUK", "BUR", "BWP", "BYB", "BYL", "BYR", "BZD",
814 "BZH", "CAD", "CDF", "CDG", "CDL", "CFF", "CHF", "CKD", "CLC", "CLE", "CLF",
815 "CLP", "CMF", "CNP", "CNX", "CNY", "COB", "COF", "COP", "CRC", "CSC", "CSK",
816 "CUP", "CUX", "CVE", "CWG", "CYP", "CZK", "DDM", "DEM", "DES", "DJF", "DKK",
817 "DOP", "DZD", "DZF", "DZG", "ECS", "ECV", "EEK", "EGP", "ERN", "ESP", "ETB",
818 "ETD", "EUR", "FIM", "FIN", "FJD", "FJP", "FKP", "FOK", "FRF", "FRG", "GAF",
819 "GBP", "GEK", "GEL", "GHC", "GHO", "GHP", "GHR", "GIP", "GLK", "GMD", "GMP",
820 "GNF", "GNI", "GNS", "GPF", "GQE", "GQF", "GQP", "GRD", "GRN", "GTQ", "GUF",
821 "GWE", "GWM", "GWP", "GYD", "HKD", "HNL", "HRD", "HRK", "HTG", "HUF", "IBP",
822 "IDG", "IDJ", "IDN", "IDR", "IEP", "ILL", "ILP", "ILS", "IMP", "INR", "IQD",
823 "IRR", "ISK", "ITL", "JEP", "JMD", "JMP", "JOD", "JPY", "KES", "KGS", "KHO",
824 "KHR", "KID", "KMF", "KPP", "KPW", "KRH", "KRO", "KRW", "KWD", "KYD", "KZR",
825 "KZT", "LAK", "LBP", "LIF", "LKR", "LNR", "LRD", "LSL", "LTL", "LTT", "LUF",
826 "LVL", "LVR", "LYB", "LYD", "LYP", "MAD", "MAF", "MCF", "MCG", "MDC", "MDL",
827 "MDR", "MGA", "MGF", "MHD", "MKD", "MKN", "MLF", "MMK", "MMX", "MNT", "MOP",
828 "MQF", "MRO", "MTL", "MTP", "MUR", "MVP", "MVR", "MWK", "MWP", "MXN", "MXP",
829 "MXV", "MYR", "MZE", "MZM", "NAD", "NCF", "NGN", "NGP", "NHF", "NIC", "NIG",
830 "NIO", "NLG", "NOK", "NPR", "NZD", "NZP", "OMR", "OMS", "PAB", "PDK", "PDN",
831 "PDR", "PEI", "PEN", "PES", "PGK", "PHP", "PKR", "PLN", "PLX", "PLZ", "PSP",
832 "PTC", "PTE", "PYG", "QAR", "REF", "ROL", "RON", "RUB", "RUR", "RWF", "SAR",
833 "SAS", "SBD", "SCR", "SDD", "SDP", "SEK", "SGD", "SHP", "SIB", "SIT", "SKK",
834 "SLL", "SML", "SOS", "SQS", "SRG", "SSP", "STD", "STE", "SUN", "SUR", "SVC",
835 "SYP", "SZL", "TCC", "TDF", "THB", "TJR", "TJS", "TMM", "TND", "TOP", "TOS",
836 "TPE", "TPP", "TRL", "TTD", "TTO", "TVD", "TWD", "TZS", "UAH", "UAK", "UGS",
837 "UGX", "USD", "USN", "USS", "UYF", "UYP", "UYU", "UZC", "UZS", "VAL", "VDD",
838 "VDN", "VDP", "VEB", "VGD", "VND", "VNN", "VNR", "VNS", "VUV", "WSP", "WST",
839 "XAD", "XAF", "XAM", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XCF", "XDR",
840 "XEF", "XEU", "XFO", "XFU", "XID", "XMF", "XNF", "XOF", "XPF", "XPS", "XSS",
841 "XTR", "YDD", "YEI", "YER", "YUD", "YUF", "YUG", "YUM", "YUN", "YUO", "YUR",
842 "ZAL", "ZAP", "ZAR", "ZMK", "ZMP", "ZRN", "ZRZ", "ZWD"
845 UErrorCode status
= U_ZERO_ERROR
;
846 int32_t i
= 0, j
= 0;
847 int32_t noLocales
= uloc_countAvailable();
851 UChar currBuffer
[256];
854 for(i
= 0; i
< noLocales
; i
++) {
855 strcpy(currLoc
, uloc_getAvailable(i
));
856 for(j
= 0; j
< UPRV_LENGTHOF(currencies
); j
++) {
857 strcpy(locale
, currLoc
);
858 strcat(locale
, "@currency=");
859 strcat(locale
, currencies
[j
]);
860 ucurr_forLocale(locale
, result
, 4, &status
);
861 u_charsToUChars(currencies
[j
], currBuffer
, 3);
863 if(u_strcmp(currBuffer
, result
) != 0) {
864 log_err("Didn't get the right currency for %s\n", locale
);
871 static void TestGetKeywordValuesForLocale(void) {
872 #define PREFERRED_SIZE 15
873 #define MAX_NUMBER_OF_KEYWORDS 4
874 const char *PREFERRED
[PREFERRED_SIZE
][MAX_NUMBER_OF_KEYWORDS
] = {
875 { "root", "USD", "USN", NULL
},
876 { "und", "USD", "USN", NULL
},
877 /* { "und_ZZ", "USD", NULL, NULL }, -- temporarily remove as this locale now has 15 entries */
878 { "en_US", "USD", "USN", NULL
},
879 { "en_029", "USD", "USN", NULL
},
880 { "en_TH", "THB", NULL
, NULL
},
881 { "de", "EUR", NULL
, NULL
},
882 { "de_DE", "EUR", NULL
, NULL
},
883 { "ar", "EGP", NULL
, NULL
},
884 { "ar_PS", "ILS", "JOD", NULL
},
885 { "en@currency=CAD", "USD", "USN", NULL
},
886 { "fr@currency=zzz", "EUR", NULL
, NULL
},
887 { "de_DE@currency=DEM", "EUR", NULL
, NULL
},
888 { "en_US@rg=THZZZZ", "THB", NULL
, NULL
},
889 { "de@rg=USZZZZ", "USD", "USN", NULL
},
890 { "en_US@currency=CAD;rg=THZZZZ", "THB", NULL
, NULL
},
892 const int32_t EXPECTED_SIZE
[PREFERRED_SIZE
] = {
893 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1
895 /* ucurr_forLocale results for same locales; "" if no result expected */
896 const char *FORLOCALE
[PREFERRED_SIZE
] = {
898 "THB", "", "EUR", "",
899 "ILS", "CAD", "ZZZ", "DEM",
902 UErrorCode status
= U_ZERO_ERROR
;
904 UEnumeration
*pref
, *all
;
905 const char *loc
= NULL
;
906 UBool matchPref
, matchAll
;
907 const char *value
= NULL
;
908 int32_t valueLength
= 0;
910 UList
*ALLList
= NULL
;
912 UEnumeration
*ALL
= ucurr_getKeywordValuesForLocale("currency", uloc_getDefault(), FALSE
, &status
);
914 log_err_status(status
, "ERROR getting keyword value for default locale. -> %s\n", u_errorName(status
));
918 for (i
= 0; i
< PREFERRED_SIZE
; i
++) {
922 status
= U_ZERO_ERROR
;
925 loc
= PREFERRED
[i
][0];
926 pref
= ucurr_getKeywordValuesForLocale("currency", loc
, TRUE
, &status
);
930 size
= uenum_count(pref
, &status
);
932 if (size
== EXPECTED_SIZE
[i
]) {
934 for (j
= 0; j
< size
; j
++) {
935 if ((value
= uenum_next(pref
, &valueLength
, &status
)) != NULL
&& U_SUCCESS(status
)) {
936 if (uprv_strcmp(value
, PREFERRED
[i
][j
+1]) != 0) {
937 log_err("ERROR: locale %s got keywords #%d %s expected %s\n", loc
, j
, value
, PREFERRED
[i
][j
+1]);
944 log_err("ERROR getting keyword value for locale \"%s\"\n", loc
);
949 log_err("FAIL: size of locale \"%s\" %d does not match expected size %d\n", loc
, size
, EXPECTED_SIZE
[i
]);
953 log_err("FAIL: Preferred values for locale \"%s\" does not match expected.\n", loc
);
958 all
= ucurr_getKeywordValuesForLocale("currency", loc
, FALSE
, &status
);
960 size
= uenum_count(all
, &status
);
962 if (U_SUCCESS(status
) && size
== uenum_count(ALL
, &status
)) {
964 ALLList
= ulist_getListFromEnum(ALL
);
965 for (j
= 0; j
< size
; j
++) {
966 if ((value
= uenum_next(all
, &valueLength
, &status
)) != NULL
&& U_SUCCESS(status
)) {
967 if (!ulist_containsString(ALLList
, value
, uprv_strlen(value
))) {
968 log_err("Locale %s have %s not in ALL\n", loc
, value
);
974 log_err("ERROR getting \"all\" keyword value for locale \"%s\"\n", loc
);
979 log_err("FAIL: All values for locale \"%s\" does not match expected.\n", loc
);
982 if(U_FAILURE(status
)) {
983 log_err("ERROR: %s\n", u_errorName(status
));
984 } else if(size
!=uenum_count(ALL
, &status
)) {
985 log_err("ERROR: got size of %d, wanted %d\n", size
, uenum_count(ALL
, &status
));
991 status
= U_ZERO_ERROR
;
992 getCurrLen
= ucurr_forLocale(loc
, getCurrU
, 4, &status
);
993 if(U_FAILURE(status
)) {
994 if (FORLOCALE
[i
][0] != 0) {
995 log_err("ERROR: ucurr_forLocale %s, status %s\n", loc
, u_errorName(status
));
997 } else if (getCurrLen
!= 3) {
998 if (FORLOCALE
[i
][0] != 0 || getCurrLen
!= -1) {
999 log_err("ERROR: ucurr_forLocale %s, returned len %d\n", loc
, getCurrLen
);
1003 u_UCharsToChars(getCurrU
, getCurrB
, 4);
1004 if ( uprv_strncmp(getCurrB
, FORLOCALE
[i
], 4) != 0 ) {
1005 log_err("ERROR: ucurr_forLocale %s, expected %s, got %s\n", loc
, FORLOCALE
[i
], getCurrB
);
1015 * Test proper handling of rounding modes.
1017 static void TestRounding5350(void)
1020 UErrorCode status
= U_ZERO_ERROR
;
1021 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
1022 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
1023 /* nnf = unum_open(UNUM_DEFAULT, NULL, &status); */
1024 nnf
= unum_open(UNUM_DEFAULT
, NULL
,0,"en_US",NULL
, &status
);
1026 if(U_FAILURE(status
)){
1027 log_data_err("FAIL: failure in the construction of number format: %s (Are you missing data?)\n", myErrorName(status
));
1031 unum_setAttribute(nnf
, UNUM_MAX_FRACTION_DIGITS
, 2);
1032 roundingTest2(nnf
, -0.125, UNUM_ROUND_CEILING
, "-0.12");
1033 roundingTest2(nnf
, -0.125, UNUM_ROUND_FLOOR
, "-0.13");
1034 roundingTest2(nnf
, -0.125, UNUM_ROUND_DOWN
, "-0.12");
1035 roundingTest2(nnf
, -0.125, UNUM_ROUND_UP
, "-0.13");
1036 roundingTest2(nnf
, 0.125, UNUM_FOUND_HALFEVEN
, "0.12");
1037 roundingTest2(nnf
, 0.135, UNUM_ROUND_HALFDOWN
, "0.13");
1038 roundingTest2(nnf
, 0.125, UNUM_ROUND_HALFUP
, "0.13");
1039 roundingTest2(nnf
, 0.135, UNUM_FOUND_HALFEVEN
, "0.14");
1040 /* The following are exactly represented, and shouldn't round */
1041 roundingTest2(nnf
, 1.00, UNUM_ROUND_UP
, "1");
1042 roundingTest2(nnf
, 24.25, UNUM_ROUND_UP
, "24.25");
1043 roundingTest2(nnf
, 24.25, UNUM_ROUND_CEILING
, "24.25");
1044 roundingTest2(nnf
, -24.25, UNUM_ROUND_UP
, "-24.25");
1046 /* Differences pretty far out there */
1047 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_CEILING
, "1.01");
1048 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_FLOOR
, "1");
1049 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_DOWN
, "1");
1050 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_UP
, "1.01");
1051 roundingTest2(nnf
, 1.0000001, UNUM_FOUND_HALFEVEN
, "1");
1052 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_HALFDOWN
, "1");
1053 roundingTest2(nnf
, 1.0000001, UNUM_ROUND_HALFUP
, "1");
1055 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_CEILING
, "-1");
1056 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_FLOOR
, "-1.01");
1057 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_DOWN
, "-1");
1058 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_UP
, "-1.01");
1059 roundingTest2(nnf
, -1.0000001, UNUM_FOUND_HALFEVEN
, "-1");
1060 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_HALFDOWN
, "-1");
1061 roundingTest2(nnf
, -1.0000001, UNUM_ROUND_HALFUP
, "-1");
1066 /*-------------------------------------*/
1068 static void roundingTest2(UNumberFormat
* nf
, double x
, int32_t roundingMode
, const char* expected
)
1075 status
=U_ZERO_ERROR
;
1076 unum_setAttribute(nf
, UNUM_ROUNDING_MODE
, roundingMode
);
1078 lneed
=unum_formatDouble(nf
, x
, NULL
, lneed
, NULL
, &status
);
1079 if(status
==U_BUFFER_OVERFLOW_ERROR
){
1080 status
=U_ZERO_ERROR
;
1081 out
=(UChar
*)malloc(sizeof(UChar
) * (lneed
+1) );
1083 unum_formatDouble(nf
, x
, out
, lneed
+1, &pos
, &status
);
1085 if(U_FAILURE(status
)) {
1086 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status
) );
1088 /*Need to use log_verbose here. Problem with the float*/
1089 /*printf("%f format with %d fraction digits to %s\n", x, maxFractionDigits, austrdup(out) );*/
1090 res
=(UChar
*)malloc(sizeof(UChar
) * (strlen(expected
)+1) );
1091 u_uastrcpy(res
, expected
);
1092 if (u_strcmp(out
, res
) != 0)
1093 log_err("FAIL: Expected: \"%s\" Got: \"%s\"\n", expected
, austrdup(out
) );
1100 #endif /* #if !UCONFIG_NO_FORMATTING */