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