Home | History | Annotate | Download | only in intltest
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4  *******************************************************************************
      5  * Copyright (C) 2004-2009, International Business Machines Corporation and         *
      6  * others. All Rights Reserved.                                                *
      7  *******************************************************************************
      8  */
      9 
     10 #include "unicode/utypes.h"
     11 
     12 #if !UCONFIG_NO_FORMATTING
     13 
     14 #include "itrbnfp.h"
     15 
     16 #include "unicode/umachine.h"
     17 
     18 #include "unicode/tblcoll.h"
     19 #include "unicode/coleitr.h"
     20 #include "unicode/ures.h"
     21 #include "unicode/ustring.h"
     22 #include "unicode/decimfmt.h"
     23 
     24 #include <string.h>
     25 
     26 // current macro not in icu1.8.1
     27 #define TESTCASE(id,test)             \
     28     case id:                          \
     29         name = #test;                 \
     30         if (exec) {                   \
     31             logln(#test "---");       \
     32             logln();                  \
     33             test();                   \
     34         }                             \
     35         break
     36 
     37 void IntlTestRBNFParse::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/)
     38 {
     39     if (exec) logln("TestSuite RuleBasedNumberFormatParse");
     40     switch (index) {
     41 #if U_HAVE_RBNF
     42         TESTCASE(0, TestParse);
     43 #else
     44         TESTCASE(0, TestRBNFParseDisabled);
     45 #endif
     46     default:
     47         name = "";
     48         break;
     49     }
     50 }
     51 
     52 #if U_HAVE_RBNF
     53 
     54 void
     55 IntlTestRBNFParse::TestParse() {
     56   // Try various rule parsing errors.  Shouldn't crash.
     57 
     58   logln("RBNF Parse test starting");
     59 
     60   // these rules make no sense but behave rationally
     61   const char* okrules[] = {
     62     "",
     63     "random text",
     64     "%foo:bar",
     65     "%foo: bar",
     66     "0:",
     67     "0::",
     68     ";",
     69     ";;",
     70     "%%foo:;",
     71     ":",
     72     "::",
     73     ":1",
     74     ":;",
     75     ":;:;",
     76     "-",
     77     "-1",
     78     "-:",
     79     ".",
     80     ".1",
     81     "[",
     82     "]",
     83     "[]",
     84     "[foo]",
     85     "[[]",
     86     "[]]",
     87     "[[]]",
     88     "[][]",
     89     "<",
     90     "<<",
     91     "<<<",
     92     "10:;9:;",
     93     ">",
     94     ">>",
     95     ">>>",
     96     "=",
     97     "==",
     98     "===",
     99     "=foo=",
    100 
    101     NULL,
    102   };
    103 
    104   // these rules would throw exceptions when formatting, if we could throw exceptions
    105   const char* exceptrules[] = {
    106     "10:", // formatting any value with a one's digit will fail
    107     "11: << x", // formating a multiple of 10 causes rollback rule to fail
    108     "%%foo: 0 foo; 10: =%%bar=; %%bar: 0: bar; 10: =%%foo=;",
    109 
    110     NULL,
    111   };
    112 
    113   // none of these rules should crash the formatter
    114   const char** allrules[] = {
    115     okrules,
    116     exceptrules,
    117     NULL,
    118   };
    119 
    120   for (int j = 0; allrules[j]; ++j) {
    121       const char** rules = allrules[j];
    122       for (int i = 0; rules[i]; ++i) {
    123           const char* rule = rules[i];
    124           logln("rule[%d] \"%s\"", i, rule);
    125           UErrorCode status = U_ZERO_ERROR;
    126           UParseError perr;
    127           RuleBasedNumberFormat* formatter = new RuleBasedNumberFormat(rule, Locale::getUS(), perr, status);
    128 
    129           if (U_SUCCESS(status)) {
    130               // format some values
    131 
    132               testfmt(formatter, 20, status);
    133               testfmt(formatter, 1.23, status);
    134               testfmt(formatter, -123, status);
    135               testfmt(formatter, .123, status);
    136               testfmt(formatter, 123, status);
    137 
    138           } else if (status == U_PARSE_ERROR) {
    139               logln("perror line: %x offset: %x context: %s|%s", perr.line, perr.offset, perr.preContext, perr.postContext);
    140           }
    141 
    142           delete formatter;
    143       }
    144   }
    145 }
    146 
    147 void
    148 IntlTestRBNFParse::testfmt(RuleBasedNumberFormat* formatter, double val, UErrorCode& status) {
    149     UnicodeString us;
    150     formatter->format((const Formattable)val, us, status);
    151     if (U_SUCCESS(status)) {
    152         us.insert(0, (UChar)'"');
    153         us.append((UChar)'"');
    154         logln(us);
    155     } else {
    156         logln("error: could not format %g, returned status: %d", val, status);
    157     }
    158 }
    159 
    160 void
    161 IntlTestRBNFParse::testfmt(RuleBasedNumberFormat* formatter, int val, UErrorCode& status) {
    162     UnicodeString us;
    163     formatter->format((const Formattable)(int32_t)val, us, status);
    164     if (U_SUCCESS(status)) {
    165         us.insert(0, (UChar)'"');
    166         us.append((UChar)'"');
    167         logln(us);
    168     } else {
    169         logln("error: could not format %d, returned status: %d", val, status);
    170     }
    171 }
    172 
    173 
    174 /* U_HAVE_RBNF */
    175 #else
    176 
    177 void
    178 IntlTestRBNF::TestRBNFParseDisabled() {
    179     errln("*** RBNF currently disabled on this platform ***\n");
    180 }
    181 
    182 /* U_HAVE_RBNF */
    183 #endif
    184 
    185 #endif /* #if !UCONFIG_NO_FORMATTING */
    186