• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * COPYRIGHT:
5  * Copyright (c) 1997-2016, International Business Machines Corporation
6  * and others. All Rights Reserved.
7  ********************************************************************/
8 /*******************************************************************************
9 *
10 * File CNMDPTST.C
11 *
12 *  Madhu Katragadda                       Creation
13 * Modification History:
14 *
15 *   Date        Name        Description
16 *   06/24/99    helena      Integrated Alan's NF enhancements and Java2 bug fixes
17 *******************************************************************************
18 */
19 
20 /* C DEPTH TEST FOR NUMBER FORMAT */
21 
22 #include "unicode/utypes.h"
23 
24 #if !UCONFIG_NO_FORMATTING
25 
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"
31 #include "cintltst.h"
32 #include "cnmdptst.h"
33 #include "cmemory.h"
34 #include "cstring.h"
35 #include "ulist.h"
36 
37 #define CHECK(status,str) if (U_FAILURE(status)) { log_err("FAIL: %s\n", str); return; }
38 
39 void addNumFrDepTest(TestNode** root);
40 static void TestCurrencyPreEuro(void);
41 static void TestCurrencyObject(void);
42 
addNumFrDepTest(TestNode ** root)43 void addNumFrDepTest(TestNode** root)
44 {
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");
58 }
59 
60 /*Test Various format patterns*/
TestPatterns(void)61 static void TestPatterns(void)
62 {
63     int32_t pat_length, i, lneed;
64     UNumberFormat *fmt;
65     UChar upat[5];
66     UChar unewpat[5];
67     UChar unum[5];
68     UChar *unewp=NULL;
69     UChar *str=NULL;
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" };
74 
75     log_verbose("\nTesting different format patterns\n");
76     pat_length = UPRV_LENGTHOF(pat);
77     for (i=0; i < pat_length; ++i)
78     {
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));
84             continue;
85         }
86         lneed=0;
87         lneed=unum_toPattern(fmt, FALSE, NULL, lneed, &status);
88         if(status==U_BUFFER_OVERFLOW_ERROR){
89             status= U_ZERO_ERROR;
90             unewp=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
91             unum_toPattern(fmt, FALSE, unewp, lneed+1, &status);
92         }
93         if(U_FAILURE(status)){
94             log_err("FAIL: Number format extracting the pattern failed for %s\n", pat[i]);
95         }
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) );
99 
100         lneed=0;
101         lneed=unum_format(fmt, 0, NULL, lneed, NULL, &status);
102         if(status==U_BUFFER_OVERFLOW_ERROR){
103             status=U_ZERO_ERROR;
104             str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
105             unum_format(fmt, 0, str, lneed+1,  NULL, &status);
106         }
107         if(U_FAILURE(status)) {
108             log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
109         }
110         u_uastrcpy(unum, num[i]);
111         if (u_strcmp(str, unum) != 0)
112         {
113             log_err("FAIL: Pattern %s should format zero as %s; %s Seen instead\n", pat[i], num[i], austrdup(str) );
114 
115         }
116         free(unewp);
117         free(str);
118         unum_close(fmt);
119     }
120 }
121 
122 /* Test the handling of quotes*/
TestQuotes(void)123 static void TestQuotes(void)
124 {
125     int32_t lneed;
126     UErrorCode status=U_ZERO_ERROR;
127     UChar pat[15];
128     UChar res[15];
129     UChar *str=NULL;
130     UNumberFormat *fmt;
131     char tempBuf[256];
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));
137     }
138     lneed=0;
139     lneed=unum_format(fmt, 123, NULL, lneed, NULL, &status);
140     if(status==U_BUFFER_OVERFLOW_ERROR){
141         status=U_ZERO_ERROR;
142         str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
143         unum_format(fmt, 123, str, lneed+1,  NULL, &status);
144     }
145     if(U_FAILURE(status) || !str) {
146         log_err_status(status, "Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
147         return;
148     }
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");
154 
155     free(str);
156     unum_close(fmt);
157 
158 
159     u_uastrcpy(pat, "");
160     u_uastrcpy(pat, "a''b#");
161 
162 
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");
166     }
167     lneed=0;
168     lneed=unum_format(fmt, 123, NULL, lneed, NULL, &status);
169     if(status==U_BUFFER_OVERFLOW_ERROR){
170         status=U_ZERO_ERROR;
171         str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
172         unum_format(fmt, 123, str, lneed+1,  NULL, &status);
173     }
174     if(U_FAILURE(status)) {
175         log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
176     }
177     log_verbose("Pattern \"%s\" \n", u_austrcpy(tempBuf, pat) );
178     log_verbose("Format 123 -> %s\n", u_austrcpy(tempBuf, str) );
179     u_uastrcpy(res, "");
180     u_uastrcpy(res, "a'b123");
181     if(u_strcmp(str, res) != 0)
182         log_err("FAIL: Expected a'b123\n");
183 
184     free(str);
185     unum_close(fmt);
186 }
187 
188 /* Test exponential pattern*/
TestExponential(void)189 static void TestExponential(void)
190 {
191     int32_t pat_length, val_length, lval_length;
192     int32_t ival, ilval, p, v, lneed;
193     UNumberFormat *fmt;
194     int32_t ppos;
195     UChar *upat;
196     UChar pattern[20];
197     UChar *str=NULL;
198     UChar uvalfor[20], ulvalfor[20];
199     char tempMsgBug[256];
200     double a;
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 };
204 #else
205     static const double val[] = { 0.01234, 123456789, 1.23e300, -3.141592653e-271 };
206 #endif
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 };
209 
210     static const char* valFormat[] =
211     {
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]"
216     };
217     static const char* lvalFormat[] =
218     {
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"
223     };
224     static const double valParse[] =
225     {
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
231 #else
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
238 #endif
239     };
240     static const int32_t lvalParse[] =
241     {
242         0, -1, 1, 123460000,
243             0, -1, 1, 123460000,
244             0, -1, 1, 123456800,
245             0, -1, 1, 123500000
246     };
247 
248 
249     pat_length = UPRV_LENGTHOF(pat);
250     val_length = UPRV_LENGTHOF(val);
251     lval_length = UPRV_LENGTHOF(lval);
252     ival = 0;
253     ilval = 0;
254     for (p=0; p < pat_length; ++p)
255     {
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));
261             continue;
262         }
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)
267         {
268             /*format*/
269             lneed=0;
270             lneed=unum_formatDouble(fmt, val[v], NULL, lneed, NULL, &status);
271             if(status==U_BUFFER_OVERFLOW_ERROR){
272                 status=U_ZERO_ERROR;
273                 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
274                 unum_formatDouble(fmt, val[v], str, lneed+1,  NULL, &status);
275             }
276             if(U_FAILURE(status)) {
277                 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
278             }
279 
280 
281 
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) );
285 
286             /*parsing*/
287             ppos=0;
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);
292             }
293             else
294                 log_err(" FAIL: Partial parse (  %d  chars ) ->  %e\n",  ppos, a);
295 
296             free(str);
297         }
298         for (v=0; v<lval_length; ++v)
299         {
300             /*format*/
301             lneed=0;
302             lneed=unum_formatDouble(fmt, lval[v], NULL, lneed, NULL, &status);
303             if(status==U_BUFFER_OVERFLOW_ERROR){
304                 status=U_ZERO_ERROR;
305                 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
306                 unum_formatDouble(fmt, lval[v], str, lneed+1,  NULL, &status);
307             }
308             if(U_FAILURE(status)) {
309                 log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
310             }
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) );
315 
316             /*parsing*/
317             ppos=0;
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]);
323             }
324             else
325                 log_err(" FAIL: Partial parse (  %d  chars ) ->  %e\n",  ppos, a);
326 
327             free(str);
328 
329         }
330         ival += val_length;
331         ilval += lval_length;
332         unum_close(fmt);
333         free(upat);
334     }
335 }
336 
337 /**
338  * Test the handling of the currency symbol in patterns.
339  */
TestCurrencySign(void)340 static void TestCurrencySign(void)
341 {
342     int32_t lneed;
343     UNumberFormat *fmt;
344     UChar *pattern=NULL;
345     UChar *str=NULL;
346     UChar *pat=NULL;
347     UChar *res=NULL;
348     UErrorCode status = U_ZERO_ERROR;
349     char tempBuf[256];
350 
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));
357     }
358     lneed=0;
359     lneed=unum_formatDouble(fmt, 1234.56, NULL, lneed, NULL, &status);
360     if(status==U_BUFFER_OVERFLOW_ERROR){
361         status=U_ZERO_ERROR;
362         str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
363         unum_formatDouble(fmt, 1234.56, str, lneed+1, NULL, &status);
364     }
365     if(U_FAILURE(status)) {
366         log_err_status(status, "Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
367     }
368     lneed=0;
369     lneed=unum_toPattern(fmt, FALSE, NULL, lneed, &status);
370     if(status==U_BUFFER_OVERFLOW_ERROR){
371         status=U_ZERO_ERROR;
372         pat=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
373         unum_formatDouble(fmt, FALSE, pat, lneed+1, NULL, &status);
374     }
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");
381     } else {
382         log_err_status(status, "Error formatting -> %s\n", u_errorName(status));
383     }
384     free(str);
385     free(res);
386     free(pat);
387 
388     lneed=0;
389     lneed=unum_formatDouble(fmt, -1234.56, NULL, lneed, NULL, &status);
390     if(status==U_BUFFER_OVERFLOW_ERROR){
391         status=U_ZERO_ERROR;
392         str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
393         unum_formatDouble(fmt, -1234.56, str, lneed+1, NULL, &status);
394     }
395     if(U_FAILURE(status)) {
396         log_err_status(status, "Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
397     }
398     if(str) {
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");
402         free(str);
403         free(res);
404     }
405 
406     unum_close(fmt);
407     free(pattern);
408 }
409 
410 /**
411  * Test localized currency patterns.
412  */
TestCurrency(void)413 static void TestCurrency(void)
414 {
415     UNumberFormat *currencyFmt;
416     UChar *str;
417     int32_t lneed, i;
418     UFieldPosition pos;
419     UChar res[100];
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");
424     for(i=0; i < 3; i++)
425     {
426         str=NULL;
427         currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,locale[i],NULL, &status);
428 
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));
432         } else {
433             lneed=0;
434             lneed= unum_formatDouble(currencyFmt, 1.50, NULL, lneed, NULL, &status);
435             if(status==U_BUFFER_OVERFLOW_ERROR){
436                 status=U_ZERO_ERROR;
437                 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
438                 pos.field = 0;
439                 unum_formatDouble(currencyFmt, 1.50, str, lneed+1, &pos, &status);
440             }
441 
442             if(U_FAILURE(status)) {
443                 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
444             } else {
445                 u_unescape(result[i], res, (int32_t)strlen(result[i])+1);
446 
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]);
449                 }
450             }
451         }
452 
453         unum_close(currencyFmt);
454         free(str);
455     }
456 }
457 /**
458  * Test localized currency patterns for PREEURO variants.
459  */
TestCurrencyPreEuro(void)460 static void TestCurrencyPreEuro(void)
461 {
462     UNumberFormat *currencyFmt;
463     UChar *str=NULL, *res=NULL;
464     int32_t lneed, i;
465     UFieldPosition pos;
466     UErrorCode status = U_ZERO_ERROR;
467 
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",
472         "nl_NL_PREEURO",
473     };
474 
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",
479         "NLG\\u00A01,50"
480     };
481 
482     log_verbose("\nTesting the number format with different currency patterns\n");
483     for(i=0; i < 19; i++)
484     {
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));
489             continue;
490         }
491         currencyFmt = unum_open(UNUM_CURRENCY, NULL,0,curID,NULL, &status);
492 
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));
496         } else {
497             lneed=0;
498             lneed= unum_formatDouble(currencyFmt, 1.50, NULL, lneed, NULL, &status);
499 
500             if(status==U_BUFFER_OVERFLOW_ERROR){
501                 status=U_ZERO_ERROR;
502                 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
503                 pos.field = 0;
504                 unum_formatDouble(currencyFmt, 1.50, str, lneed+1, &pos, &status);
505             }
506 
507             if(U_FAILURE(status)) {
508                 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
509             } else {
510                 res=(UChar*)malloc(sizeof(UChar) * (strlen(result[i])+1) );
511                 u_unescape(result[i],res,(int32_t)(strlen(result[i])+1));
512 
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]);
515                 }
516             }
517         }
518 
519         unum_close(currencyFmt);
520         free(str);
521         free(res);
522     }
523 }
524 
525 /**
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.
529  */
TestCurrencyObject(void)530 static void TestCurrencyObject(void)
531 {
532     UNumberFormat *currencyFmt;
533     UChar *str=NULL, *res=NULL;
534     int32_t lneed, i;
535     UFieldPosition pos;
536     UErrorCode status = U_ZERO_ERROR;
537 
538     const char* locale[]={
539         "fr_FR",
540         "fr_FR",
541     };
542 
543     const char* currency[]={
544         "",
545         "JPY",
546     };
547 
548     const char* result[]={
549         "1\\u00A0234,56\\u00A0\\u20AC",
550         "1\\u00A0235\\u00A0JPY",
551     };
552 
553     log_verbose("\nTesting the number format with different currency codes\n");
554     for(i=0; i < 2; i++)
555     {
556         char cStr[20]={0};
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));
562         } else {
563             if (*currency[i]) {
564                 u_uastrcpy(isoCode, currency[i]);
565                 unum_setTextAttribute(currencyFmt, UNUM_CURRENCY_CODE,
566                     isoCode, u_strlen(isoCode), &status);
567 
568                 if(U_FAILURE(status)) {
569                     log_err("FAIL: can't set currency code %s\n", myErrorName(status) );
570                 }
571             }
572 
573             unum_getTextAttribute(currencyFmt, UNUM_CURRENCY_CODE,
574                 isoCode, sizeof(isoCode), &status);
575 
576             if(U_FAILURE(status)) {
577                 log_err("FAIL: can't get currency code %s\n", myErrorName(status) );
578             }
579 
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);
584             }
585 
586             lneed=0;
587             lneed= unum_formatDouble(currencyFmt, 1234.56, NULL, lneed, NULL, &status);
588             if(status==U_BUFFER_OVERFLOW_ERROR){
589                 status=U_ZERO_ERROR;
590                 str=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
591                 pos.field = 0;
592                 unum_formatDouble(currencyFmt, 1234.56, str, lneed+1, &pos, &status);
593             }
594             if(U_FAILURE(status)) {
595                 log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
596             } else {
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]);
601                 }
602             }
603         }
604 
605         unum_close(currencyFmt);
606         free(str);
607         free(res);
608     }
609 }
610 
611 /**
612  * Test proper rounding by the format method.
613  */
TestRounding487(void)614 static void TestRounding487(void)
615 {
616     UNumberFormat *nnf;
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);
622 
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));
625     } else {
626         roundingTest(nnf, 0.00159999, 4, "0.0016");
627         roundingTest(nnf, 0.00995, 4, "0.01");
628 
629         roundingTest(nnf, 12.3995, 3, "12.4");
630 
631         roundingTest(nnf, 12.4999, 0, "12");
632         roundingTest(nnf, - 19.5, 0, "-20");
633     }
634 
635     unum_close(nnf);
636 }
637 
638 /*-------------------------------------*/
639 
roundingTest(UNumberFormat * nf,double x,int32_t maxFractionDigits,const char * expected)640 static void roundingTest(UNumberFormat* nf, double x, int32_t maxFractionDigits, const char* expected)
641 {
642     UChar *out = NULL;
643     UChar *res;
644     UFieldPosition pos;
645     UErrorCode status;
646     int32_t lneed;
647     status=U_ZERO_ERROR;
648     unum_setAttribute(nf, UNUM_MAX_FRACTION_DIGITS, maxFractionDigits);
649     lneed=0;
650     lneed=unum_formatDouble(nf, x, NULL, lneed, NULL, &status);
651     if(status==U_BUFFER_OVERFLOW_ERROR){
652         status=U_ZERO_ERROR;
653         out=(UChar*)malloc(sizeof(UChar) * (lneed+1) );
654         pos.field=0;
655         unum_formatDouble(nf, x, out, lneed+1, &pos, &status);
656     }
657     if(U_FAILURE(status)) {
658         log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
659     }
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) );
666     free(res);
667     if(out != NULL) {
668         free(out);
669     }
670 }
671 
672 /*
673  * Testing unum_getDoubleAttribute and  unum_setDoubleAttribute()
674  */
TestDoubleAttribute(void)675 static void TestDoubleAttribute(void)
676 {
677     double mydata[] = { 1.11, 22.22, 333.33, 4444.44, 55555.55, 666666.66, 7777777.77, 88888888.88, 999999999.99};
678     double dvalue;
679     int i;
680     UErrorCode status=U_ZERO_ERROR;
681     UNumberFormatAttribute attr;
682     UNumberFormatStyle style= UNUM_DEFAULT;
683     UNumberFormat *def;
684 
685     log_verbose("\nTesting get and set DoubleAttributes\n");
686     def=unum_open(style, NULL,0,NULL,NULL, &status);
687 
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));
690     } else {
691         attr=UNUM_ROUNDING_INCREMENT;
692         dvalue=unum_getDoubleAttribute(def, attr);
693         for (i = 0; i<9 ; i++)
694         {
695             dvalue = mydata[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");
699             else
700                 log_verbose("Pass: setting and getting double attributes for UNUM_ROUNDING_INCREMENT works fine\n");
701         }
702     }
703 
704     unum_close(def);
705 }
706 
707 /**
708  * Test the functioning of the secondary grouping value.
709  */
TestSecondaryGrouping(void)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);
714     UFieldPosition pos;
715     UChar resultBuffer[512];
716     int32_t l = 1876543210L;
717     UBool ok = TRUE;
718     UChar buffer[512];
719     int32_t i;
720     UBool expectGroup = FALSE, isGroup = FALSE;
721 
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));
726         return;
727     }
728 
729     pos.field = 0;
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))
733     {
734         log_err("Fail: Formatting \"#,##,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer, "12,34,56,789");
735     }
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);
738     }
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))
743     {
744         log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer, "#,##,###");
745     }
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))
750     {
751         log_err("Fail: applyPattern call failed\n");
752     }
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))
757     {
758         log_err("Fail: Formatting \"#,###\" pattern with 123456789 got %s, expected %s\n", resultBuffer, "12,3456,789");
759     }
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))
764     {
765         log_err("Fail: toPattern() got %s, expected %s\n", resultBuffer, "#,####,###");
766     }
767     memset(resultBuffer,0, sizeof(UChar)*512);
768     g = unum_open(UNUM_DECIMAL, NULL,0,"hi_IN",NULL, &status);
769     if (U_FAILURE(status))
770     {
771         log_err("Fail: Cannot create UNumberFormat for \"hi_IN\" locale.\n");
772     }
773 
774     unum_format(g, l, resultBuffer, 512, &pos, &status);
775     unum_close(g);
776     /* expect "1,87,65,43,210", but with Hindi digits */
777     /*         01234567890123                         */
778     if (u_strlen(resultBuffer) != 14) {
779         ok = FALSE;
780     } else {
781         for (i=0; i<u_strlen(resultBuffer); ++i) {
782             expectGroup = FALSE;
783             switch (i) {
784             case 1:
785             case 4:
786             case 7:
787             case 10:
788                 expectGroup = TRUE;
789                 break;
790             }
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) {
795                 ok = FALSE;
796                 break;
797             }
798         }
799     }
800     if (!ok) {
801         log_err("FAIL  Expected %s x hi_IN -> \"1,87,65,43,210\" (with Hindi digits), got %s\n", "1876543210L", resultBuffer);
802     }
803     unum_close(f);
804     unum_close(us);
805 }
806 
TestCurrencyKeywords(void)807 static void TestCurrencyKeywords(void)
808 {
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"
845     };
846 
847     UErrorCode status = U_ZERO_ERROR;
848     int32_t i = 0, j = 0;
849     int32_t noLocales = uloc_countAvailable();
850     char locale[256];
851     char currLoc[256];
852     UChar result[4];
853     UChar currBuffer[256];
854 
855 
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);
864             currBuffer[3] = 0;
865             if(u_strcmp(currBuffer, result) != 0) {
866                 log_err("Didn't get the right currency for %s\n", locale);
867             }
868         }
869 
870     }
871 }
872 
TestGetKeywordValuesForLocale(void)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 },
893     };
894     const int32_t EXPECTED_SIZE[PREFERRED_SIZE] = {
895             2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1
896     };
897     /* ucurr_forLocale results for same locales; "" if no result expected */
898     const char *FORLOCALE[PREFERRED_SIZE] = {
899             "",    "",    "USD", "",
900             "THB", "",    "EUR", "",
901             "ILS", "CAD", "ZZZ", "DEM",
902             "THB", "USD", "CAD"
903     };
904     UErrorCode status = U_ZERO_ERROR;
905     int32_t i, j, size;
906     UEnumeration *pref, *all;
907     const char *loc = NULL;
908     UBool matchPref, matchAll;
909     const char *value = NULL;
910     int32_t valueLength = 0;
911 
912     UList *ALLList = NULL;
913 
914     UEnumeration *ALL = ucurr_getKeywordValuesForLocale("currency", uloc_getDefault(), FALSE, &status);
915     if (ALL == NULL) {
916         log_err_status(status, "ERROR getting keyword value for default locale. -> %s\n", u_errorName(status));
917         return;
918     }
919 
920     for (i = 0; i < PREFERRED_SIZE; i++) {
921         UChar getCurrU[4];
922         int32_t getCurrLen;
923 
924         status = U_ZERO_ERROR;
925         pref = NULL;
926         all = NULL;
927         loc = PREFERRED[i][0];
928         pref = ucurr_getKeywordValuesForLocale("currency", loc, TRUE, &status);
929         matchPref = FALSE;
930         matchAll = FALSE;
931 
932         size = uenum_count(pref, &status);
933 
934         if (size == EXPECTED_SIZE[i]) {
935             matchPref = TRUE;
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]);
940 
941                         matchPref = FALSE;
942                         break;
943                     }
944                 } else {
945                     matchPref = FALSE;
946                     log_err("ERROR getting keyword value for locale \"%s\"\n", loc);
947                     break;
948                 }
949             }
950         } else {
951             log_err("FAIL: size of locale \"%s\" %d does not match expected size %d\n", loc, size, EXPECTED_SIZE[i]);
952         }
953 
954         if (!matchPref) {
955             log_err("FAIL: Preferred values for locale \"%s\" does not match expected.\n", loc);
956             break;
957         }
958         uenum_close(pref);
959 
960         all = ucurr_getKeywordValuesForLocale("currency", loc, FALSE, &status);
961 
962         size = uenum_count(all, &status);
963 
964         if (U_SUCCESS(status) && size == uenum_count(ALL, &status)) {
965             matchAll = TRUE;
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);
971                         matchAll = FALSE;
972                         break;
973                     }
974                 } else {
975                     matchAll = FALSE;
976                     log_err("ERROR getting \"all\" keyword value for locale \"%s\"\n", loc);
977                     break;
978                 }
979             }
980            if (!matchAll) {
981             log_err("FAIL: All values for locale \"%s\" does not match expected.\n", loc);
982            }
983         } else {
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));
988             }
989         }
990 
991         uenum_close(all);
992 
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));
998             }
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);
1002             }
1003         } else {
1004             char getCurrB[4];
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);
1008             }
1009         }
1010     }
1011 
1012     uenum_close(ALL);
1013 
1014 }
1015 
1016 /**
1017  * Test proper handling of rounding modes.
1018  */
TestRounding5350(void)1019 static void TestRounding5350(void)
1020 {
1021     UNumberFormat *nnf;
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);
1027 
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));
1030         return;
1031     }
1032 
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");
1047 
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");
1056 
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");
1064 
1065     unum_close(nnf);
1066 }
1067 
1068 /*-------------------------------------*/
1069 
roundingTest2(UNumberFormat * nf,double x,int32_t roundingMode,const char * expected)1070 static void roundingTest2(UNumberFormat* nf, double x, int32_t roundingMode, const char* expected)
1071 {
1072     UChar *out = NULL;
1073     UChar *res;
1074     UFieldPosition pos;
1075     UErrorCode status;
1076     int32_t lneed;
1077     status=U_ZERO_ERROR;
1078     unum_setAttribute(nf, UNUM_ROUNDING_MODE, roundingMode);
1079     lneed=0;
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) );
1084         pos.field=0;
1085         unum_formatDouble(nf, x, out, lneed+1, &pos, &status);
1086     }
1087     if(U_FAILURE(status)) {
1088         log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status) );
1089     }
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) );
1096     free(res);
1097     if(out != NULL) {
1098         free(out);
1099     }
1100 }
1101 
1102 #endif /* #if !UCONFIG_NO_FORMATTING */
1103