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
35void 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
52void
53IntlTestRBNFParse::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
145void
146IntlTestRBNFParse::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
158void
159IntlTestRBNFParse::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
175void
176IntlTestRBNF::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