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