"Fossies" - the Fresh Open Source Software Archive

Member "icu/source/test/cintltst/unumberformattertst.c" (22 Apr 2020, 13110 Bytes) of package /linux/misc/icu4c-67_1-src.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes reports for "unumberformattertst.c": 67rc_vs_67_1 or 66_1_vs_67_1.

    1 // © 2018 and later: Unicode, Inc. and others.
    2 // License & terms of use: http://www.unicode.org/copyright.html
    3 
    4 #include "unicode/utypes.h"
    5 
    6 #if !UCONFIG_NO_FORMATTING
    7 
    8 // Allow implicit conversion from char16_t* to UnicodeString for this file:
    9 // Helpful in toString methods and elsewhere.
   10 #define UNISTR_FROM_STRING_EXPLICIT
   11 
   12 #include <stdio.h>
   13 #include "unicode/unumberformatter.h"
   14 #include "unicode/umisc.h"
   15 #include "unicode/unum.h"
   16 #include "unicode/ustring.h"
   17 #include "cformtst.h"
   18 #include "cintltst.h"
   19 #include "cmemory.h"
   20 
   21 static void TestSkeletonFormatToString(void);
   22 
   23 static void TestSkeletonFormatToFields(void);
   24 
   25 static void TestExampleCode(void);
   26 
   27 static void TestFormattedValue(void);
   28 
   29 static void TestSkeletonParseError(void);
   30 
   31 static void TestPerUnitInArabic(void);
   32 
   33 void addUNumberFormatterTest(TestNode** root);
   34 
   35 #define TESTCASE(x) addTest(root, &x, "tsformat/unumberformatter/" #x)
   36 
   37 void addUNumberFormatterTest(TestNode** root) {
   38     TESTCASE(TestSkeletonFormatToString);
   39     TESTCASE(TestSkeletonFormatToFields);
   40     TESTCASE(TestExampleCode);
   41     TESTCASE(TestFormattedValue);
   42     TESTCASE(TestSkeletonParseError);
   43     TESTCASE(TestPerUnitInArabic);
   44 }
   45 
   46 
   47 #define CAPACITY 30
   48 
   49 static void TestSkeletonFormatToString() {
   50     UErrorCode ec = U_ZERO_ERROR;
   51     UChar buffer[CAPACITY];
   52     UFormattedNumber* result = NULL;
   53 
   54     // setup:
   55     UNumberFormatter* f = unumf_openForSkeletonAndLocale(
   56                               u"precision-integer currency/USD sign-accounting", -1, "en", &ec);
   57     assertSuccessCheck("Should create without error", &ec, TRUE);
   58     result = unumf_openResult(&ec);
   59     assertSuccess("Should create result without error", &ec);
   60 
   61     // int64 test:
   62     unumf_formatInt(f, -444444, result, &ec);
   63     // Missing data will give a U_MISSING_RESOURCE_ERROR here.
   64     if (assertSuccessCheck("Should format integer without error", &ec, TRUE)) {
   65         unumf_resultToString(result, buffer, CAPACITY, &ec);
   66         assertSuccess("Should print string to buffer without error", &ec);
   67         assertUEquals("Should produce expected string result", u"($444,444)", buffer);
   68 
   69         // double test:
   70         unumf_formatDouble(f, -5142.3, result, &ec);
   71         assertSuccess("Should format double without error", &ec);
   72         unumf_resultToString(result, buffer, CAPACITY, &ec);
   73         assertSuccess("Should print string to buffer without error", &ec);
   74         assertUEquals("Should produce expected string result", u"($5,142)", buffer);
   75 
   76         // decnumber test:
   77         unumf_formatDecimal(f, "9.876E2", -1, result, &ec);
   78         assertSuccess("Should format decimal without error", &ec);
   79         unumf_resultToString(result, buffer, CAPACITY, &ec);
   80         assertSuccess("Should print string to buffer without error", &ec);
   81         assertUEquals("Should produce expected string result", u"$988", buffer);
   82     }
   83 
   84     // cleanup:
   85     unumf_closeResult(result);
   86     unumf_close(f);
   87 }
   88 
   89 
   90 static void TestSkeletonFormatToFields() {
   91     UErrorCode ec = U_ZERO_ERROR;
   92     UFieldPositionIterator* ufpositer = NULL;
   93 
   94     // setup:
   95     UNumberFormatter* uformatter = unumf_openForSkeletonAndLocale(
   96             u".00 measure-unit/length-meter sign-always", -1, "en", &ec);
   97     assertSuccessCheck("Should create without error", &ec, TRUE);
   98     UFormattedNumber* uresult = unumf_openResult(&ec);
   99     assertSuccess("Should create result without error", &ec);
  100     unumf_formatInt(uformatter, 9876543210L, uresult, &ec); // "+9,876,543,210.00 m"
  101     if (assertSuccessCheck("unumf_formatInt() failed", &ec, TRUE)) {
  102 
  103         // field position test:
  104         UFieldPosition ufpos = {UNUM_DECIMAL_SEPARATOR_FIELD, 0, 0};
  105         unumf_resultNextFieldPosition(uresult, &ufpos, &ec);
  106         assertIntEquals("Field position should be correct", 14, ufpos.beginIndex);
  107         assertIntEquals("Field position should be correct", 15, ufpos.endIndex);
  108 
  109         // field position iterator test:
  110         ufpositer = ufieldpositer_open(&ec);
  111         if (assertSuccessCheck("Should create iterator without error", &ec, TRUE)) {
  112 
  113             unumf_resultGetAllFieldPositions(uresult, ufpositer, &ec);
  114             static const UFieldPosition expectedFields[] = {
  115                 // Field, begin index, end index
  116                 {UNUM_SIGN_FIELD, 0, 1},
  117                 {UNUM_GROUPING_SEPARATOR_FIELD, 2, 3},
  118                 {UNUM_GROUPING_SEPARATOR_FIELD, 6, 7},
  119                 {UNUM_GROUPING_SEPARATOR_FIELD, 10, 11},
  120                 {UNUM_INTEGER_FIELD, 1, 14},
  121                 {UNUM_DECIMAL_SEPARATOR_FIELD, 14, 15},
  122                 {UNUM_FRACTION_FIELD, 15, 17},
  123                 {UNUM_MEASURE_UNIT_FIELD, 18, 19}
  124             };
  125             UFieldPosition actual;
  126             for (int32_t i = 0; i < (int32_t)(sizeof(expectedFields) / sizeof(*expectedFields)); i++) {
  127                 // Iterate using the UFieldPosition to hold state...
  128                 UFieldPosition expected = expectedFields[i];
  129                 actual.field = ufieldpositer_next(ufpositer, &actual.beginIndex, &actual.endIndex);
  130                 assertTrue("Should not return a negative index yet", actual.field >= 0);
  131                 if (expected.field != actual.field) {
  132                     log_err(
  133                         "FAIL: iteration %d; expected field %d; got %d\n", i, expected.field, actual.field);
  134                 }
  135                 if (expected.beginIndex != actual.beginIndex) {
  136                     log_err(
  137                         "FAIL: iteration %d; expected beginIndex %d; got %d\n",
  138                         i,
  139                         expected.beginIndex,
  140                         actual.beginIndex);
  141                 }
  142                 if (expected.endIndex != actual.endIndex) {
  143                     log_err(
  144                         "FAIL: iteration %d; expected endIndex %d; got %d\n",
  145                         i,
  146                         expected.endIndex,
  147                         actual.endIndex);
  148                 }
  149             }
  150             actual.field = ufieldpositer_next(ufpositer, &actual.beginIndex, &actual.endIndex);
  151             assertTrue("No more fields; should return a negative index", actual.field < 0);
  152 
  153             // next field iteration:
  154             actual.field = UNUM_GROUPING_SEPARATOR_FIELD;
  155             actual.beginIndex = 0;
  156             actual.endIndex = 0;
  157             int32_t i = 1;
  158             while (unumf_resultNextFieldPosition(uresult, &actual, &ec)) {
  159                 UFieldPosition expected = expectedFields[i++];
  160                 assertIntEquals("Grouping separator begin index", expected.beginIndex, actual.beginIndex);
  161                 assertIntEquals("Grouping separator end index", expected.endIndex, actual.endIndex);
  162             }
  163             assertIntEquals("Should have seen all grouping separators", 4, i);
  164         }
  165     }
  166 
  167     // cleanup:
  168     unumf_closeResult(uresult);
  169     unumf_close(uformatter);
  170     ufieldpositer_close(ufpositer);
  171 }
  172 
  173 
  174 static void TestExampleCode() {
  175     // This is the example code given in unumberformatter.h.
  176 
  177     // Setup:
  178     UErrorCode ec = U_ZERO_ERROR;
  179     UNumberFormatter* uformatter = unumf_openForSkeletonAndLocale(u"precision-integer", -1, "en", &ec);
  180     UFormattedNumber* uresult = unumf_openResult(&ec);
  181     UChar* buffer = NULL;
  182     assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE);
  183 
  184     // Format a double:
  185     unumf_formatDouble(uformatter, 5142.3, uresult, &ec);
  186     if (assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE)) {
  187 
  188         // Export the string to a malloc'd buffer:
  189         int32_t len = unumf_resultToString(uresult, NULL, 0, &ec);
  190         assertTrue("No buffer yet", ec == U_BUFFER_OVERFLOW_ERROR);
  191         ec = U_ZERO_ERROR;
  192         buffer = (UChar*) uprv_malloc((len+1)*sizeof(UChar));
  193         unumf_resultToString(uresult, buffer, len+1, &ec);
  194         assertSuccess("There should not be a failure in the example code", &ec);
  195         assertUEquals("Should produce expected string result", u"5,142", buffer);
  196     }
  197 
  198     // Cleanup:
  199     unumf_close(uformatter);
  200     unumf_closeResult(uresult);
  201     uprv_free(buffer);
  202 }
  203 
  204 
  205 static void TestFormattedValue() {
  206     UErrorCode ec = U_ZERO_ERROR;
  207     UNumberFormatter* uformatter = unumf_openForSkeletonAndLocale(
  208             u".00 compact-short", -1, "en", &ec);
  209     assertSuccessCheck("Should create without error", &ec, TRUE);
  210     UFormattedNumber* uresult = unumf_openResult(&ec);
  211     assertSuccess("Should create result without error", &ec);
  212 
  213     unumf_formatInt(uformatter, 55000, uresult, &ec); // "55.00 K"
  214     if (assertSuccessCheck("Should format without error", &ec, TRUE)) {
  215         const UFormattedValue* fv = unumf_resultAsValue(uresult, &ec);
  216         assertSuccess("Should convert without error", &ec);
  217         static const UFieldPosition expectedFieldPositions[] = {
  218             // field, begin index, end index
  219             {UNUM_INTEGER_FIELD, 0, 2},
  220             {UNUM_DECIMAL_SEPARATOR_FIELD, 2, 3},
  221             {UNUM_FRACTION_FIELD, 3, 5},
  222             {UNUM_COMPACT_FIELD, 5, 6}};
  223         checkFormattedValue(
  224             "FormattedNumber as FormattedValue",
  225             fv,
  226             u"55.00K",
  227             UFIELD_CATEGORY_NUMBER,
  228             expectedFieldPositions,
  229             UPRV_LENGTHOF(expectedFieldPositions));
  230     }
  231 
  232     // cleanup:
  233     unumf_closeResult(uresult);
  234     unumf_close(uformatter);
  235 }
  236 
  237 
  238 static void TestSkeletonParseError() {
  239     UErrorCode ec = U_ZERO_ERROR;
  240     UNumberFormatter* uformatter;
  241     UParseError perror;
  242 
  243     // The UParseError can be null. The following should not segfault.
  244     uformatter = unumf_openForSkeletonAndLocaleWithError(
  245             u".00 measure-unit/typo", -1, "en", NULL, &ec);
  246     unumf_close(uformatter);
  247 
  248     // Now test the behavior.
  249     ec = U_ZERO_ERROR;
  250     uformatter = unumf_openForSkeletonAndLocaleWithError(
  251             u".00 measure-unit/typo", -1, "en", &perror, &ec);
  252 
  253     assertIntEquals("Should have set error code", U_NUMBER_SKELETON_SYNTAX_ERROR, ec);
  254     assertIntEquals("Should have correct skeleton error offset", 17, perror.offset);
  255     assertUEquals("Should have correct pre context", u"0 measure-unit/", perror.preContext);
  256     assertUEquals("Should have correct post context", u"typo", perror.postContext);
  257 
  258     // cleanup:
  259     unumf_close(uformatter);
  260 }
  261 
  262 static void TestPerUnitInArabic() {
  263     const char* simpleMeasureUnits[] = {
  264         "area-acre",
  265         "digital-bit",
  266         "digital-byte",
  267         "temperature-celsius",
  268         "length-centimeter",
  269         "duration-day",
  270         "angle-degree",
  271         "temperature-fahrenheit",
  272         "volume-fluid-ounce",
  273         "length-foot",
  274         "volume-gallon",
  275         "digital-gigabit",
  276         "digital-gigabyte",
  277         "mass-gram",
  278         "area-hectare",
  279         "duration-hour",
  280         "length-inch",
  281         "digital-kilobit",
  282         "digital-kilobyte",
  283         "mass-kilogram",
  284         "length-kilometer",
  285         "volume-liter",
  286         "digital-megabit",
  287         "digital-megabyte",
  288         "length-meter",
  289         "length-mile",
  290         "length-mile-scandinavian",
  291         "volume-milliliter",
  292         "length-millimeter",
  293         "duration-millisecond",
  294         "duration-minute",
  295         "duration-month",
  296         "mass-ounce",
  297         "concentr-percent",
  298         "digital-petabyte",
  299         "mass-pound",
  300         "duration-second",
  301         "mass-stone",
  302         "digital-terabit",
  303         "digital-terabyte",
  304         "duration-week",
  305         "length-yard",
  306         "duration-year"
  307     };
  308 #define BUFFER_LEN 256
  309     char buffer[BUFFER_LEN];
  310     UChar ubuffer[BUFFER_LEN];
  311     const char* locale = "ar";
  312     UErrorCode status = U_ZERO_ERROR;
  313     UFormattedNumber* formatted = unumf_openResult(&status);
  314     if (U_FAILURE(status)) {
  315         log_err("FAIL: unumf_openResult failed");
  316         return;
  317     }
  318     for(int32_t i=0; i < UPRV_LENGTHOF(simpleMeasureUnits); ++i) {
  319         for(int32_t j=0; j < UPRV_LENGTHOF(simpleMeasureUnits); ++j) {
  320             status = U_ZERO_ERROR;
  321             sprintf(buffer, "measure-unit/%s per-measure-unit/%s",
  322                     simpleMeasureUnits[i], simpleMeasureUnits[j]);
  323             int32_t outputlen = 0;
  324             u_strFromUTF8(ubuffer, BUFFER_LEN, &outputlen, buffer, strlen(buffer), &status);
  325             if (U_FAILURE(status)) {
  326                 log_err("FAIL u_strFromUTF8: %s = %s ( %s )\n", locale, buffer,
  327                         u_errorName(status));
  328             }
  329             UNumberFormatter* nf = unumf_openForSkeletonAndLocale(
  330                 ubuffer, outputlen, locale, &status);
  331             if (U_FAILURE(status)) {
  332                 log_err("FAIL unumf_openForSkeletonAndLocale: %s = %s ( %s )\n",
  333                         locale, buffer, u_errorName(status));
  334             } else {
  335                 unumf_formatDouble(nf, 1, formatted, &status);
  336                 if (U_FAILURE(status)) {
  337                     log_err("FAIL unumf_formatDouble: %s = %s ( %s )\n",
  338                             locale, buffer, u_errorName(status));
  339                 }
  340             }
  341             unumf_close(nf);
  342         }
  343     }
  344     unumf_closeResult(formatted);
  345 }
  346 #endif /* #if !UCONFIG_NO_FORMATTING */