• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 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 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)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
TestParse()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
testfmt(RuleBasedNumberFormat * formatter,double val,UErrorCode & status)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
testfmt(RuleBasedNumberFormat * formatter,int val,UErrorCode & status)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
TestRBNFParseDisabled()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