Home | History | Annotate | Download | only in cintltst
      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 
     39 static 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 
     47 void addNumForTest(TestNode** root);
     48 static void TestTextAttributeCrash(void);
     49 static void TestNBSPInPattern(void);
     50 static void TestInt64Parse(void);
     51 static void TestParseCurrency(void);
     52 static void TestMaxInt(void);
     53 static void TestNoExponent(void);
     54 
     55 #define TESTCASE(x) addTest(root, &x, "tsformat/cnumtst/" #x)
     56 
     57 void 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 
     80 static 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 */
    123 static 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 
    402 free(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 
    450 free(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");
    484 free(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 
    511 free(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 
    587 free(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 
    949 static 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 
    971 static const UChar dollars2Sym[] = { 0x24,0x32,0x2E,0x30,0x30,0 }; /* $2.00 */
    972 static const UChar dollars4Sym[] = { 0x24,0x34,0 }; /* $4 */
    973 static const UChar dollars9Sym[] = { 0x39,0xA0,0x24,0 }; /* 9 $ */
    974 static const UChar pounds3Sym[]  = { 0xA3,0x33,0x2E,0x30,0x30,0 }; /* [POUND]3.00 */
    975 static const UChar pounds5Sym[]  = { 0xA3,0x35,0 }; /* [POUND]5 */
    976 static const UChar pounds7Sym[]  = { 0x37,0xA0,0xA3,0 }; /* 7 [POUND] */
    977 static const UChar euros4Sym[]   = { 0x34,0x2C,0x30,0x30,0xA0,0x20AC,0 }; /* 4,00 [EURO] */
    978 static const UChar euros6Sym[]   = { 0x36,0xA0,0x20AC,0 }; /* 6 [EURO] */
    979 static const UChar euros8Sym[]   = { 0x20AC,0x38,0 }; /* [EURO]8 */
    980 static const UChar dollars4PluEn[] = { 0x34,0x20,0x55,0x53,0x20,0x64,0x6F,0x6C,0x6C,0x61,0x72,0x73,0 }; /* 4 US dollars*/
    981 static 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 */
    982 static const UChar euros8PluEn[]   = { 0x38,0x20,0x65,0x75,0x72,0x6F,0x73,0 }; /* 8 euros*/
    983 static const UChar euros6PluFr[]   = { 0x36,0x20,0x65,0x75,0x72,0x6F,0x73,0 }; /* 6 euros*/
    984 
    985 typedef 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 
    999 static 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 
   1025 static 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 
   1101 typedef 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 
   1111 static const UChar ustr_en0[]   = {0x7A, 0x65, 0x72, 0x6F, 0}; /* zero */
   1112 static const UChar ustr_123[]   = {0x31, 0x32, 0x33, 0};       /* 123 */
   1113 static 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 */
   1116 static 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 */
   1118 static const UChar ustr_ja123[] = {0x767e, 0x4e8c, 0x5341, 0x4e09, 0};     /* kanji 100(+)2(*)10(+)3 */
   1119 
   1120 static 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 
   1138 static 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 
   1160 static 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 
   1202 static 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 
   1239 static 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");
   1299 free(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");
   1343 free(result);
   1344         }
   1345     }
   1346 
   1347     unum_close(pattern);
   1348 }
   1349 
   1350 static UBool
   1351 withinErr(double a, double b, double err) {
   1352     return uprv_fabs(a - b) < uprv_fabs(a * err);
   1353 }
   1354 
   1355 static 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 
   1485 static 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 
   1628 static 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 
   1652 static 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 
   1769 static void TestCurrencyRegression(void) {
   1770 /*
   1771  I've found a case where unum_parseDoubleCurrency is not doing what I
   1772 expect.  The value I pass in is $1234567890q123460000.00 and this
   1773 returns with a status of zero error & a parse pos of 22 (I would
   1774 expect a parse error at position 11).
   1775 
   1776 I stepped into DecimalFormat::subparse() and it looks like it parses
   1777 the first 10 digits and then stops parsing at the q but doesn't set an
   1778 error. Then later in DecimalFormat::parse() the value gets crammed
   1779 into a long (which greatly truncates the value).
   1780 
   1781 This is very problematic for me 'cause I try to remove chars that are
   1782 invalid but this allows my users to enter bad chars and truncates
   1783 their 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 
   1826 static 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 
   1867 static 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 
   1890 static void TestNBSPPatternRT(const char *testcase, UNumberFormat *nf) {
   1891   TestNBSPPatternRtNum(testcase, __LINE__, nf, 12345.);
   1892   TestNBSPPatternRtNum(testcase, __LINE__, nf, -12345.);
   1893 }
   1894 
   1895 static 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 }
   1944 static 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 
   2009 static 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 
   2103 static 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