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
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", // formatting 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