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