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