1/*
2 *******************************************************************************
3 * Copyright (C) 1996-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 "itrbnfrt.h"
13
14#include "unicode/fmtable.h"
15#include <math.h> // fabs
16#include <stdio.h>
17
18// current macro not in icu1.8.1
19#define TESTCASE(id,test)             \
20    case id:                          \
21        name = #test;                 \
22        if (exec) {                   \
23            logln(#test "---");       \
24            logln();                  \
25            test();                   \
26        }                             \
27        break
28
29void RbnfRoundTripTest::runIndexedTest(int32_t index, UBool exec, const char* &name, char* /*par*/)
30{
31    if (exec) logln("TestSuite RuleBasedNumberFormatRT");
32    switch (index) {
33#if U_HAVE_RBNF
34      TESTCASE(0, TestEnglishSpelloutRT);
35      TESTCASE(1, TestDurationsRT);
36      TESTCASE(2, TestSpanishSpelloutRT);
37      TESTCASE(3, TestFrenchSpelloutRT);
38      TESTCASE(4, TestSwissFrenchSpelloutRT);
39      TESTCASE(5, TestItalianSpelloutRT);
40      TESTCASE(6, TestGermanSpelloutRT);
41      TESTCASE(7, TestSwedishSpelloutRT);
42      TESTCASE(8, TestDutchSpelloutRT);
43      TESTCASE(9, TestJapaneseSpelloutRT);
44      TESTCASE(10, TestRussianSpelloutRT);
45      TESTCASE(11, TestPortugueseSpelloutRT);
46#else
47      TESTCASE(0, TestRBNFDisabled);
48#endif
49    default:
50      name = "";
51      break;
52    }
53}
54
55#if U_HAVE_RBNF
56
57/**
58 * Perform an exhaustive round-trip test on the English spellout rules
59 */
60void
61RbnfRoundTripTest::TestEnglishSpelloutRT()
62{
63  UErrorCode status = U_ZERO_ERROR;
64  RuleBasedNumberFormat* formatter
65    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getUS(), status);
66
67  if (U_FAILURE(status)) {
68    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
69  } else {
70    doTest(formatter, -12345678, 12345678);
71  }
72  delete formatter;
73}
74
75/**
76 * Perform an exhaustive round-trip test on the duration-formatting rules
77 */
78void
79RbnfRoundTripTest::TestDurationsRT()
80{
81  UErrorCode status = U_ZERO_ERROR;
82  RuleBasedNumberFormat* formatter
83    = new RuleBasedNumberFormat(URBNF_DURATION, Locale::getUS(), status);
84
85  if (U_FAILURE(status)) {
86    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
87  } else {
88    doTest(formatter, 0, 12345678);
89  }
90  delete formatter;
91}
92
93/**
94 * Perform an exhaustive round-trip test on the Spanish spellout rules
95 */
96void
97RbnfRoundTripTest::TestSpanishSpelloutRT()
98{
99  UErrorCode status = U_ZERO_ERROR;
100  RuleBasedNumberFormat* formatter
101    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("es", "es"), status);
102
103  if (U_FAILURE(status)) {
104    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
105  } else {
106    doTest(formatter, -12345678, 12345678);
107  }
108  delete formatter;
109}
110
111/**
112 * Perform an exhaustive round-trip test on the French spellout rules
113 */
114void
115RbnfRoundTripTest::TestFrenchSpelloutRT()
116{
117  UErrorCode status = U_ZERO_ERROR;
118  RuleBasedNumberFormat* formatter
119    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getFrance(), status);
120
121  if (U_FAILURE(status)) {
122    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
123  } else {
124    doTest(formatter, -12345678, 12345678);
125  }
126  delete formatter;
127}
128
129/**
130 * Perform an exhaustive round-trip test on the Swiss French spellout rules
131 */
132void
133RbnfRoundTripTest::TestSwissFrenchSpelloutRT()
134{
135  UErrorCode status = U_ZERO_ERROR;
136  RuleBasedNumberFormat* formatter
137    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("fr", "CH"), status);
138
139  if (U_FAILURE(status)) {
140    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
141  } else {
142    doTest(formatter, -12345678, 12345678);
143  }
144  delete formatter;
145}
146
147/**
148 * Perform an exhaustive round-trip test on the Italian spellout rules
149 */
150void
151RbnfRoundTripTest::TestItalianSpelloutRT()
152{
153  UErrorCode status = U_ZERO_ERROR;
154  RuleBasedNumberFormat* formatter
155    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getItalian(), status);
156
157  if (U_FAILURE(status)) {
158    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
159  } else {
160    doTest(formatter, -999999, 999999);
161  }
162  delete formatter;
163}
164
165/**
166 * Perform an exhaustive round-trip test on the German spellout rules
167 */
168void
169RbnfRoundTripTest::TestGermanSpelloutRT()
170{
171  UErrorCode status = U_ZERO_ERROR;
172  RuleBasedNumberFormat* formatter
173    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getGermany(), status);
174
175  if (U_FAILURE(status)) {
176    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
177  } else {
178    doTest(formatter, 0, 12345678);
179  }
180  delete formatter;
181}
182
183/**
184 * Perform an exhaustive round-trip test on the Swedish spellout rules
185 */
186void
187RbnfRoundTripTest::TestSwedishSpelloutRT()
188{
189  UErrorCode status = U_ZERO_ERROR;
190  RuleBasedNumberFormat* formatter
191    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("sv", "SE"), status);
192
193  if (U_FAILURE(status)) {
194    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
195  } else {
196    doTest(formatter, 0, 12345678);
197  }
198  delete formatter;
199}
200
201/**
202 * Perform an exhaustive round-trip test on the Dutch spellout rules
203 */
204void
205RbnfRoundTripTest::TestDutchSpelloutRT()
206{
207  UErrorCode status = U_ZERO_ERROR;
208  RuleBasedNumberFormat* formatter
209    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("nl", "NL"), status);
210
211  if (U_FAILURE(status)) {
212    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
213  } else {
214    doTest(formatter, -12345678, 12345678);
215  }
216  delete formatter;
217}
218
219/**
220 * Perform an exhaustive round-trip test on the Japanese spellout rules
221 */
222void
223RbnfRoundTripTest::TestJapaneseSpelloutRT()
224{
225  UErrorCode status = U_ZERO_ERROR;
226  RuleBasedNumberFormat* formatter
227    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale::getJapan(), status);
228
229  if (U_FAILURE(status)) {
230    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
231  } else {
232    doTest(formatter, 0, 12345678);
233  }
234  delete formatter;
235}
236
237/**
238 * Perform an exhaustive round-trip test on the Russian spellout rules
239 */
240void
241RbnfRoundTripTest::TestRussianSpelloutRT()
242{
243  UErrorCode status = U_ZERO_ERROR;
244  RuleBasedNumberFormat* formatter
245    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("ru", "RU"), status);
246
247  if (U_FAILURE(status)) {
248    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
249  } else {
250    doTest(formatter, 0, 12345678);
251  }
252  delete formatter;
253}
254
255/**
256 * Perform an exhaustive round-trip test on the Portuguese spellout rules
257 */
258void
259RbnfRoundTripTest::TestPortugueseSpelloutRT()
260{
261  UErrorCode status = U_ZERO_ERROR;
262  RuleBasedNumberFormat* formatter
263    = new RuleBasedNumberFormat(URBNF_SPELLOUT, Locale("pt", "BR"), status);
264
265  if (U_FAILURE(status)) {
266    errcheckln(status, "failed to construct formatter - %s", u_errorName(status));
267  } else {
268    doTest(formatter, -12345678, 12345678);
269  }
270  delete formatter;
271}
272
273void
274RbnfRoundTripTest::doTest(const RuleBasedNumberFormat* formatter,
275                          double lowLimit,
276                          double highLimit)
277{
278  char buf[128];
279
280  uint32_t count = 0;
281  double increment = 1;
282  for (double i = lowLimit; i <= highLimit; i += increment) {
283    if (count % 1000 == 0) {
284      sprintf(buf, "%.12g", i);
285      logln(buf);
286    }
287
288    if (fabs(i) <  5000)
289      increment = 1;
290    else if (fabs(i) < 500000)
291      increment = 2737;
292    else
293      increment = 267437;
294
295    UnicodeString formatResult;
296    formatter->format(i, formatResult);
297    UErrorCode status = U_ZERO_ERROR;
298    Formattable parseResult;
299    formatter->parse(formatResult, parseResult, status);
300    if (U_FAILURE(status)) {
301      sprintf(buf, "Round-trip status failure: %.12g, status: %d", i, status);
302      errln(buf);
303      return;
304    } else {
305      double rt = (parseResult.getType() == Formattable::kDouble) ?
306        parseResult.getDouble() :
307        (double)parseResult.getLong();
308
309      if (rt != i) {
310        sprintf(buf, "Round-trip failed: %.12g -> %.12g", i, rt);
311        errln(buf);
312        return;
313      }
314    }
315
316    ++count;
317  }
318
319  if (lowLimit < 0) {
320    double d = 1.234;
321    while (d < 1000) {
322      UnicodeString formatResult;
323      formatter->format(d, formatResult);
324      UErrorCode status = U_ZERO_ERROR;
325      Formattable parseResult;
326      formatter->parse(formatResult, parseResult, status);
327      if (U_FAILURE(status)) {
328        sprintf(buf, "Round-trip status failure: %.12g, status: %d", d, status);
329        errln(buf);
330        return;
331      } else {
332        double rt = (parseResult.getType() == Formattable::kDouble) ?
333          parseResult.getDouble() :
334          (double)parseResult.getLong();
335
336        if (rt != d) {
337          UnicodeString msg;
338          sprintf(buf, "Round-trip failed: %.12g -> ", d);
339          msg.append(buf);
340          msg.append(formatResult);
341          sprintf(buf, " -> %.12g", rt);
342          msg.append(buf);
343          errln(msg);
344          return;
345        }
346      }
347
348      d *= 10;
349    }
350  }
351}
352
353/* U_HAVE_RBNF */
354#else
355
356void
357RbnfRoundTripTest::TestRBNFDisabled() {
358    errln("*** RBNF currently disabled on this platform ***\n");
359}
360
361/* U_HAVE_RBNF */
362#endif
363
364#endif /* #if !UCONFIG_NO_FORMATTING */
365