1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2012, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6/********************************************************************************
7*
8* File CNUMTST.C
9*
10*     Madhu Katragadda              Creation
11*
12* Modification History:
13*
14*   Date        Name        Description
15*   06/24/99    helena      Integrated Alan's NF enhancements and Java2 bug fixes
16*   07/15/99    helena      Ported to HPUX 10/11 CC.
17*********************************************************************************
18*/
19
20/* C API TEST FOR NUMBER FORMAT */
21
22#include "unicode/utypes.h"
23
24#if !UCONFIG_NO_FORMATTING
25
26#include "unicode/uloc.h"
27#include "unicode/umisc.h"
28#include "unicode/unum.h"
29#include "unicode/ustring.h"
30
31#include "cintltst.h"
32#include "cnumtst.h"
33#include "cmemory.h"
34#include "putilimp.h"
35#include <stdio.h>
36
37#define LENGTH(arr) (sizeof(arr)/sizeof(arr[0]))
38
39static const char *tagAssert(const char *f, int32_t l, const char *msg) {
40    static char _fileline[1000];
41    sprintf(_fileline, "%s:%d: ASSERT_TRUE(%s)", f, l, msg);
42    return _fileline;
43}
44
45#define ASSERT_TRUE(x)   assertTrue(tagAssert(__FILE__, __LINE__, #x), (x))
46
47void addNumForTest(TestNode** root);
48static void TestTextAttributeCrash(void);
49static void TestNBSPInPattern(void);
50static void TestInt64Parse(void);
51static void TestParseCurrency(void);
52static void TestMaxInt(void);
53static void TestNoExponent(void);
54
55#define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x)
56
57void addNumForTest(TestNode** root)
58{
59    TESTCASE(TestNumberFormat);
60    TESTCASE(TestSpelloutNumberParse);
61    TESTCASE(TestSignificantDigits);
62    TESTCASE(TestSigDigRounding);
63    TESTCASE(TestNumberFormatPadding);
64    TESTCASE(TestInt64Format);
65    TESTCASE(TestNonExistentCurrency);
66    TESTCASE(TestCurrencyRegression);
67    TESTCASE(TestTextAttributeCrash);
68    TESTCASE(TestRBNFFormat);
69    TESTCASE(TestNBSPInPattern);
70    TESTCASE(TestInt64Parse);
71    TESTCASE(TestParseZero);
72    TESTCASE(TestParseCurrency);
73    TESTCASE(TestCloneWithRBNF);
74    TESTCASE(TestMaxInt);
75    TESTCASE(TestNoExponent);
76}
77
78/* test Parse int 64 */
79
80static void TestInt64Parse()
81{
82
83    UErrorCode st = U_ZERO_ERROR;
84    UErrorCode* status = &st;
85
86    const char* st1 = "009223372036854775808";
87    const int size = 21;
88    UChar text[21];
89
90
91    UNumberFormat* nf;
92
93    int64_t a;
94
95    u_charsToUChars(st1, text, size);
96    nf = unum_open(UNUM_DEFAULT, NULL, -1, NULL, NULL, status);
97
98    if(U_FAILURE(*status))
99    {
100        log_data_err("Error in unum_open() %s \n", myErrorName(*status));
101        return;
102    }
103
104    log_verbose("About to test unum_parseInt64() with out of range number\n");
105
106    a = unum_parseInt64(nf, text, size, 0, status);
107
108
109    if(!U_FAILURE(*status))
110    {
111        log_err("Error in unum_parseInt64(): %s \n", myErrorName(*status));
112    }
113    else
114    {
115        log_verbose("unum_parseInt64() successful\n");
116    }
117
118    unum_close(nf);
119    return;
120}
121
122/* test Number Format API */
123static void TestNumberFormat()
124{
125    UChar *result=NULL;
126    UChar temp1[512];
127    UChar temp2[512];
128
129    UChar temp[5];
130
131    UChar prefix[5];
132    UChar suffix[5];
133    UChar symbol[20];
134    int32_t resultlength;
135    int32_t resultlengthneeded;
136    int32_t parsepos;
137    double d1 = -1.0;
138    int32_t l1;
139    double d = -10456.37;
140    double a = 1234.56, a1 = 1235.0;
141    int32_t l = 100000000;
142    UFieldPosition pos1;
143    UFieldPosition pos2;
144    int32_t numlocales;
145    int32_t i;
146
147    UNumberFormatAttribute attr;
148    UNumberFormatSymbol symType = UNUM_DECIMAL_SEPARATOR_SYMBOL;
149    int32_t newvalue;
150    UErrorCode status=U_ZERO_ERROR;
151    UNumberFormatStyle style= UNUM_DEFAULT;
152    UNumberFormat *pattern;
153    UNumberFormat *def, *fr, *cur_def, *cur_fr, *per_def, *per_fr,
154                  *cur_frpattern, *myclone, *spellout_def;
155
156    /* Testing unum_open() with various Numberformat styles and locales*/
157    status = U_ZERO_ERROR;
158    log_verbose("Testing  unum_open() with default style and locale\n");
159    def=unum_open(style, NULL,0,NULL, NULL,&status);
160
161    /* Might as well pack it in now if we can't even get a default NumberFormat... */
162    if(U_FAILURE(status))
163    {
164        log_data_err("Error in creating default NumberFormat using unum_open(): %s (Are you missing data?)\n", myErrorName(status));
165        return;
166    }
167
168    log_verbose("\nTesting unum_open() with french locale and default style(decimal)\n");
169    fr=unum_open(style,NULL,0, "fr_FR",NULL, &status);
170    if(U_FAILURE(status))
171        log_err("Error: could not create NumberFormat (french): %s\n", myErrorName(status));
172
173    log_verbose("\nTesting unum_open(currency,NULL,status)\n");
174    style=UNUM_CURRENCY;
175    /* Can't hardcode the result to assume the default locale is "en_US". */
176    cur_def=unum_open(style, NULL,0,"en_US", NULL, &status);
177    if(U_FAILURE(status))
178        log_err("Error: could not create NumberFormat using \n unum_open(currency, NULL, &status) %s\n",
179                        myErrorName(status) );
180
181    log_verbose("\nTesting unum_open(currency, frenchlocale, status)\n");
182    cur_fr=unum_open(style,NULL,0, "fr_FR", NULL, &status);
183    if(U_FAILURE(status))
184        log_err("Error: could not create NumberFormat using unum_open(currency, french, &status): %s\n",
185                myErrorName(status));
186
187    log_verbose("\nTesting unum_open(percent, NULL, status)\n");
188    style=UNUM_PERCENT;
189    per_def=unum_open(style,NULL,0, NULL,NULL, &status);
190    if(U_FAILURE(status))
191        log_err("Error: could not create NumberFormat using unum_open(percent, NULL, &status): %s\n", myErrorName(status));
192
193    log_verbose("\nTesting unum_open(percent,frenchlocale, status)\n");
194    per_fr=unum_open(style, NULL,0,"fr_FR", NULL,&status);
195    if(U_FAILURE(status))
196        log_err("Error: could not create NumberFormat using unum_open(percent, french, &status): %s\n", myErrorName(status));
197
198    log_verbose("\nTesting unum_open(spellout, NULL, status)");
199    style=UNUM_SPELLOUT;
200    spellout_def=unum_open(style, NULL, 0, "en_US", NULL, &status);
201    if(U_FAILURE(status))
202        log_err("Error: could not create NumberFormat using unum_open(spellout, NULL, &status): %s\n", myErrorName(status));
203
204    /* Testing unum_clone(..) */
205    log_verbose("\nTesting unum_clone(fmt, status)");
206    status = U_ZERO_ERROR;
207    myclone = unum_clone(def,&status);
208    if(U_FAILURE(status))
209        log_err("Error: could not clone unum_clone(def, &status): %s\n", myErrorName(status));
210    else
211    {
212        log_verbose("unum_clone() successful\n");
213    }
214
215    /*Testing unum_getAvailable() and unum_countAvailable()*/
216    log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
217    numlocales=unum_countAvailable();
218    if(numlocales < 0)
219        log_err("error in countAvailable");
220    else{
221        log_verbose("unum_countAvialable() successful\n");
222        log_verbose("The no: of locales where number formattting is applicable is %d\n", numlocales);
223    }
224    for(i=0;i<numlocales;i++)
225    {
226        log_verbose("%s\n", unum_getAvailable(i));
227        if (unum_getAvailable(i) == 0)
228            log_err("No locale for which number formatting patterns are applicable\n");
229        else
230            log_verbose("A locale %s for which number formatting patterns are applicable\n",unum_getAvailable(i));
231    }
232
233
234    /*Testing unum_format() and unum_formatdouble()*/
235    u_uastrcpy(temp1, "$100,000,000.00");
236
237    log_verbose("\nTesting unum_format() \n");
238    resultlength=0;
239    pos1.field = UNUM_INTEGER_FIELD;
240    resultlengthneeded=unum_format(cur_def, l, NULL, resultlength, &pos1, &status);
241    if(status==U_BUFFER_OVERFLOW_ERROR)
242    {
243        status=U_ZERO_ERROR;
244        resultlength=resultlengthneeded+1;
245        result=(UChar*)malloc(sizeof(UChar) * resultlength);
246/*        for (i = 0; i < 100000; i++) */
247        {
248            unum_format(cur_def, l, result, resultlength, &pos1, &status);
249        }
250    }
251
252    if(U_FAILURE(status))
253    {
254        log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status) );
255    }
256    if(u_strcmp(result, temp1)==0)
257        log_verbose("Pass: Number formatting using unum_format() successful\n");
258    else
259        log_err("Fail: Error in number Formatting using unum_format()\n");
260    if(pos1.beginIndex == 1 && pos1.endIndex == 12)
261        log_verbose("Pass: Complete number formatting using unum_format() successful\n");
262    else
263        log_err("Fail: Error in complete number Formatting using unum_format()\nGot: b=%d end=%d\nExpected: b=1 end=12\n",
264                pos1.beginIndex, pos1.endIndex);
265
266    free(result);
267    result = 0;
268
269    log_verbose("\nTesting unum_formatDouble()\n");
270    u_uastrcpy(temp1, "($10,456.37)");
271    resultlength=0;
272    pos2.field = UNUM_FRACTION_FIELD;
273    resultlengthneeded=unum_formatDouble(cur_def, d, NULL, resultlength, &pos2, &status);
274    if(status==U_BUFFER_OVERFLOW_ERROR)
275    {
276        status=U_ZERO_ERROR;
277        resultlength=resultlengthneeded+1;
278        result=(UChar*)malloc(sizeof(UChar) * resultlength);
279/*        for (i = 0; i < 100000; i++) */
280        {
281            unum_formatDouble(cur_def, d, result, resultlength, &pos2, &status);
282        }
283    }
284    if(U_FAILURE(status))
285    {
286        log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
287    }
288    if(result && u_strcmp(result, temp1)==0)
289        log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n");
290    else
291        log_err("FAIL: Error in number formatting using unum_formatDouble()\n");
292    if(pos2.beginIndex == 9 && pos2.endIndex == 11)
293        log_verbose("Pass: Complete number formatting using unum_format() successful\n");
294    else
295        log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=9 end=11",
296                pos1.beginIndex, pos1.endIndex);
297
298
299    /* Testing unum_parse() and unum_parseDouble() */
300    log_verbose("\nTesting unum_parseDouble()\n");
301/*    for (i = 0; i < 100000; i++)*/
302    parsepos=0;
303    if (result != NULL) {
304      d1=unum_parseDouble(cur_def, result, u_strlen(result), &parsepos, &status);
305    } else {
306      log_err("result is NULL\n");
307    }
308    if(U_FAILURE(status)) {
309      log_err("parse of '%s' failed. Parsepos=%d. The error is  : %s\n", aescstrdup(result,u_strlen(result)),parsepos, myErrorName(status));
310    }
311
312    if(d1!=d)
313        log_err("Fail: Error in parsing\n");
314    else
315        log_verbose("Pass: parsing successful\n");
316    if (result)
317        free(result);
318    result = 0;
319
320    status = U_ZERO_ERROR;
321    /* Testing unum_formatDoubleCurrency / unum_parseDoubleCurrency */
322    log_verbose("\nTesting unum_formatDoubleCurrency\n");
323    u_uastrcpy(temp1, "Y1,235");
324    temp1[0] = 0xA5; /* Yen sign */
325    u_uastrcpy(temp, "JPY");
326    resultlength=0;
327    pos2.field = UNUM_INTEGER_FIELD;
328    resultlengthneeded=unum_formatDoubleCurrency(cur_def, a, temp, NULL, resultlength, &pos2, &status);
329    if (status==U_BUFFER_OVERFLOW_ERROR) {
330        status=U_ZERO_ERROR;
331        resultlength=resultlengthneeded+1;
332        result=(UChar*)malloc(sizeof(UChar) * resultlength);
333        unum_formatDoubleCurrency(cur_def, a, temp, result, resultlength, &pos2, &status);
334    }
335    if (U_FAILURE(status)) {
336        log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
337    }
338    if (result && u_strcmp(result, temp1)==0) {
339        log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n");
340    } else {
341        log_err("FAIL: Error in number formatting using unum_formatDouble()\n");
342    }
343    if (pos2.beginIndex == 1 && pos2.endIndex == 6) {
344        log_verbose("Pass: Complete number formatting using unum_format() successful\n");
345    } else {
346        log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=1 end=6\n",
347                pos1.beginIndex, pos1.endIndex);
348    }
349
350    log_verbose("\nTesting unum_parseDoubleCurrency\n");
351    parsepos=0;
352    if (result == NULL) {
353        log_err("result is NULL\n");
354    }
355    else {
356        d1=unum_parseDoubleCurrency(cur_def, result, u_strlen(result), &parsepos, temp2, &status);
357        if (U_FAILURE(status)) {
358          log_err("parseDoubleCurrency '%s' failed. The error is  : %s\n", aescstrdup(result, u_strlen(result)), myErrorName(status));
359        }
360        /* Note: a==1234.56, but on parse expect a1=1235.0 */
361        if (d1!=a1) {
362            log_err("Fail: Error in parsing currency, got %f, expected %f\n", d1, a1);
363        } else {
364            log_verbose("Pass: parsed currency ammount successfully\n");
365        }
366        if (u_strcmp(temp2, temp)==0) {
367            log_verbose("Pass: parsed correct currency\n");
368        } else {
369            log_err("Fail: parsed incorrect currency\n");
370        }
371    }
372    status = U_ZERO_ERROR; /* reset */
373
374    free(result);
375    result = 0;
376
377
378/* performance testing */
379    u_uastrcpy(temp1, "$462.12345");
380    resultlength=u_strlen(temp1);
381/*    for (i = 0; i < 100000; i++) */
382    {
383        parsepos=0;
384        d1=unum_parseDouble(cur_def, temp1, resultlength, &parsepos, &status);
385    }
386    if(U_FAILURE(status))
387    {
388        log_err("parseDouble('%s') failed. The error is  : %s\n", aescstrdup(temp1, resultlength), myErrorName(status));
389    }
390
391    /*
392     * Note: "for strict standard conformance all operations and constants are now supposed to be
393              evaluated in precision of long double".  So,  we assign a1 before comparing to a double. Bug #7932.
394     */
395    a1 = 462.12345;
396
397    if(d1!=a1)
398        log_err("Fail: Error in parsing\n");
399    else
400        log_verbose("Pass: parsing successful\n");
401
402free(result);
403
404    u_uastrcpy(temp1, "($10,456.3E1])");
405    parsepos=0;
406    d1=unum_parseDouble(cur_def, temp1, u_strlen(temp1), &parsepos, &status);
407    if(U_SUCCESS(status))
408    {
409        log_err("Error in unum_parseDouble(..., %s, ...): %s\n", temp1, myErrorName(status));
410    }
411
412
413    log_verbose("\nTesting unum_format()\n");
414    status=U_ZERO_ERROR;
415    resultlength=0;
416    parsepos=0;
417    resultlengthneeded=unum_format(per_fr, l, NULL, resultlength, &pos1, &status);
418    if(status==U_BUFFER_OVERFLOW_ERROR)
419    {
420        status=U_ZERO_ERROR;
421        resultlength=resultlengthneeded+1;
422        result=(UChar*)malloc(sizeof(UChar) * resultlength);
423/*        for (i = 0; i < 100000; i++)*/
424        {
425            unum_format(per_fr, l, result, resultlength, &pos1, &status);
426        }
427    }
428    if(U_FAILURE(status))
429    {
430        log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status));
431    }
432
433
434    log_verbose("\nTesting unum_parse()\n");
435/*    for (i = 0; i < 100000; i++) */
436    {
437        parsepos=0;
438        l1=unum_parse(per_fr, result, u_strlen(result), &parsepos, &status);
439    }
440    if(U_FAILURE(status))
441    {
442        log_err("parse failed. The error is  : %s\n", myErrorName(status));
443    }
444
445    if(l1!=l)
446        log_err("Fail: Error in parsing\n");
447    else
448        log_verbose("Pass: parsing successful\n");
449
450free(result);
451
452    /* create a number format using unum_openPattern(....)*/
453    log_verbose("\nTesting unum_openPattern()\n");
454    u_uastrcpy(temp1, "#,##0.0#;(#,##0.0#)");
455    pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), NULL, NULL,&status);
456    if(U_FAILURE(status))
457    {
458        log_err("error in unum_openPattern(): %s\n", myErrorName(status) );;
459    }
460    else
461        log_verbose("Pass: unum_openPattern() works fine\n");
462
463    /*test for unum_toPattern()*/
464    log_verbose("\nTesting unum_toPattern()\n");
465    resultlength=0;
466    resultlengthneeded=unum_toPattern(pattern, FALSE, NULL, resultlength, &status);
467    if(status==U_BUFFER_OVERFLOW_ERROR)
468    {
469        status=U_ZERO_ERROR;
470        resultlength=resultlengthneeded+1;
471        result=(UChar*)malloc(sizeof(UChar) * resultlength);
472        unum_toPattern(pattern, FALSE, result, resultlength, &status);
473    }
474    if(U_FAILURE(status))
475    {
476        log_err("error in extracting the pattern from UNumberFormat: %s\n", myErrorName(status));
477    }
478    else
479    {
480        if(u_strcmp(result, temp1)!=0)
481            log_err("FAIL: Error in extracting the pattern using unum_toPattern()\n");
482        else
483            log_verbose("Pass: extracted the pattern correctly using unum_toPattern()\n");
484free(result);
485    }
486
487    /*Testing unum_getSymbols() and unum_setSymbols()*/
488    log_verbose("\nTesting unum_getSymbols and unum_setSymbols()\n");
489    /*when we try to change the symbols of french to default we need to apply the pattern as well to fetch correct results */
490    resultlength=0;
491    resultlengthneeded=unum_toPattern(cur_def, FALSE, NULL, resultlength, &status);
492    if(status==U_BUFFER_OVERFLOW_ERROR)
493    {
494        status=U_ZERO_ERROR;
495        resultlength=resultlengthneeded+1;
496        result=(UChar*)malloc(sizeof(UChar) * resultlength);
497        unum_toPattern(cur_def, FALSE, result, resultlength, &status);
498    }
499    if(U_FAILURE(status))
500    {
501        log_err("error in extracting the pattern from UNumberFormat: %s\n", myErrorName(status));
502    }
503
504    status=U_ZERO_ERROR;
505    cur_frpattern=unum_open(UNUM_IGNORE,result, u_strlen(result), "fr_FR",NULL, &status);
506    if(U_FAILURE(status))
507    {
508        log_err("error in unum_openPattern(): %s\n", myErrorName(status));
509    }
510
511free(result);
512
513    /*getting the symbols of cur_def */
514    /*set the symbols of cur_frpattern to cur_def */
515    for (symType = UNUM_DECIMAL_SEPARATOR_SYMBOL; symType < UNUM_FORMAT_SYMBOL_COUNT; symType++) {
516        status=U_ZERO_ERROR;
517        unum_getSymbol(cur_def, symType, temp1, sizeof(temp1), &status);
518        unum_setSymbol(cur_frpattern, symType, temp1, -1, &status);
519        if(U_FAILURE(status))
520        {
521            log_err("Error in get/set symbols: %s\n", myErrorName(status));
522        }
523    }
524
525    /*format to check the result */
526    resultlength=0;
527    resultlengthneeded=unum_format(cur_def, l, NULL, resultlength, &pos1, &status);
528    if(status==U_BUFFER_OVERFLOW_ERROR)
529    {
530        status=U_ZERO_ERROR;
531        resultlength=resultlengthneeded+1;
532        result=(UChar*)malloc(sizeof(UChar) * resultlength);
533        unum_format(cur_def, l, result, resultlength, &pos1, &status);
534    }
535    if(U_FAILURE(status))
536    {
537        log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status));
538    }
539
540    if(U_FAILURE(status)){
541        log_err("Fail: error in unum_setSymbols: %s\n", myErrorName(status));
542    }
543    unum_applyPattern(cur_frpattern, FALSE, result, u_strlen(result),NULL,NULL);
544
545    for (symType = UNUM_DECIMAL_SEPARATOR_SYMBOL; symType < UNUM_FORMAT_SYMBOL_COUNT; symType++) {
546        status=U_ZERO_ERROR;
547        unum_getSymbol(cur_def, symType, temp1, sizeof(temp1), &status);
548        unum_getSymbol(cur_frpattern, symType, temp2, sizeof(temp2), &status);
549        if(U_FAILURE(status) || u_strcmp(temp1, temp2) != 0)
550        {
551            log_err("Fail: error in getting symbols\n");
552        }
553        else
554            log_verbose("Pass: get and set symbols successful\n");
555    }
556
557    /*format and check with the previous result */
558
559    resultlength=0;
560    resultlengthneeded=unum_format(cur_frpattern, l, NULL, resultlength, &pos1, &status);
561    if(status==U_BUFFER_OVERFLOW_ERROR)
562    {
563        status=U_ZERO_ERROR;
564        resultlength=resultlengthneeded+1;
565        unum_format(cur_frpattern, l, temp1, resultlength, &pos1, &status);
566    }
567    if(U_FAILURE(status))
568    {
569        log_err("Error in formatting using unum_format(.....): %s\n", myErrorName(status));
570    }
571    /* TODO:
572     * This test fails because we have not called unum_applyPattern().
573     * Currently, such an applyPattern() does not exist on the C API, and
574     * we have jitterbug 411 for it.
575     * Since it is close to the 1.5 release, I (markus) am disabling this test just
576     * for this release (I added the test itself only last week).
577     * For the next release, we need to fix this.
578     * Then, remove the uprv_strcmp("1.5", ...) and this comment, and the include "cstring.h" at the beginning of this file.
579     */
580    if(u_strcmp(result, temp1) != 0) {
581        log_err("Formatting failed after setting symbols. result=%s temp1=%s\n", result, temp1);
582    }
583
584
585    /*----------- */
586
587free(result);
588
589    /* Testing unum_get/setSymbol() */
590    for(i = 0; i < UNUM_FORMAT_SYMBOL_COUNT; ++i) {
591        symbol[0] = (UChar)(0x41 + i);
592        symbol[1] = (UChar)(0x61 + i);
593        unum_setSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, 2, &status);
594        if(U_FAILURE(status)) {
595            log_err("Error from unum_setSymbol(%d): %s\n", i, myErrorName(status));
596            return;
597        }
598    }
599    for(i = 0; i < UNUM_FORMAT_SYMBOL_COUNT; ++i) {
600        resultlength = unum_getSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, sizeof(symbol)/U_SIZEOF_UCHAR, &status);
601        if(U_FAILURE(status)) {
602            log_err("Error from unum_getSymbol(%d): %s\n", i, myErrorName(status));
603            return;
604        }
605        if(resultlength != 2 || symbol[0] != 0x41 + i || symbol[1] != 0x61 + i) {
606            log_err("Failure in unum_getSymbol(%d): got unexpected symbol\n", i);
607        }
608    }
609    /*try getting from a bogus symbol*/
610    unum_getSymbol(cur_frpattern, (UNumberFormatSymbol)i, symbol, sizeof(symbol)/U_SIZEOF_UCHAR, &status);
611    if(U_SUCCESS(status)){
612        log_err("Error : Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol");
613    }
614    if(U_FAILURE(status)){
615        if(status != U_ILLEGAL_ARGUMENT_ERROR){
616            log_err("Error: Expected U_ILLEGAL_ARGUMENT_ERROR for bogus symbol, Got %s\n", myErrorName(status));
617        }
618    }
619    status=U_ZERO_ERROR;
620
621    /* Testing unum_getTextAttribute() and unum_setTextAttribute()*/
622    log_verbose("\nTesting getting and setting text attributes\n");
623    resultlength=5;
624    unum_getTextAttribute(cur_fr, UNUM_NEGATIVE_SUFFIX, temp, resultlength, &status);
625    if(U_FAILURE(status))
626    {
627        log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status));
628    }
629    unum_setTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, temp, u_strlen(temp), &status);
630    if(U_FAILURE(status))
631    {
632        log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status));
633    }
634    unum_getTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, suffix, resultlength, &status);
635    if(U_FAILURE(status))
636    {
637        log_err("Failure in gettting the Text attributes of number format: %s\n", myErrorName(status));
638    }
639    if(u_strcmp(suffix,temp)!=0)
640        log_err("Fail:Error in setTextAttribute or getTextAttribute in setting and getting suffix\n");
641    else
642        log_verbose("Pass: setting and getting suffix works fine\n");
643    /*set it back to normal */
644    u_uastrcpy(temp,"$");
645    unum_setTextAttribute(cur_def, UNUM_NEGATIVE_SUFFIX, temp, u_strlen(temp), &status);
646
647    /*checking some more text setter conditions */
648    u_uastrcpy(prefix, "+");
649    unum_setTextAttribute(def, UNUM_POSITIVE_PREFIX, prefix, u_strlen(prefix) , &status);
650    if(U_FAILURE(status))
651    {
652        log_err("error in setting the text attributes : %s\n", myErrorName(status));
653    }
654    unum_getTextAttribute(def, UNUM_POSITIVE_PREFIX, temp, resultlength, &status);
655    if(U_FAILURE(status))
656    {
657        log_err("error in getting the text attributes : %s\n", myErrorName(status));
658    }
659
660    if(u_strcmp(prefix, temp)!=0)
661        log_err("ERROR: get and setTextAttributes with positive prefix failed\n");
662    else
663        log_verbose("Pass: get and setTextAttributes with positive prefix works fine\n");
664
665    u_uastrcpy(prefix, "+");
666    unum_setTextAttribute(def, UNUM_NEGATIVE_PREFIX, prefix, u_strlen(prefix), &status);
667    if(U_FAILURE(status))
668    {
669        log_err("error in setting the text attributes : %s\n", myErrorName(status));
670    }
671    unum_getTextAttribute(def, UNUM_NEGATIVE_PREFIX, temp, resultlength, &status);
672    if(U_FAILURE(status))
673    {
674        log_err("error in getting the text attributes : %s\n", myErrorName(status));
675    }
676    if(u_strcmp(prefix, temp)!=0)
677        log_err("ERROR: get and setTextAttributes with negative prefix failed\n");
678    else
679        log_verbose("Pass: get and setTextAttributes with negative prefix works fine\n");
680
681    u_uastrcpy(suffix, "+");
682    unum_setTextAttribute(def, UNUM_NEGATIVE_SUFFIX, suffix, u_strlen(suffix) , &status);
683    if(U_FAILURE(status))
684    {
685        log_err("error in setting the text attributes: %s\n", myErrorName(status));
686    }
687
688    unum_getTextAttribute(def, UNUM_NEGATIVE_SUFFIX, temp, resultlength, &status);
689    if(U_FAILURE(status))
690    {
691        log_err("error in getting the text attributes : %s\n", myErrorName(status));
692    }
693    if(u_strcmp(suffix, temp)!=0)
694        log_err("ERROR: get and setTextAttributes with negative suffix failed\n");
695    else
696        log_verbose("Pass: get and settextAttributes with negative suffix works fine\n");
697
698    u_uastrcpy(suffix, "++");
699    unum_setTextAttribute(def, UNUM_POSITIVE_SUFFIX, suffix, u_strlen(suffix) , &status);
700    if(U_FAILURE(status))
701    {
702        log_err("error in setting the text attributes: %s\n", myErrorName(status));
703    }
704
705    unum_getTextAttribute(def, UNUM_POSITIVE_SUFFIX, temp, resultlength, &status);
706    if(U_FAILURE(status))
707    {
708        log_err("error in getting the text attributes : %s\n", myErrorName(status));
709    }
710    if(u_strcmp(suffix, temp)!=0)
711        log_err("ERROR: get and setTextAttributes with negative suffix failed\n");
712    else
713        log_verbose("Pass: get and settextAttributes with negative suffix works fine\n");
714
715    /*Testing unum_getAttribute and  unum_setAttribute() */
716    log_verbose("\nTesting get and set Attributes\n");
717    attr=UNUM_GROUPING_SIZE;
718    newvalue=unum_getAttribute(def, attr);
719    newvalue=2;
720    unum_setAttribute(def, attr, newvalue);
721    if(unum_getAttribute(def,attr)!=2)
722        log_err("Fail: error in setting and getting attributes for UNUM_GROUPING_SIZE\n");
723    else
724        log_verbose("Pass: setting and getting attributes for UNUM_GROUPING_SIZE works fine\n");
725
726    attr=UNUM_MULTIPLIER;
727    newvalue=unum_getAttribute(def, attr);
728    newvalue=8;
729    unum_setAttribute(def, attr, newvalue);
730    if(unum_getAttribute(def,attr) != 8)
731        log_err("error in setting and getting attributes for UNUM_MULTIPLIER\n");
732    else
733        log_verbose("Pass:setting and getting attributes for UNUM_MULTIPLIER works fine\n");
734
735    attr=UNUM_SECONDARY_GROUPING_SIZE;
736    newvalue=unum_getAttribute(def, attr);
737    newvalue=2;
738    unum_setAttribute(def, attr, newvalue);
739    if(unum_getAttribute(def,attr) != 2)
740        log_err("error in setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE\n");
741    else
742        log_verbose("Pass:setting and getting attributes for UNUM_SECONDARY_GROUPING_SIZE works fine\n");
743
744    /*testing set and get Attributes extensively */
745    log_verbose("\nTesting get and set attributes extensively\n");
746    for(attr=UNUM_PARSE_INT_ONLY; attr<= UNUM_PADDING_POSITION; attr=(UNumberFormatAttribute)((int32_t)attr + 1) )
747    {
748        newvalue=unum_getAttribute(fr, attr);
749        unum_setAttribute(def, attr, newvalue);
750        if(unum_getAttribute(def,attr)!=unum_getAttribute(fr, attr))
751            log_err("error in setting and getting attributes\n");
752        else
753            log_verbose("Pass: attributes set and retrieved successfully\n");
754    }
755
756    /*testing spellout format to make sure we can use it successfully.*/
757    log_verbose("\nTesting spellout format\n");
758    if (spellout_def)
759    {
760        static const int32_t values[] = { 0, -5, 105, 1005, 105050 };
761        for (i = 0; i < LENGTH(values); ++i) {
762            UChar buffer[128];
763            int32_t len;
764            int32_t value = values[i];
765            status = U_ZERO_ERROR;
766            len = unum_format(spellout_def, value, buffer, LENGTH(buffer), NULL, &status);
767            if(U_FAILURE(status)) {
768                log_err("Error in formatting using unum_format(spellout_fmt, ...): %s\n", myErrorName(status));
769            } else {
770                int32_t pp = 0;
771                int32_t parseResult;
772                /*ustrToAstr(buffer, len, logbuf, LENGTH(logbuf));*/
773                log_verbose("formatted %d as '%s', length: %d\n", value, aescstrdup(buffer, len), len);
774
775                parseResult = unum_parse(spellout_def, buffer, len, &pp, &status);
776                if (U_FAILURE(status)) {
777                    log_err("Error in parsing using unum_format(spellout_fmt, ...): %s\n", myErrorName(status));
778                } else if (parseResult != value) {
779                    log_err("unum_format result %d != value %d\n", parseResult, value);
780                }
781            }
782        }
783    }
784    else {
785        log_err("Spellout format is unavailable\n");
786    }
787
788    {    /* Test for ticket #7079 */
789        UNumberFormat* dec_en;
790        UChar groupingSep[] = { 0 };
791        UChar numPercent[] = { 0x0031, 0x0032, 0x0025, 0 }; /* "12%" */
792        double parseResult = 0.0;
793
794        status=U_ZERO_ERROR;
795        dec_en = unum_open(UNUM_DECIMAL, NULL, 0, "en_US", NULL, &status);
796        unum_setAttribute(dec_en, UNUM_LENIENT_PARSE, 0);
797        unum_setSymbol(dec_en, UNUM_GROUPING_SEPARATOR_SYMBOL, groupingSep, 0, &status);
798        parseResult = unum_parseDouble(dec_en, numPercent, -1, NULL, &status);
799        /* Without the fix in #7079, the above call will hang */
800        if ( U_FAILURE(status) || parseResult != 12.0 ) {
801            log_err("unum_parseDouble with empty groupingSep: status %s, parseResult %f not 12.0\n",
802                    myErrorName(status), parseResult);
803        } else {
804            log_verbose("unum_parseDouble with empty groupingSep: no hang, OK\n");
805        }
806        unum_close(dec_en);
807    }
808
809    {   /* Test parse & format of big decimals.  Use a number with too many digits to fit in a double,
810                                         to verify that it is taking the pure decimal path. */
811        UNumberFormat *fmt;
812        const char *bdpattern = "#,##0.#########";
813        const char *numInitial     = "12345678900987654321.1234567896";
814        const char *numFormatted  = "12,345,678,900,987,654,321.12345679";
815        const char *parseExpected = "12345678900987654321.12345679";
816        int32_t resultSize    = 0;
817        int32_t parsePos      = 0;     /* Output parameter for Parse operations. */
818        #define DESTCAPACITY 100
819        UChar dest[DESTCAPACITY];
820        char  desta[DESTCAPACITY];
821        UFieldPosition fieldPos = {0};
822
823        /* Format */
824
825        status = U_ZERO_ERROR;
826        u_uastrcpy(dest, bdpattern);
827        fmt = unum_open(UNUM_PATTERN_DECIMAL, dest, -1, "en", NULL /*parseError*/, &status);
828        if (U_FAILURE(status)) log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
829
830        resultSize = unum_formatDecimal(fmt, numInitial, -1, dest, DESTCAPACITY, NULL, &status);
831        if (U_FAILURE(status)) {
832            log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
833        }
834        u_austrncpy(desta, dest, DESTCAPACITY);
835        if (strcmp(numFormatted, desta) != 0) {
836            log_err("File %s, Line %d, (expected, acutal) =  (\"%s\", \"%s\")\n",
837                    __FILE__, __LINE__, numFormatted, desta);
838        }
839        if (strlen(numFormatted) != resultSize) {
840            log_err("File %s, Line %d, (expected, actual) = (%d, %d)\n",
841                     __FILE__, __LINE__, strlen(numFormatted), resultSize);
842        }
843
844        /* Format with a FieldPosition parameter */
845
846        fieldPos.field = UNUM_DECIMAL_SEPARATOR_FIELD;
847        resultSize = unum_formatDecimal(fmt, numInitial, -1, dest, DESTCAPACITY, &fieldPos, &status);
848        if (U_FAILURE(status)) {
849            log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
850        }
851        u_austrncpy(desta, dest, DESTCAPACITY);
852        if (strcmp(numFormatted, desta) != 0) {
853            log_err("File %s, Line %d, (expected, acutal) =  (\"%s\", \"%s\")\n",
854                    __FILE__, __LINE__, numFormatted, desta);
855        }
856        if (fieldPos.beginIndex != 26) {  /* index of "." in formatted number */
857            log_err("File %s, Line %d, (expected, acutal) =  (%d, %d)\n",
858                    __FILE__, __LINE__, 0, fieldPos.beginIndex);
859        }
860        if (fieldPos.endIndex != 27) {
861            log_err("File %s, Line %d, (expected, acutal) =  (%d, %d)\n",
862                    __FILE__, __LINE__, 0, fieldPos.endIndex);
863        }
864
865        /* Parse */
866
867        status = U_ZERO_ERROR;
868        u_uastrcpy(dest, numFormatted);   /* Parse the expected output of the formatting test */
869        resultSize = unum_parseDecimal(fmt, dest, -1, NULL, desta, DESTCAPACITY, &status);
870        if (U_FAILURE(status)) {
871            log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
872        }
873        if (strcmp(parseExpected, desta) != 0) {
874            log_err("File %s, Line %d, (expected, actual) = (\"%s\", \"%s\")\n",
875                    __FILE__, __LINE__, parseExpected, desta);
876        }
877        if (strlen(parseExpected) != resultSize) {
878            log_err("File %s, Line %d, (expected, actual) = (%d, %d)\n",
879                    __FILE__, __LINE__, strlen(parseExpected), resultSize);
880        }
881
882        /* Parse with a parsePos parameter */
883
884        status = U_ZERO_ERROR;
885        u_uastrcpy(dest, numFormatted);   /* Parse the expected output of the formatting test */
886        parsePos = 3;                 /*      12,345,678,900,987,654,321.12345679         */
887                                      /* start parsing at the the third char              */
888        resultSize = unum_parseDecimal(fmt, dest, -1, &parsePos, desta, DESTCAPACITY, &status);
889        if (U_FAILURE(status)) {
890            log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
891        }
892        if (strcmp(parseExpected+2, desta) != 0) {   /*  "345678900987654321.12345679" */
893            log_err("File %s, Line %d, (expected, actual) = (\"%s\", \"%s\")\n",
894                    __FILE__, __LINE__, parseExpected+2, desta);
895        }
896        if (strlen(numFormatted) != parsePos) {
897            log_err("File %s, Line %d, parsePos (expected, actual) = (\"%d\", \"%d\")\n",
898                    __FILE__, __LINE__, strlen(parseExpected), parsePos);
899        }
900
901        unum_close(fmt);
902    }
903
904    status = U_ZERO_ERROR;
905    /* Test invalid symbol argument */
906    {
907        int32_t badsymbolLarge = UNUM_FORMAT_SYMBOL_COUNT + 1;
908        int32_t badsymbolSmall = -1;
909        UChar value[10];
910        int32_t valueLength = 10;
911        UNumberFormat *fmt = unum_open(UNUM_DEFAULT, NULL, 0, NULL, NULL, &status);
912        if (U_FAILURE(status)) {
913            log_err("File %s, Line %d, status = %s\n", __FILE__, __LINE__, u_errorName(status));
914        } else {
915            unum_getSymbol(fmt, (UNumberFormatSymbol)badsymbolLarge, NULL, 0, &status);
916            if (U_SUCCESS(status)) log_err("unum_getSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (> UNUM_FORMAT_SYMBOL_COUNT) argument\n");
917
918            status = U_ZERO_ERROR;
919            unum_getSymbol(fmt, (UNumberFormatSymbol)badsymbolSmall, NULL, 0, &status);
920            if (U_SUCCESS(status)) log_err("unum_getSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (less than 0) argument\n");
921
922            status = U_ZERO_ERROR;
923            unum_setSymbol(fmt, (UNumberFormatSymbol)badsymbolLarge, value, valueLength, &status);
924            if (U_SUCCESS(status)) log_err("unum_setSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (> UNUM_FORMAT_SYMBOL_COUNT) argument\n");
925
926            status = U_ZERO_ERROR;
927            unum_setSymbol(fmt, (UNumberFormatSymbol)badsymbolSmall, value, valueLength, &status);
928            if (U_SUCCESS(status)) log_err("unum_setSymbol()'s status should be ILLEGAL_ARGUMENT with invalid symbol (less than 0) argument\n");
929
930            unum_close(fmt);
931        }
932    }
933
934
935    /*closing the NumberFormat() using unum_close(UNumberFormat*)")*/
936    unum_close(def);
937    unum_close(fr);
938    unum_close(cur_def);
939    unum_close(cur_fr);
940    unum_close(per_def);
941    unum_close(per_fr);
942    unum_close(spellout_def);
943    unum_close(pattern);
944    unum_close(cur_frpattern);
945    unum_close(myclone);
946
947}
948
949static void TestParseZero(void)
950{
951    UErrorCode errorCode = U_ZERO_ERROR;
952    UChar input[] = {0x30, 0};   /*  Input text is decimal '0' */
953    UChar pat[] = {0x0023,0x003b,0x0023,0}; /*  {'#', ';', '#', 0}; */
954    double  dbl;
955
956#if 0
957    UNumberFormat* unum = unum_open( UNUM_DECIMAL /*or UNUM_DEFAULT*/, NULL, -1, NULL, NULL, &errorCode);
958#else
959    UNumberFormat* unum = unum_open( UNUM_PATTERN_DECIMAL /*needs pattern*/, pat, -1, NULL, NULL, &errorCode);
960#endif
961
962    dbl = unum_parseDouble( unum, input, -1 /*u_strlen(input)*/, 0 /* 0 = start */, &errorCode );
963    if (U_FAILURE(errorCode)) {
964        log_data_err("Result - %s\n", u_errorName(errorCode));
965    } else {
966        log_verbose("Double: %f\n", dbl);
967    }
968    unum_close(unum);
969}
970
971static const UChar dollars2Sym[] = { 0x24,0x32,0x2E,0x30,0x30,0 }; /* $2.00 */
972static const UChar dollars4Sym[] = { 0x24,0x34,0 }; /* $4 */
973static const UChar dollars9Sym[] = { 0x39,0xA0,0x24,0 }; /* 9 $ */
974static const UChar pounds3Sym[]  = { 0xA3,0x33,0x2E,0x30,0x30,0 }; /* [POUND]3.00 */
975static const UChar pounds5Sym[]  = { 0xA3,0x35,0 }; /* [POUND]5 */
976static const UChar pounds7Sym[]  = { 0x37,0xA0,0xA3,0 }; /* 7 [POUND] */
977static const UChar euros4Sym[]   = { 0x34,0x2C,0x30,0x30,0xA0,0x20AC,0 }; /* 4,00 [EURO] */
978static const UChar euros6Sym[]   = { 0x36,0xA0,0x20AC,0 }; /* 6 [EURO] */
979static const UChar euros8Sym[]   = { 0x20AC,0x38,0 }; /* [EURO]8 */
980static const UChar dollars4PluEn[] = { 0x34,0x20,0x55,0x53,0x20,0x64,0x6F,0x6C,0x6C,0x61,0x72,0x73,0 }; /* 4 US dollars*/
981static const UChar pounds5PluEn[]  = { 0x35,0x20,0x42,0x72,0x69,0x74,0x69,0x73,0x68,0x20,0x70,0x6F,0x75,0x6E,0x64,0x73,0x20,0x73,0x74,0x65,0x72,0x6C,0x69,0x6E,0x67,0 }; /* 5 British pounds sterling */
982static const UChar euros8PluEn[]   = { 0x38,0x20,0x65,0x75,0x72,0x6F,0x73,0 }; /* 8 euros*/
983static const UChar euros6PluFr[]   = { 0x36,0x20,0x65,0x75,0x72,0x6F,0x73,0 }; /* 6 euros*/
984
985typedef struct {
986    const char *  locale;
987    const char *  descrip;
988    const UChar * currStr;
989    const UChar * plurStr;
990    UErrorCode    parsDoubExpectErr;
991    int32_t       parsDoubExpectPos;
992    double        parsDoubExpectVal;
993    UErrorCode    parsCurrExpectErr;
994    int32_t       parsCurrExpectPos;
995    double        parsCurrExpectVal;
996    const char *  parsCurrExpectCurr;
997} ParseCurrencyItem;
998
999static const ParseCurrencyItem parseCurrencyItems[] = {
1000    { "en_US", "dollars2", dollars2Sym, NULL,          U_ZERO_ERROR,  5, 2.0, U_ZERO_ERROR,  5, 2.0, "USD" },
1001    { "en_US", "dollars4", dollars4Sym, dollars4PluEn, U_ZERO_ERROR,  2, 4.0, U_ZERO_ERROR,  2, 4.0, "USD" },
1002    { "en_US", "dollars9", dollars9Sym, NULL,          U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, ""    },
1003    { "en_US", "pounds3",  pounds3Sym,  NULL,          U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR,  5, 3.0, "GBP" },
1004    { "en_US", "pounds5",  pounds5Sym,  pounds5PluEn,  U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR,  2, 5.0, "GBP" },
1005    { "en_US", "pounds7",  pounds7Sym,  NULL,          U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, ""    },
1006    { "en_US", "euros8",   euros8Sym,   euros8PluEn,   U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR,  2, 8.0, "EUR" },
1007
1008    { "en_GB", "pounds3",  pounds3Sym,  NULL,          U_ZERO_ERROR,  5, 3.0, U_ZERO_ERROR,  5, 3.0, "GBP" },
1009    { "en_GB", "pounds5",  pounds5Sym,  pounds5PluEn,  U_ZERO_ERROR,  2, 5.0, U_ZERO_ERROR,  2, 5.0, "GBP" },
1010    { "en_GB", "pounds7",  pounds7Sym,  NULL,          U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, ""    },
1011    { "en_GB", "euros4",   euros4Sym,   NULL,          U_PARSE_ERROR, 4, 0.0, U_PARSE_ERROR, 4, 0.0, ""    },
1012    { "en_GB", "euros6",   euros6Sym,   NULL,          U_PARSE_ERROR, 1, 0.0, U_PARSE_ERROR, 1, 0.0, ""    },
1013    { "en_GB", "euros8",   euros8Sym,   euros8PluEn,   U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR,  2, 8.0, "EUR" },
1014    { "en_GB", "dollars4", dollars4Sym, dollars4PluEn, U_PARSE_ERROR, 0, 0.0, U_ZERO_ERROR,  2, 4.0, "USD" },
1015
1016    { "fr_FR", "euros4",   euros4Sym,   NULL,          U_ZERO_ERROR,  6, 4.0, U_ZERO_ERROR,  6, 4.0, "EUR" },
1017    { "fr_FR", "euros6",   euros6Sym,   euros6PluFr,   U_ZERO_ERROR,  3, 6.0, U_ZERO_ERROR,  3, 6.0, "EUR" },
1018    { "fr_FR", "euros8",   euros8Sym,   NULL,          U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, 0.0, ""    },
1019    { "fr_FR", "dollars2", dollars2Sym, NULL,          U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, 0.0, ""    },
1020    { "fr_FR", "dollars4", dollars4Sym, NULL,          U_PARSE_ERROR, 0, 0.0, U_PARSE_ERROR, 0, 0.0, ""    },
1021
1022    { NULL,    NULL,       NULL,        NULL,          0,             0, 0.0, 0,             0, 0.0, NULL  }
1023};
1024
1025static void TestParseCurrency()
1026{
1027    const ParseCurrencyItem * itemPtr;
1028    for (itemPtr = parseCurrencyItems; itemPtr->locale != NULL; ++itemPtr) {
1029        UNumberFormat* unum;
1030        UErrorCode status;
1031        double parseVal;
1032        int32_t parsePos;
1033        UChar parseCurr[4];
1034        char parseCurrB[4];
1035
1036        status = U_ZERO_ERROR;
1037        unum = unum_open(UNUM_CURRENCY, NULL, 0, itemPtr->locale, NULL, &status);
1038        if (U_SUCCESS(status)) {
1039            status = U_ZERO_ERROR;
1040            parsePos = 0;
1041            parseVal = unum_parseDouble(unum, itemPtr->currStr, -1, &parsePos, &status);
1042            if (status != itemPtr->parsDoubExpectErr || parsePos != itemPtr->parsDoubExpectPos || parseVal != itemPtr->parsDoubExpectVal) {
1043                log_err("UNUM_CURRENCY parseDouble %s/%s, expect %s pos %d val %.1f, get %s pos %d val %.1f\n",
1044                        itemPtr->locale, itemPtr->descrip,
1045                        u_errorName(itemPtr->parsDoubExpectErr), itemPtr->parsDoubExpectPos, itemPtr->parsDoubExpectVal,
1046                        u_errorName(status), parsePos, parseVal );
1047            }
1048            status = U_ZERO_ERROR;
1049            parsePos = 0;
1050            parseCurr[0] = 0;
1051            parseVal = unum_parseDoubleCurrency(unum, itemPtr->currStr, -1, &parsePos, parseCurr, &status);
1052            u_austrncpy(parseCurrB, parseCurr, 4);
1053            if (status != itemPtr->parsCurrExpectErr || parsePos != itemPtr->parsCurrExpectPos || parseVal != itemPtr->parsCurrExpectVal ||
1054                    strncmp(parseCurrB, itemPtr->parsCurrExpectCurr, 4) != 0) {
1055                log_err("UNUM_CURRENCY parseDoubleCurrency %s/%s, expect %s pos %d val %.1f cur %s, get %s pos %d val %.1f cur %s\n",
1056                        itemPtr->locale, itemPtr->descrip,
1057                        u_errorName(itemPtr->parsCurrExpectErr), itemPtr->parsCurrExpectPos, itemPtr->parsCurrExpectVal, itemPtr->parsCurrExpectCurr,
1058                        u_errorName(status), parsePos, parseVal, parseCurrB );
1059            }
1060            unum_close(unum);
1061        } else {
1062            log_data_err("unexpected error in unum_open UNUM_CURRENCY for locale %s: '%s'\n", itemPtr->locale, u_errorName(status));
1063        }
1064
1065#if 0
1066        /* Hmm, for UNUM_CURRENCY_PLURAL, currently unum_open always sets U_UNSUPPORTED_ERROR, save this test until it is supported */
1067        if (itemPtr->plurStr != NULL) {
1068            status = U_ZERO_ERROR;
1069            unum = unum_open(UNUM_CURRENCY_PLURAL, NULL, 0, itemPtr->locale, NULL, &status);
1070            if (U_SUCCESS(status)) {
1071                status = U_ZERO_ERROR;
1072                parsePos = 0;
1073                parseVal = unum_parseDouble(unum, itemPtr->plurStr, -1, &parsePos, &status);
1074                if (status != itemPtr->parsDoubExpectErr || parseVal != itemPtr->parsDoubExpectVal) {
1075                    log_err("UNUM_CURRENCY parseDouble %s/%s, expect %s val %.1f, get %s val %.1f\n",
1076                            itemPtr->locale, itemPtr->descrip,
1077                            u_errorName(itemPtr->parsDoubExpectErr), itemPtr->parsDoubExpectVal,
1078                            u_errorName(status), parseVal );
1079                }
1080                status = U_ZERO_ERROR;
1081                parsePos = 0;
1082                parseCurr[0] = 0;
1083                parseVal = unum_parseDoubleCurrency(unum, itemPtr->plurStr, -1, &parsePos, parseCurr, &status);
1084                u_austrncpy(parseCurrB, parseCurr, 4);
1085                if (status != itemPtr->parsCurrExpectErr || parseVal != itemPtr->parsCurrExpectVal ||
1086                        strncmp(parseCurrB, itemPtr->parsCurrExpectCurr, 4) != 0) {
1087                    log_err("UNUM_CURRENCY parseDoubleCurrency %s/%s, expect %s val %.1f cur %s, get %s val %.1f cur %s\n",
1088                            itemPtr->locale, itemPtr->descrip,
1089                            u_errorName(itemPtr->parsCurrExpectErr), itemPtr->parsCurrExpectVal, itemPtr->parsCurrExpectCurr,
1090                            u_errorName(status), parseVal, parseCurrB );
1091                }
1092                unum_close(unum);
1093            } else {
1094                log_data_err("unexpected error in unum_open UNUM_CURRENCY_PLURAL for locale %s: '%s'\n", itemPtr->locale, u_errorName(status));
1095            }
1096        }
1097#endif
1098    }
1099}
1100
1101typedef struct {
1102    const char *  testname;
1103    const char *  locale;
1104    const UChar * source;
1105    int32_t       startPos;
1106    int32_t       value;
1107    int32_t       endPos;
1108    UErrorCode    status;
1109} SpelloutParseTest;
1110
1111static const UChar ustr_en0[]   = {0x7A, 0x65, 0x72, 0x6F, 0}; /* zero */
1112static const UChar ustr_123[]   = {0x31, 0x32, 0x33, 0};       /* 123 */
1113static const UChar ustr_en123[] = {0x6f, 0x6e, 0x65, 0x20, 0x68, 0x75, 0x6e, 0x64, 0x72, 0x65, 0x64,
1114                                   0x20, 0x74, 0x77, 0x65, 0x6e, 0x74, 0x79,
1115                                   0x2d, 0x74, 0x68, 0x72, 0x65, 0x65, 0}; /* one hundred twenty-three */
1116static const UChar ustr_fr123[] = {0x63, 0x65, 0x6e, 0x74, 0x2d, 0x76, 0x69, 0x6e, 0x67, 0x74, 0x2d,
1117                                   0x74, 0x72, 0x6f, 0x69, 0x73, 0};       /* cent-vingt-trois */
1118static const UChar ustr_ja123[] = {0x767e, 0x4e8c, 0x5341, 0x4e09, 0};     /* kanji 100(+)2(*)10(+)3 */
1119
1120static const SpelloutParseTest spelloutParseTests[] = {
1121    /* name    loc   src       start val  end status */
1122    { "en0",   "en", ustr_en0,    0,   0,  4, U_ZERO_ERROR },
1123    { "en0",   "en", ustr_en0,    2,   0,  2, U_PARSE_ERROR },
1124    { "en0",   "ja", ustr_en0,    0,   0,  0, U_PARSE_ERROR },
1125    { "123",   "en", ustr_123,    0, 123,  3, U_ZERO_ERROR },
1126    { "en123", "en", ustr_en123,  0, 123, 24, U_ZERO_ERROR },
1127    { "en123", "en", ustr_en123, 12,  23, 24, U_ZERO_ERROR },
1128    { "en123", "fr", ustr_en123, 16,   0, 16, U_PARSE_ERROR },
1129    { "fr123", "fr", ustr_fr123,  0, 123, 16, U_ZERO_ERROR },
1130    { "fr123", "fr", ustr_fr123,  5,  23, 16, U_ZERO_ERROR },
1131    { "fr123", "en", ustr_fr123,  0,   0,  0, U_PARSE_ERROR },
1132    { "ja123", "ja", ustr_ja123,  0, 123,  4, U_ZERO_ERROR },
1133    { "ja123", "ja", ustr_ja123,  1,  23,  4, U_ZERO_ERROR },
1134    { "ja123", "fr", ustr_ja123,  0,   0,  0, U_PARSE_ERROR },
1135    { NULL,    NULL, NULL,        0,   0,  0, 0 } /* terminator */
1136};
1137
1138static void TestSpelloutNumberParse()
1139{
1140    const SpelloutParseTest * testPtr;
1141    for (testPtr = spelloutParseTests; testPtr->testname != NULL; ++testPtr) {
1142        UErrorCode status = U_ZERO_ERROR;
1143        int32_t	value, position = testPtr->startPos;
1144        UNumberFormat *nf = unum_open(UNUM_SPELLOUT, NULL, 0, testPtr->locale, NULL, &status);
1145        if (U_FAILURE(status)) {
1146            log_err_status(status, "unum_open fails for UNUM_SPELLOUT with locale %s, status %s\n", testPtr->locale, myErrorName(status));
1147            continue;
1148        }
1149        value = unum_parse(nf, testPtr->source, -1, &position, &status);
1150        if ( value != testPtr->value || position != testPtr->endPos || status != testPtr->status ) {
1151            log_err("unum_parse SPELLOUT, locale %s, testname %s, startPos %d: for value / endPos / status, expected %d / %d / %s, got %d / %d / %s\n",
1152                    testPtr->locale, testPtr->testname, testPtr->startPos,
1153                    testPtr->value, testPtr->endPos, myErrorName(testPtr->status),
1154                    value, position, myErrorName(status) );
1155        }
1156        unum_close(nf);
1157    }
1158}
1159
1160static void TestSignificantDigits()
1161{
1162    UChar temp[128];
1163    int32_t resultlengthneeded;
1164    int32_t resultlength;
1165    UErrorCode status = U_ZERO_ERROR;
1166    UChar *result = NULL;
1167    UNumberFormat* fmt;
1168    double d = 123456.789;
1169
1170    u_uastrcpy(temp, "###0.0#");
1171    fmt=unum_open(UNUM_IGNORE, temp, -1, NULL, NULL,&status);
1172    if (U_FAILURE(status)) {
1173        log_data_err("got unexpected error for unum_open: '%s'\n", u_errorName(status));
1174        return;
1175    }
1176    unum_setAttribute(fmt, UNUM_SIGNIFICANT_DIGITS_USED, TRUE);
1177    unum_setAttribute(fmt, UNUM_MAX_SIGNIFICANT_DIGITS, 6);
1178
1179    u_uastrcpy(temp, "123457");
1180    resultlength=0;
1181    resultlengthneeded=unum_formatDouble(fmt, d, NULL, resultlength, NULL, &status);
1182    if(status==U_BUFFER_OVERFLOW_ERROR)
1183    {
1184        status=U_ZERO_ERROR;
1185        resultlength=resultlengthneeded+1;
1186        result=(UChar*)malloc(sizeof(UChar) * resultlength);
1187        unum_formatDouble(fmt, d, result, resultlength, NULL, &status);
1188    }
1189    if(U_FAILURE(status))
1190    {
1191        log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
1192        return;
1193    }
1194    if(u_strcmp(result, temp)==0)
1195        log_verbose("Pass: Number Formatting using unum_formatDouble() Successful\n");
1196    else
1197        log_err("FAIL: Error in number formatting using unum_formatDouble()\n");
1198    free(result);
1199    unum_close(fmt);
1200}
1201
1202static void TestSigDigRounding()
1203{
1204    UErrorCode status = U_ZERO_ERROR;
1205    UChar expected[128];
1206    UChar result[128];
1207    char		temp1[128];
1208    char		temp2[128];
1209    UNumberFormat* fmt;
1210    double d = 123.4;
1211
1212    fmt=unum_open(UNUM_DECIMAL, NULL, 0, NULL /* "en_US"*/, NULL, &status);
1213    if (U_FAILURE(status)) {
1214        log_data_err("got unexpected error for unum_open: '%s'\n", u_errorName(status));
1215        return;
1216    }
1217    unum_setAttribute(fmt, UNUM_LENIENT_PARSE, FALSE);
1218    unum_setAttribute(fmt, UNUM_SIGNIFICANT_DIGITS_USED, TRUE);
1219    unum_setAttribute(fmt, UNUM_MAX_SIGNIFICANT_DIGITS, 2);
1220    /* unum_setAttribute(fmt, UNUM_MAX_FRACTION_DIGITS, 0); */
1221
1222    unum_setAttribute(fmt, UNUM_ROUNDING_MODE, UNUM_ROUND_UP);
1223    unum_setDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT, 20.0);
1224
1225    (void)unum_formatDouble(fmt, d, result, sizeof(result) / sizeof(result[0]), NULL, &status);
1226    if(U_FAILURE(status))
1227    {
1228        log_err("Error in formatting using unum_formatDouble(.....): %s\n", myErrorName(status));
1229        return;
1230    }
1231
1232    u_uastrcpy(expected, "140");
1233    if(u_strcmp(result, expected)!=0)
1234        log_err("FAIL: Error in unum_formatDouble result %s instead of %s\n", u_austrcpy(temp1, result), u_austrcpy(temp2, expected) );
1235
1236    unum_close(fmt);
1237}
1238
1239static void TestNumberFormatPadding()
1240{
1241    UChar *result=NULL;
1242    UChar temp1[512];
1243
1244    UErrorCode status=U_ZERO_ERROR;
1245    int32_t resultlength;
1246    int32_t resultlengthneeded;
1247    UNumberFormat *pattern;
1248    double d1;
1249    double d = -10456.37;
1250    UFieldPosition pos1;
1251    int32_t parsepos;
1252
1253    /* create a number format using unum_openPattern(....)*/
1254    log_verbose("\nTesting unum_openPattern() with padding\n");
1255    u_uastrcpy(temp1, "*#,##0.0#*;(#,##0.0#)");
1256    status=U_ZERO_ERROR;
1257    pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), NULL, NULL,&status);
1258    if(U_SUCCESS(status))
1259    {
1260        log_err("error in unum_openPattern(%s): %s\n", temp1, myErrorName(status) );
1261    }
1262    else
1263    {
1264        unum_close(pattern);
1265    }
1266
1267/*    u_uastrcpy(temp1, "*x#,###,###,##0.0#;(*x#,###,###,##0.0#)"); */
1268    u_uastrcpy(temp1, "*x#,###,###,##0.0#;*x(###,###,##0.0#)");
1269    status=U_ZERO_ERROR;
1270    pattern=unum_open(UNUM_IGNORE,temp1, u_strlen(temp1), "en_US",NULL, &status);
1271    if(U_FAILURE(status))
1272    {
1273        log_err_status(status, "error in padding unum_openPattern(%s): %s\n", temp1, myErrorName(status) );;
1274    }
1275    else {
1276        log_verbose("Pass: padding unum_openPattern() works fine\n");
1277
1278        /*test for unum_toPattern()*/
1279        log_verbose("\nTesting padding unum_toPattern()\n");
1280        resultlength=0;
1281        resultlengthneeded=unum_toPattern(pattern, FALSE, NULL, resultlength, &status);
1282        if(status==U_BUFFER_OVERFLOW_ERROR)
1283        {
1284            status=U_ZERO_ERROR;
1285            resultlength=resultlengthneeded+1;
1286            result=(UChar*)malloc(sizeof(UChar) * resultlength);
1287            unum_toPattern(pattern, FALSE, result, resultlength, &status);
1288        }
1289        if(U_FAILURE(status))
1290        {
1291            log_err("error in extracting the padding pattern from UNumberFormat: %s\n", myErrorName(status));
1292        }
1293        else
1294        {
1295            if(u_strcmp(result, temp1)!=0)
1296                log_err("FAIL: Error in extracting the padding pattern using unum_toPattern()\n");
1297            else
1298                log_verbose("Pass: extracted the padding pattern correctly using unum_toPattern()\n");
1299free(result);
1300        }
1301/*        u_uastrcpy(temp1, "(xxxxxxx10,456.37)"); */
1302        u_uastrcpy(temp1, "xxxxx(10,456.37)");
1303        resultlength=0;
1304        pos1.field = UNUM_FRACTION_FIELD;
1305        resultlengthneeded=unum_formatDouble(pattern, d, NULL, resultlength, &pos1, &status);
1306        if(status==U_BUFFER_OVERFLOW_ERROR)
1307        {
1308            status=U_ZERO_ERROR;
1309            resultlength=resultlengthneeded+1;
1310            result=(UChar*)malloc(sizeof(UChar) * resultlength);
1311            unum_formatDouble(pattern, d, result, resultlength, NULL, &status);
1312        }
1313        if(U_FAILURE(status))
1314        {
1315            log_err("Error in formatting using unum_formatDouble(.....) with padding : %s\n", myErrorName(status));
1316        }
1317        else
1318        {
1319            if(u_strcmp(result, temp1)==0)
1320                log_verbose("Pass: Number Formatting using unum_formatDouble() padding Successful\n");
1321            else
1322                log_data_err("FAIL: Error in number formatting using unum_formatDouble() with padding\n");
1323            if(pos1.beginIndex == 13 && pos1.endIndex == 15)
1324                log_verbose("Pass: Complete number formatting using unum_formatDouble() successful\n");
1325            else
1326                log_err("Fail: Error in complete number Formatting using unum_formatDouble()\nGot: b=%d end=%d\nExpected: b=13 end=15\n",
1327                        pos1.beginIndex, pos1.endIndex);
1328
1329
1330            /* Testing unum_parse() and unum_parseDouble() */
1331            log_verbose("\nTesting padding unum_parseDouble()\n");
1332            parsepos=0;
1333            d1=unum_parseDouble(pattern, result, u_strlen(result), &parsepos, &status);
1334            if(U_FAILURE(status))
1335            {
1336                log_err("padding parse failed. The error is : %s\n", myErrorName(status));
1337            }
1338
1339            if(d1!=d)
1340                log_err("Fail: Error in padding parsing\n");
1341            else
1342                log_verbose("Pass: padding parsing successful\n");
1343free(result);
1344        }
1345    }
1346
1347    unum_close(pattern);
1348}
1349
1350static UBool
1351withinErr(double a, double b, double err) {
1352    return uprv_fabs(a - b) < uprv_fabs(a * err);
1353}
1354
1355static void TestInt64Format() {
1356    UChar temp1[512];
1357    UChar result[512];
1358    UNumberFormat *fmt;
1359    UErrorCode status = U_ZERO_ERROR;
1360    const double doubleInt64Max = (double)U_INT64_MAX;
1361    const double doubleInt64Min = (double)U_INT64_MIN;
1362    const double doubleBig = 10.0 * (double)U_INT64_MAX;
1363    int32_t val32;
1364    int64_t val64;
1365    double  valDouble;
1366    int32_t parsepos;
1367
1368    /* create a number format using unum_openPattern(....) */
1369    log_verbose("\nTesting Int64Format\n");
1370    u_uastrcpy(temp1, "#.#E0");
1371    fmt = unum_open(UNUM_IGNORE, temp1, u_strlen(temp1), NULL, NULL, &status);
1372    if(U_FAILURE(status)) {
1373        log_data_err("error in unum_openPattern() - %s\n", myErrorName(status));
1374    } else {
1375        unum_setAttribute(fmt, UNUM_MAX_FRACTION_DIGITS, 20);
1376        unum_formatInt64(fmt, U_INT64_MAX, result, 512, NULL, &status);
1377        if (U_FAILURE(status)) {
1378            log_err("error in unum_format(): %s\n", myErrorName(status));
1379        } else {
1380            log_verbose("format int64max: '%s'\n", result);
1381            parsepos = 0;
1382            val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status);
1383            if (status != U_INVALID_FORMAT_ERROR) {
1384                log_err("parse didn't report error: %s\n", myErrorName(status));
1385            } else if (val32 != INT32_MAX) {
1386                log_err("parse didn't pin return value, got: %d\n", val32);
1387            }
1388
1389            status = U_ZERO_ERROR;
1390            parsepos = 0;
1391            val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status);
1392            if (U_FAILURE(status)) {
1393                log_err("parseInt64 returned error: %s\n", myErrorName(status));
1394            } else if (val64 != U_INT64_MAX) {
1395                log_err("parseInt64 returned incorrect value, got: %ld\n", val64);
1396            }
1397
1398            status = U_ZERO_ERROR;
1399            parsepos = 0;
1400            valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
1401            if (U_FAILURE(status)) {
1402                log_err("parseDouble returned error: %s\n", myErrorName(status));
1403            } else if (valDouble != doubleInt64Max) {
1404                log_err("parseDouble returned incorrect value, got: %g\n", valDouble);
1405            }
1406        }
1407
1408        unum_formatInt64(fmt, U_INT64_MIN, result, 512, NULL, &status);
1409        if (U_FAILURE(status)) {
1410            log_err("error in unum_format(): %s\n", myErrorName(status));
1411        } else {
1412            log_verbose("format int64min: '%s'\n", result);
1413            parsepos = 0;
1414            val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status);
1415            if (status != U_INVALID_FORMAT_ERROR) {
1416                log_err("parse didn't report error: %s\n", myErrorName(status));
1417            } else if (val32 != INT32_MIN) {
1418                log_err("parse didn't pin return value, got: %d\n", val32);
1419            }
1420
1421            status = U_ZERO_ERROR;
1422            parsepos = 0;
1423            val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status);
1424            if (U_FAILURE(status)) {
1425                log_err("parseInt64 returned error: %s\n", myErrorName(status));
1426            } else if (val64 != U_INT64_MIN) {
1427                log_err("parseInt64 returned incorrect value, got: %ld\n", val64);
1428            }
1429
1430            status = U_ZERO_ERROR;
1431            parsepos = 0;
1432            valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
1433            if (U_FAILURE(status)) {
1434                log_err("parseDouble returned error: %s\n", myErrorName(status));
1435            } else if (valDouble != doubleInt64Min) {
1436                log_err("parseDouble returned incorrect value, got: %g\n", valDouble);
1437            }
1438        }
1439
1440        unum_formatDouble(fmt, doubleBig, result, 512, NULL, &status);
1441        if (U_FAILURE(status)) {
1442            log_err("error in unum_format(): %s\n", myErrorName(status));
1443        } else {
1444            log_verbose("format doubleBig: '%s'\n", result);
1445            parsepos = 0;
1446            val32 = unum_parse(fmt, result, u_strlen(result), &parsepos, &status);
1447            if (status != U_INVALID_FORMAT_ERROR) {
1448                log_err("parse didn't report error: %s\n", myErrorName(status));
1449            } else if (val32 != INT32_MAX) {
1450                log_err("parse didn't pin return value, got: %d\n", val32);
1451            }
1452
1453            status = U_ZERO_ERROR;
1454            parsepos = 0;
1455            val64 = unum_parseInt64(fmt, result, u_strlen(result), &parsepos, &status);
1456            if (status != U_INVALID_FORMAT_ERROR) {
1457                log_err("parseInt64 didn't report error error: %s\n", myErrorName(status));
1458            } else if (val64 != U_INT64_MAX) {
1459                log_err("parseInt64 returned incorrect value, got: %ld\n", val64);
1460            }
1461
1462            status = U_ZERO_ERROR;
1463            parsepos = 0;
1464            valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
1465            if (U_FAILURE(status)) {
1466                log_err("parseDouble returned error: %s\n", myErrorName(status));
1467            } else if (!withinErr(valDouble, doubleBig, 1e-15)) {
1468                log_err("parseDouble returned incorrect value, got: %g\n", valDouble);
1469            }
1470        }
1471
1472		u_uastrcpy(result, "5.06e-27");
1473        parsepos = 0;
1474        valDouble = unum_parseDouble(fmt, result, u_strlen(result), &parsepos, &status);
1475        if (U_FAILURE(status)) {
1476            log_err("parseDouble() returned error: %s\n", myErrorName(status));
1477        } else if (!withinErr(valDouble, 5.06e-27, 1e-15)) {
1478            log_err("parseDouble() returned incorrect value, got: %g\n", valDouble);
1479        }
1480    }
1481    unum_close(fmt);
1482}
1483
1484
1485static void test_fmt(UNumberFormat* fmt, UBool isDecimal) {
1486    char temp[512];
1487    UChar buffer[512];
1488    int32_t BUFSIZE = sizeof(buffer)/sizeof(buffer[0]);
1489    double vals[] = {
1490        -.2, 0, .2, 5.5, 15.2, 250, 123456789
1491    };
1492    int i;
1493
1494    for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) {
1495        UErrorCode status = U_ZERO_ERROR;
1496        unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status);
1497        if (U_FAILURE(status)) {
1498            log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status));
1499        } else {
1500            u_austrcpy(temp, buffer);
1501            log_verbose("formatting %g returned '%s'\n", vals[i], temp);
1502        }
1503    }
1504
1505    /* check APIs now */
1506    {
1507        UErrorCode status = U_ZERO_ERROR;
1508        UParseError perr;
1509        u_uastrcpy(buffer, "#,##0.0#");
1510        unum_applyPattern(fmt, FALSE, buffer, -1, &perr, &status);
1511        if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
1512            log_err("got unexpected error for applyPattern: '%s'\n", u_errorName(status));
1513        }
1514    }
1515
1516    {
1517        int isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE);
1518        log_verbose("lenient: 0x%x\n", isLenient);
1519        if (isLenient != FALSE) {
1520            log_err("didn't expect lenient value: %d\n", isLenient);
1521        }
1522
1523        unum_setAttribute(fmt, UNUM_LENIENT_PARSE, TRUE);
1524        isLenient = unum_getAttribute(fmt, UNUM_LENIENT_PARSE);
1525        if (isLenient != TRUE) {
1526            log_err("didn't expect lenient value after set: %d\n", isLenient);
1527        }
1528    }
1529
1530    {
1531        double val2;
1532        double val = unum_getDoubleAttribute(fmt, UNUM_LENIENT_PARSE);
1533        if (val != -1) {
1534            log_err("didn't expect double attribute\n");
1535        }
1536        val = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT);
1537        if ((val == -1) == isDecimal) {
1538            log_err("didn't expect -1 rounding increment\n");
1539        }
1540        unum_setDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT, val+.5);
1541        val2 = unum_getDoubleAttribute(fmt, UNUM_ROUNDING_INCREMENT);
1542        if (isDecimal && (val2 - val != .5)) {
1543            log_err("set rounding increment had no effect on decimal format");
1544        }
1545    }
1546
1547    {
1548        UErrorCode status = U_ZERO_ERROR;
1549        int len = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status);
1550        if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) {
1551            log_err("got unexpected error for get default ruleset: '%s'\n", u_errorName(status));
1552        }
1553        if (U_SUCCESS(status)) {
1554            u_austrcpy(temp, buffer);
1555            log_verbose("default ruleset: '%s'\n", temp);
1556        }
1557
1558        status = U_ZERO_ERROR;
1559        len = unum_getTextAttribute(fmt, UNUM_PUBLIC_RULESETS, buffer, BUFSIZE, &status);
1560        if (isDecimal ? (status != U_UNSUPPORTED_ERROR) : U_FAILURE(status)) {
1561            log_err("got unexpected error for get public rulesets: '%s'\n", u_errorName(status));
1562        }
1563        if (U_SUCCESS(status)) {
1564            u_austrcpy(temp, buffer);
1565            log_verbose("public rulesets: '%s'\n", temp);
1566
1567            /* set the default ruleset to the first one found, and retry */
1568
1569            if (len > 0) {
1570                for (i = 0; i < len && temp[i] != ';'; ++i){};
1571                if (i < len) {
1572                    buffer[i] = 0;
1573                    unum_setTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, -1, &status);
1574                    if (U_FAILURE(status)) {
1575                        log_err("unexpected error setting default ruleset: '%s'\n", u_errorName(status));
1576                    } else {
1577                        int len2 = unum_getTextAttribute(fmt, UNUM_DEFAULT_RULESET, buffer, BUFSIZE, &status);
1578                        if (U_FAILURE(status)) {
1579                            log_err("could not fetch default ruleset: '%s'\n", u_errorName(status));
1580                        } else if (len2 != i) {
1581                            u_austrcpy(temp, buffer);
1582                            log_err("unexpected ruleset len: %d ex: %d val: %s\n", len2, i, temp);
1583                        } else {
1584                            for (i = 0; i < sizeof(vals)/sizeof(vals[0]); ++i) {
1585                                status = U_ZERO_ERROR;
1586                                unum_formatDouble(fmt, vals[i], buffer, BUFSIZE, NULL, &status);
1587                                if (U_FAILURE(status)) {
1588                                    log_err("failed to format: %g, returned %s\n", vals[i], u_errorName(status));
1589                                } else {
1590                                    u_austrcpy(temp, buffer);
1591                                    log_verbose("formatting %g returned '%s'\n", vals[i], temp);
1592                                }
1593                            }
1594                        }
1595                    }
1596                }
1597            }
1598        }
1599    }
1600
1601    {
1602        UErrorCode status = U_ZERO_ERROR;
1603        unum_toPattern(fmt, FALSE, buffer, BUFSIZE, &status);
1604        if (U_SUCCESS(status)) {
1605            u_austrcpy(temp, buffer);
1606            log_verbose("pattern: '%s'\n", temp);
1607        } else if (status != U_BUFFER_OVERFLOW_ERROR) {
1608            log_err("toPattern failed unexpectedly: %s\n", u_errorName(status));
1609        } else {
1610            log_verbose("pattern too long to display\n");
1611        }
1612    }
1613
1614    {
1615        UErrorCode status = U_ZERO_ERROR;
1616        int len = unum_getSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, BUFSIZE, &status);
1617        if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
1618            log_err("unexpected error getting symbol: '%s'\n", u_errorName(status));
1619        }
1620
1621        unum_setSymbol(fmt, UNUM_CURRENCY_SYMBOL, buffer, len, &status);
1622        if (isDecimal ? U_FAILURE(status) : (status != U_UNSUPPORTED_ERROR)) {
1623            log_err("unexpected error setting symbol: '%s'\n", u_errorName(status));
1624        }
1625    }
1626}
1627
1628static void TestNonExistentCurrency() {
1629    UNumberFormat *format;
1630    UErrorCode status = U_ZERO_ERROR;
1631    UChar currencySymbol[8];
1632    static const UChar QQQ[] = {0x51, 0x51, 0x51, 0};
1633
1634    /* Get a non-existent currency and make sure it returns the correct currency code. */
1635    format = unum_open(UNUM_CURRENCY, NULL, 0, "th_TH@currency=QQQ", NULL, &status);
1636    if (format == NULL || U_FAILURE(status)) {
1637        log_data_err("unum_open did not return expected result for non-existent requested currency: '%s' (Are you missing data?)\n", u_errorName(status));
1638    }
1639    else {
1640        unum_getSymbol(format,
1641                UNUM_CURRENCY_SYMBOL,
1642                currencySymbol,
1643                sizeof(currencySymbol)/sizeof(currencySymbol[0]),
1644                &status);
1645        if (u_strcmp(currencySymbol, QQQ) != 0) {
1646            log_err("unum_open set the currency to QQQ\n");
1647        }
1648    }
1649    unum_close(format);
1650}
1651
1652static void TestRBNFFormat() {
1653    UErrorCode status;
1654    UParseError perr;
1655    UChar pat[1024];
1656    UChar tempUChars[512];
1657    UNumberFormat *formats[5];
1658    int COUNT = sizeof(formats)/sizeof(formats[0]);
1659    int i;
1660
1661    for (i = 0; i < COUNT; ++i) {
1662        formats[i] = 0;
1663    }
1664
1665    /* instantiation */
1666    status = U_ZERO_ERROR;
1667    u_uastrcpy(pat, "#,##0.0#;(#,##0.0#)");
1668    formats[0] = unum_open(UNUM_PATTERN_DECIMAL, pat, -1, "en_US", &perr, &status);
1669    if (U_FAILURE(status)) {
1670        log_err_status(status, "unable to open decimal pattern -> %s\n", u_errorName(status));
1671        return;
1672    }
1673
1674    status = U_ZERO_ERROR;
1675    formats[1] = unum_open(UNUM_SPELLOUT, NULL, 0, "en_US", &perr, &status);
1676    if (U_FAILURE(status)) {
1677        log_err_status(status, "unable to open spellout -> %s\n", u_errorName(status));
1678        return;
1679    }
1680
1681    status = U_ZERO_ERROR;
1682    formats[2] = unum_open(UNUM_ORDINAL, NULL, 0, "en_US", &perr, &status);
1683    if (U_FAILURE(status)) {
1684        log_err_status(status, "unable to open ordinal -> %s\n", u_errorName(status));
1685        return;
1686    }
1687
1688    status = U_ZERO_ERROR;
1689    formats[3] = unum_open(UNUM_DURATION, NULL, 0, "en_US", &perr, &status);
1690    if (U_FAILURE(status)) {
1691        log_err_status(status, "unable to open duration %s\n", u_errorName(status));
1692        return;
1693    }
1694
1695    status = U_ZERO_ERROR;
1696    u_uastrcpy(pat,
1697        "%standard:\n"
1698        "-x: minus >>;\n"
1699        "x.x: << point >>;\n"
1700        "zero; one; two; three; four; five; six; seven; eight; nine;\n"
1701        "ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"
1702        "seventeen; eighteen; nineteen;\n"
1703        "20: twenty[->>];\n"
1704        "30: thirty[->>];\n"
1705        "40: forty[->>];\n"
1706        "50: fifty[->>];\n"
1707        "60: sixty[->>];\n"
1708        "70: seventy[->>];\n"
1709        "80: eighty[->>];\n"
1710        "90: ninety[->>];\n"
1711        "100: =#,##0=;\n");
1712    u_uastrcpy(tempUChars,
1713        "%simple:\n"
1714        "=%standard=;\n"
1715        "20: twenty[ and change];\n"
1716        "30: thirty[ and change];\n"
1717        "40: forty[ and change];\n"
1718        "50: fifty[ and change];\n"
1719        "60: sixty[ and change];\n"
1720        "70: seventy[ and change];\n"
1721        "80: eighty[ and change];\n"
1722        "90: ninety[ and change];\n"
1723        "100: =#,##0=;\n"
1724        "%bogus:\n"
1725        "0.x: tiny;\n"
1726        "x.x: << point something;\n"
1727        "=%standard=;\n"
1728        "20: some reasonable number;\n"
1729        "100: some substantial number;\n"
1730        "100,000,000: some huge number;\n");
1731    /* This is to get around some compiler warnings about char * string length. */
1732    u_strcat(pat, tempUChars);
1733    formats[4] = unum_open(UNUM_PATTERN_RULEBASED, pat, -1, "en_US", &perr, &status);
1734    if (U_FAILURE(status)) {
1735        log_err_status(status, "unable to open rulebased pattern -> %s\n", u_errorName(status));
1736    }
1737    if (U_FAILURE(status)) {
1738        log_err_status(status, "Something failed with %s\n", u_errorName(status));
1739        return;
1740    }
1741
1742    for (i = 0; i < COUNT; ++i) {
1743        log_verbose("\n\ntesting format %d\n", i);
1744        test_fmt(formats[i], (UBool)(i == 0));
1745    }
1746
1747    #define FORMAT_BUF_CAPACITY 64
1748    {
1749        UChar fmtbuf[FORMAT_BUF_CAPACITY];
1750        int32_t len;
1751        double nanvalue = uprv_getNaN();
1752        status = U_ZERO_ERROR;
1753        len = unum_formatDouble(formats[1], nanvalue, fmtbuf, FORMAT_BUF_CAPACITY, NULL, &status);
1754        if (U_FAILURE(status)) {
1755            log_err_status(status, "unum_formatDouble NAN failed with %s\n", u_errorName(status));
1756        } else {
1757            UChar nansym[] = { 0x4E, 0x61, 0x4E, 0 }; /* NaN */
1758            if ( len != 3 || u_strcmp(fmtbuf, nansym) != 0 ) {
1759                log_err("unum_formatDouble NAN produced wrong answer for en_US\n");
1760            }
1761        }
1762    }
1763
1764    for (i = 0; i < COUNT; ++i) {
1765        unum_close(formats[i]);
1766    }
1767}
1768
1769static void TestCurrencyRegression(void) {
1770/*
1771 I've found a case where unum_parseDoubleCurrency is not doing what I
1772expect.  The value I pass in is $1234567890q123460000.00 and this
1773returns with a status of zero error & a parse pos of 22 (I would
1774expect a parse error at position 11).
1775
1776I stepped into DecimalFormat::subparse() and it looks like it parses
1777the first 10 digits and then stops parsing at the q but doesn't set an
1778error. Then later in DecimalFormat::parse() the value gets crammed
1779into a long (which greatly truncates the value).
1780
1781This is very problematic for me 'cause I try to remove chars that are
1782invalid but this allows my users to enter bad chars and truncates
1783their data!
1784*/
1785
1786    UChar buf[1024];
1787    UChar currency[8];
1788    char acurrency[16];
1789    double d;
1790    UNumberFormat *cur;
1791    int32_t pos;
1792    UErrorCode status  = U_ZERO_ERROR;
1793    const int32_t expected = 11;
1794
1795    currency[0]=0;
1796    u_uastrcpy(buf, "$1234567890q643210000.00");
1797    cur = unum_open(UNUM_CURRENCY, NULL,0,"en_US", NULL, &status);
1798
1799    if(U_FAILURE(status)) {
1800        log_data_err("unum_open failed: %s (Are you missing data?)\n", u_errorName(status));
1801        return;
1802    }
1803
1804    status = U_ZERO_ERROR; /* so we can test it later. */
1805    pos = 0;
1806
1807    d = unum_parseDoubleCurrency(cur,
1808                         buf,
1809                         -1,
1810                         &pos, /* 0 = start */
1811                         currency,
1812                         &status);
1813
1814    u_austrcpy(acurrency, currency);
1815
1816    if(U_FAILURE(status) || (pos != expected)) {
1817        log_err("unum_parseDoubleCurrency should have failed with pos %d, but gave: value %.9f, err %s, pos=%d, currency [%s]\n",
1818            expected, d, u_errorName(status), pos, acurrency);
1819    } else {
1820        log_verbose("unum_parseDoubleCurrency failed, value %.9f err %s, pos %d, currency [%s]\n", d, u_errorName(status), pos, acurrency);
1821    }
1822
1823    unum_close(cur);
1824}
1825
1826static void TestTextAttributeCrash(void) {
1827    UChar ubuffer[64] = {0x0049,0x004E,0x0052,0};
1828    static const UChar expectedNeg[] = {0x0049,0x004E,0x0052,0x0031,0x0032,0x0033,0x0034,0x002E,0x0035,0};
1829    static const UChar expectedPos[] = {0x0031,0x0032,0x0033,0x0034,0x002E,0x0035,0};
1830    int32_t used;
1831    UErrorCode status = U_ZERO_ERROR;
1832    UNumberFormat *nf = unum_open(UNUM_CURRENCY, NULL, 0, "en_US", NULL, &status);
1833    if (U_FAILURE(status)) {
1834        log_data_err("FAILED 1 -> %s (Are you missing data?)\n", u_errorName(status));
1835        return;
1836    }
1837    unum_setTextAttribute(nf, UNUM_CURRENCY_CODE, ubuffer, 3, &status);
1838    /*
1839     * the usual negative prefix and suffix seem to be '($' and ')' at this point
1840     * also crashes if UNUM_NEGATIVE_SUFFIX is substituted for UNUM_NEGATIVE_PREFIX here
1841     */
1842    used = unum_getTextAttribute(nf, UNUM_NEGATIVE_PREFIX, ubuffer, 64, &status);
1843    unum_setTextAttribute(nf, UNUM_NEGATIVE_PREFIX, ubuffer, used, &status);
1844    if (U_FAILURE(status)) {
1845        log_err("FAILED 2\n"); exit(1);
1846    }
1847    log_verbose("attempting to format...\n");
1848    used = unum_formatDouble(nf, -1234.5, ubuffer, 64, NULL, &status);
1849    if (U_FAILURE(status) || 64 < used) {
1850        log_err("Failed formatting %s\n", u_errorName(status));
1851        return;
1852    }
1853    if (u_strcmp(expectedNeg, ubuffer) == 0) {
1854        log_err("Didn't get expected negative result\n");
1855    }
1856    used = unum_formatDouble(nf, 1234.5, ubuffer, 64, NULL, &status);
1857    if (U_FAILURE(status) || 64 < used) {
1858        log_err("Failed formatting %s\n", u_errorName(status));
1859        return;
1860    }
1861    if (u_strcmp(expectedPos, ubuffer) == 0) {
1862        log_err("Didn't get expected positive result\n");
1863    }
1864    unum_close(nf);
1865}
1866
1867static void TestNBSPPatternRtNum(const char *testcase, int line, UNumberFormat *nf, double myNumber) {
1868    UErrorCode status = U_ZERO_ERROR;
1869    UChar myString[20];
1870    char tmpbuf[200];
1871    double aNumber = -1.0;
1872    unum_formatDouble(nf, myNumber, myString, 20, NULL, &status);
1873    log_verbose("%s:%d: formatted %.2f into %s\n", testcase, line, myNumber, u_austrcpy(tmpbuf, myString));
1874    if(U_FAILURE(status)) {
1875      log_err("%s:%d: failed format of %.2g with %s\n", testcase, line, myNumber, u_errorName(status));
1876        return;
1877    }
1878    aNumber = unum_parse(nf, myString, -1, NULL, &status);
1879    if(U_FAILURE(status)) {
1880      log_err("%s:%d: failed parse with %s\n", testcase, line, u_errorName(status));
1881        return;
1882    }
1883    if(uprv_fabs(aNumber-myNumber)>.001) {
1884      log_err("FAIL: %s:%d formatted %.2f, parsed into %.2f\n", testcase, line, myNumber, aNumber);
1885    } else {
1886      log_verbose("PASS: %s:%d formatted %.2f, parsed into %.2f\n", testcase, line, myNumber, aNumber);
1887    }
1888}
1889
1890static void TestNBSPPatternRT(const char *testcase, UNumberFormat *nf) {
1891  TestNBSPPatternRtNum(testcase, __LINE__, nf, 12345.);
1892  TestNBSPPatternRtNum(testcase, __LINE__, nf, -12345.);
1893}
1894
1895static void TestNBSPInPattern(void) {
1896    UErrorCode status = U_ZERO_ERROR;
1897    UNumberFormat* nf = NULL;
1898    const char *testcase;
1899
1900
1901    testcase="ar_AE UNUM_CURRENCY";
1902    nf  = unum_open(UNUM_CURRENCY, NULL, -1, "ar_AE", NULL, &status);
1903    if(U_FAILURE(status) || nf == NULL) {
1904      log_data_err("%s:%d: %s: unum_open failed with %s (Are you missing data?)\n", __FILE__, __LINE__, testcase, u_errorName(status));
1905        return;
1906    }
1907    TestNBSPPatternRT(testcase, nf);
1908
1909    /* if we don't have CLDR 1.6 data, bring out the problem anyways */
1910    {
1911#define SPECIAL_PATTERN "\\u00A4\\u00A4'\\u062f.\\u0625.\\u200f\\u00a0'###0.00"
1912        UChar pat[200];
1913        testcase = "ar_AE special pattern: " SPECIAL_PATTERN;
1914        u_unescape(SPECIAL_PATTERN, pat, sizeof(pat)/sizeof(pat[0]));
1915        unum_applyPattern(nf, FALSE, pat, -1, NULL, &status);
1916        if(U_FAILURE(status)) {
1917            log_err("%s: unum_applyPattern failed with %s\n", testcase, u_errorName(status));
1918        } else {
1919            TestNBSPPatternRT(testcase, nf);
1920        }
1921#undef SPECIAL_PATTERN
1922    }
1923    unum_close(nf); status = U_ZERO_ERROR;
1924
1925    testcase="ar_AE UNUM_DECIMAL";
1926    nf  = unum_open(UNUM_DECIMAL, NULL, -1, "ar_AE", NULL, &status);
1927    if(U_FAILURE(status)) {
1928        log_err("%s: unum_open failed with %s\n", testcase, u_errorName(status));
1929    }
1930    TestNBSPPatternRT(testcase, nf);
1931    unum_close(nf); status = U_ZERO_ERROR;
1932
1933    testcase="ar_AE UNUM_PERCENT";
1934    nf  = unum_open(UNUM_PERCENT, NULL, -1, "ar_AE", NULL, &status);
1935    if(U_FAILURE(status)) {
1936        log_err("%s: unum_open failed with %s\n", testcase, u_errorName(status));
1937    }
1938    TestNBSPPatternRT(testcase, nf);
1939    unum_close(nf); status = U_ZERO_ERROR;
1940
1941
1942
1943}
1944static void TestCloneWithRBNF(void) {
1945    UChar pattern[1024];
1946    UChar pat2[512];
1947    UErrorCode status = U_ZERO_ERROR;
1948    UChar buffer[256];
1949    UChar buffer_cloned[256];
1950    char temp1[256];
1951    char temp2[256];
1952    UNumberFormat *pform_cloned;
1953    UNumberFormat *pform;
1954
1955    u_uastrcpy(pattern,
1956        "%main:\n"
1957        "0.x: >%%millis-only>;\n"
1958        "x.0: <%%duration<;\n"
1959        "x.x: <%%durationwithmillis<>%%millis-added>;\n"
1960        "-x: ->>;%%millis-only:\n"
1961        "1000: 00:00.<%%millis<;\n"
1962        "%%millis-added:\n"
1963        "1000: .<%%millis<;\n"
1964        "%%millis:\n"
1965        "0: =000=;\n"
1966        "%%duration:\n"
1967        "0: =%%seconds-only=;\n"
1968        "60: =%%min-sec=;\n"
1969        "3600: =%%hr-min-sec=;\n"
1970        "86400/86400: <%%ddaayyss<[, >>];\n"
1971        "%%durationwithmillis:\n"
1972        "0: =%%seconds-only=;\n"
1973        "60: =%%min-sec=;\n"
1974        "3600: =%%hr-min-sec=;\n"
1975        "86400/86400: <%%ddaayyss<, >>;\n");
1976    u_uastrcpy(pat2,
1977        "%%seconds-only:\n"
1978        "0: 0:00:=00=;\n"
1979        "%%min-sec:\n"
1980        "0: :=00=;\n"
1981        "0/60: 0:<00<>>;\n"
1982        "%%hr-min-sec:\n"
1983        "0: :=00=;\n"
1984        "60/60: <00<>>;\n"
1985        "3600/60: <0<:>>>;\n"
1986        "%%ddaayyss:\n"
1987        "0 days;\n"
1988        "1 day;\n"
1989        "=0= days;");
1990
1991    /* This is to get around some compiler warnings about char * string length. */
1992    u_strcat(pattern, pat2);
1993
1994    pform = unum_open(UNUM_PATTERN_RULEBASED, pattern, -1, "en_US", NULL, &status);
1995    unum_formatDouble(pform, 3600, buffer, 256, NULL, &status);
1996
1997    pform_cloned = unum_clone(pform,&status);
1998    unum_formatDouble(pform_cloned, 3600, buffer_cloned, 256, NULL, &status);
1999
2000    unum_close(pform);
2001    unum_close(pform_cloned);
2002
2003    if (u_strcmp(buffer,buffer_cloned)) {
2004        log_data_err("Result from cloned formatter not identical to the original. Original: %s Cloned: %s - (Are you missing data?)",u_austrcpy(temp1, buffer),u_austrcpy(temp2,buffer_cloned));
2005    }
2006}
2007
2008
2009static void TestNoExponent(void) {
2010    UErrorCode status = U_ZERO_ERROR;
2011    UChar str[100];
2012    const char *cstr;
2013    UNumberFormat *fmt;
2014    int32_t pos;
2015    int32_t expect = 0;
2016    int32_t num;
2017
2018    fmt = unum_open(UNUM_DECIMAL, NULL, -1, "en_US", NULL, &status);
2019
2020    if(U_FAILURE(status) || fmt == NULL) {
2021        log_data_err("%s:%d: unum_open failed with %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status));
2022        return;
2023    }
2024
2025    cstr = "10E6";
2026    u_uastrcpy(str, cstr);
2027    expect = 10000000;
2028    pos = 0;
2029    num = unum_parse(fmt, str, -1, &pos, &status);
2030    ASSERT_TRUE(pos==4);
2031    if(U_FAILURE(status)) {
2032        log_data_err("%s:%d: unum_parse failed with %s for %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status), cstr);
2033    } else if(expect!=num) {
2034        log_data_err("%s:%d: unum_parse failed, got %d expected %d for '%s'(Are you missing data?)\n", __FILE__, __LINE__, num, expect, cstr);
2035    } else {
2036        log_verbose("%s:%d: unum_parse returned %d for '%s'\n", __FILE__, __LINE__, num, cstr);
2037    }
2038
2039    ASSERT_TRUE(unum_getAttribute(fmt, UNUM_PARSE_NO_EXPONENT)==0);
2040
2041    unum_setAttribute(fmt, UNUM_PARSE_NO_EXPONENT, 1); /* no error code */
2042    log_verbose("set UNUM_PARSE_NO_EXPONENT\n");
2043
2044    ASSERT_TRUE(unum_getAttribute(fmt, UNUM_PARSE_NO_EXPONENT)==1);
2045
2046    pos = 0;
2047    expect=10;
2048    num = unum_parse(fmt, str, -1, &pos, &status);
2049    if(num==10000000) {
2050        log_err("%s:%d: FAIL: unum_parse should have returned 10, not 10000000 on %s after UNUM_PARSE_NO_EXPONENT\n", __FILE__, __LINE__, cstr);
2051    } else if(num==expect) {
2052        log_verbose("%s:%d: unum_parse gave %d for %s - good.\n", __FILE__, __LINE__, num, cstr);
2053    }
2054    ASSERT_TRUE(pos==2);
2055
2056    status = U_ZERO_ERROR;
2057
2058    unum_close(fmt);
2059
2060    /* ok, now try scientific */
2061    fmt = unum_open(UNUM_SCIENTIFIC, NULL, -1, "en_US", NULL, &status);
2062    assertSuccess("unum_open(UNUM_SCIENTIFIC, ...)", &status);
2063
2064    ASSERT_TRUE(unum_getAttribute(fmt, UNUM_PARSE_NO_EXPONENT)==0);
2065
2066    cstr = "10E6";
2067    u_uastrcpy(str, cstr);
2068    expect = 10000000;
2069    pos = 0;
2070    num = unum_parse(fmt, str, -1, &pos, &status);
2071    ASSERT_TRUE(pos==4);
2072    if(U_FAILURE(status)) {
2073        log_data_err("%s:%d: unum_parse failed with %s for %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status), cstr);
2074    } else if(expect!=num) {
2075        log_data_err("%s:%d: unum_parse failed, got %d expected %d for '%s'(Are you missing data?)\n", __FILE__, __LINE__, num, expect, cstr);
2076    } else {
2077        log_verbose("%s:%d: unum_parse returned %d for '%s'\n", __FILE__, __LINE__, num, cstr);
2078    }
2079
2080    unum_setAttribute(fmt, UNUM_PARSE_NO_EXPONENT, 1); /* no error code */
2081    log_verbose("set UNUM_PARSE_NO_EXPONENT\n");
2082
2083    ASSERT_TRUE(unum_getAttribute(fmt, UNUM_PARSE_NO_EXPONENT)==1);
2084
2085
2086    cstr = "10E6";
2087    u_uastrcpy(str, cstr);
2088    expect = 10000000;
2089    pos = 0;
2090    num = unum_parse(fmt, str, -1, &pos, &status);
2091    ASSERT_TRUE(pos==4);
2092    if(U_FAILURE(status)) {
2093        log_data_err("%s:%d: unum_parse failed with %s for %s (Are you missing data?)\n", __FILE__, __LINE__, u_errorName(status), cstr);
2094    } else if(expect!=num) {
2095        log_data_err("%s:%d: unum_parse failed, got %d expected %d for '%s'(Are you missing data?)\n", __FILE__, __LINE__, num, expect, cstr);
2096    } else {
2097        log_verbose("%s:%d: unum_parse returned %d for '%s'\n", __FILE__, __LINE__, num, cstr);
2098    }
2099
2100    unum_close(fmt);
2101}
2102
2103static void TestMaxInt(void) {
2104    UErrorCode status = U_ZERO_ERROR;
2105    UChar pattern_hash[] = { 0x23, 0x00 }; /* "#" */
2106    UChar result1[1024] = { 0 }, result2[1024] = { 0 };
2107    int32_t len1, len2;
2108    UChar expect[] = { 0x0039, 0x0037, 0 };
2109    UNumberFormat *fmt = unum_open(
2110                  UNUM_PATTERN_DECIMAL,      /* style         */
2111                  &pattern_hash[0],          /* pattern       */
2112                  u_strlen(pattern_hash),    /* patternLength */
2113                  0,
2114                  0,                         /* parseErr      */
2115                  &status);
2116    if(U_FAILURE(status) || fmt == NULL) {
2117        log_data_err("%s:%d: %s: unum_open failed with %s (Are you missing data?)\n", __FILE__, __LINE__, "TestMaxInt", u_errorName(status));
2118        return;
2119    }
2120
2121    unum_setAttribute(fmt, UNUM_MAX_INTEGER_DIGITS, 2);
2122
2123    status = U_ZERO_ERROR;
2124    /* #1 */
2125    len1 = unum_formatInt64(fmt, 1997, result1, 1024, NULL, &status);
2126    result1[len1]=0;
2127    if(U_FAILURE(status) || u_strcmp(expect, result1)) {
2128        log_err("unum_formatInt64 Expected %s but got %s status %s\n", austrdup(expect), austrdup(result1), u_errorName(status));
2129    }
2130
2131    status = U_ZERO_ERROR;
2132    /* #2 */
2133    len2 = unum_formatDouble(fmt, 1997.0, result2, 1024, NULL, &status);
2134    result2[len2]=0;
2135    if(U_FAILURE(status) || u_strcmp(expect, result2)) {
2136        log_err("unum_formatDouble Expected %s but got %s status %s\n", austrdup(expect), austrdup(result2), u_errorName(status));
2137    }
2138
2139
2140
2141    /* test UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS */
2142    ASSERT_TRUE(unum_getAttribute(fmt, UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)==0);
2143
2144    unum_setAttribute(fmt, UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS, 1);
2145    /* test UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS */
2146    ASSERT_TRUE(unum_getAttribute(fmt, UNUM_FORMAT_FAIL_IF_MORE_THAN_MAX_DIGITS)==1);
2147
2148    status = U_ZERO_ERROR;
2149    /* max int digits still '2' */
2150    len1 = unum_formatInt64(fmt, 1997, result1, 1024, NULL, &status);
2151    ASSERT_TRUE(status==U_ILLEGAL_ARGUMENT_ERROR);
2152    status = U_ZERO_ERROR;
2153
2154    /* But, formatting 97->'97' works fine. */
2155
2156    /* #1 */
2157    len1 = unum_formatInt64(fmt, 97, result1, 1024, NULL, &status);
2158    result1[len1]=0;
2159    if(U_FAILURE(status) || u_strcmp(expect, result1)) {
2160        log_err("unum_formatInt64 Expected %s but got %s status %s\n", austrdup(expect), austrdup(result1), u_errorName(status));
2161    }
2162
2163    status = U_ZERO_ERROR;
2164    /* #2 */
2165    len2 = unum_formatDouble(fmt, 97.0, result2, 1024, NULL, &status);
2166    result2[len2]=0;
2167    if(U_FAILURE(status) || u_strcmp(expect, result2)) {
2168        log_err("unum_formatDouble Expected %s but got %s status %s\n", austrdup(expect), austrdup(result2), u_errorName(status));
2169    }
2170
2171
2172    unum_close(fmt);
2173}
2174
2175#endif /* #if !UCONFIG_NO_FORMATTING */
2176