]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/tests/core/src/com/ibm/icu/dev/test/format/RbnfTest.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / tests / core / src / com / ibm / icu / dev / test / format / RbnfTest.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2009, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.dev.test.format;\r
8 \r
9 import java.math.BigInteger;\r
10 import java.text.DecimalFormat;\r
11 import java.text.NumberFormat;\r
12 import java.text.ParseException;\r
13 import java.util.Locale;\r
14 import java.util.Random;\r
15 \r
16 import com.ibm.icu.dev.test.TestFmwk;\r
17 import com.ibm.icu.text.RuleBasedNumberFormat;\r
18 import com.ibm.icu.util.ULocale;\r
19 \r
20 /**\r
21  * This does not test lenient parse mode, since testing the default implementation\r
22  * introduces a dependency on collation.  See RbnfLenientScannerTest.\r
23  */\r
24 public class RbnfTest extends TestFmwk {\r
25     public static void main(String[] args) {\r
26         RbnfTest test = new RbnfTest();\r
27 \r
28         try {\r
29             test.run(args);\r
30         }\r
31         catch (Throwable e) {\r
32             System.out.println("Entire test failed because of exception: "\r
33                                + e.toString());\r
34             e.printStackTrace();\r
35         }\r
36     }\r
37 \r
38     static String fracRules = \r
39         "%main:\n" +\r
40         // this rule formats the number if it's 1 or more.  It formats\r
41         // the integral part using a DecimalFormat ("#,##0" puts\r
42         // thousands separators in the right places) and the fractional\r
43         // part using %%frac.  If there is no fractional part, it\r
44         // just shows the integral part.\r
45         "    x.0: <#,##0<[ >%%frac>];\n" +\r
46         // this rule formats the number if it's between 0 and 1.  It\r
47         // shows only the fractional part (0.5 shows up as "1/2," not\r
48         // "0 1/2")\r
49         "    0.x: >%%frac>;\n" +\r
50         // the fraction rule set.  This works the same way as the one in the\r
51         // preceding example: We multiply the fractional part of the number\r
52         // being formatted by each rule's base value and use the rule that\r
53         // produces the result closest to 0 (or the first rule that produces 0).\r
54         // Since we only provide rules for the numbers from 2 to 10, we know\r
55         // we'll get a fraction with a denominator between 2 and 10.\r
56         // "<0<" causes the numerator of the fraction to be formatted\r
57         // using numerals\r
58         "%%frac:\n" +\r
59         "    2: 1/2;\n" +\r
60         "    3: <0</3;\n" +\r
61         "    4: <0</4;\n" +\r
62         "    5: <0</5;\n" +\r
63         "    6: <0</6;\n" +\r
64         "    7: <0</7;\n" +\r
65         "    8: <0</8;\n" +\r
66         "    9: <0</9;\n" +\r
67         "   10: <0</10;\n";\r
68 \r
69     static {\r
70         // mondo hack\r
71     char[] fracRulesArr = fracRules.toCharArray();\r
72         int len = fracRulesArr.length;\r
73         int change = 2;\r
74         for (int i = 0; i < len; ++i) {\r
75             char ch = fracRulesArr[i];\r
76             if (ch == '\n') {\r
77                 change = 2; // change ok\r
78             } else if (ch == ':') {\r
79                 change = 1; // change, but once we hit a non-space char, don't change\r
80             } else if (ch == ' ') {\r
81                 if (change != 0) {\r
82                     fracRulesArr[i] = (char)0x200e;\r
83                 }\r
84             } else {\r
85                 if (change == 1) {\r
86                     change = 0;\r
87                 }\r
88             }\r
89         }\r
90     fracRules = new String(fracRulesArr);\r
91     }\r
92 \r
93     static final String durationInSecondsRules =\r
94         // main rule set for formatting with words\r
95         "%with-words:\n"\r
96         // take care of singular and plural forms of "second"\r
97         + "    0 seconds; 1 second; =0= seconds;\n"\r
98         // use %%min to format values greater than 60 seconds\r
99         + "    60/60: <%%min<[, >>];\n"\r
100         // use %%hr to format values greater than 3,600 seconds\r
101         // (the ">>>" below causes us to see the number of minutes\r
102         // when when there are zero minutes)\r
103         + "    3600/60: <%%hr<[, >>>];\n"\r
104         // this rule set takes care of the singular and plural forms\r
105         // of "minute"\r
106         + "%%min:\n"\r
107         + "    0 minutes; 1 minute; =0= minutes;\n"\r
108         // this rule set takes care of the singular and plural forms\r
109         // of "hour"\r
110         + "%%hr:\n"\r
111         + "    0 hours; 1 hour; =0= hours;\n"\r
112 \r
113         // main rule set for formatting in numerals\r
114         + "%in-numerals:\n"\r
115         // values below 60 seconds are shown with "sec."\r
116         + "    =0= sec.;\n"\r
117         // higher values are shown with colons: %%min-sec is used for\r
118         // values below 3,600 seconds...\r
119         + "    60: =%%min-sec=;\n"\r
120         // ...and %%hr-min-sec is used for values of 3,600 seconds\r
121         // and above\r
122         + "    3600: =%%hr-min-sec=;\n"\r
123         // this rule causes values of less than 10 minutes to show without\r
124         // a leading zero\r
125         + "%%min-sec:\n"\r
126         + "    0: :=00=;\n"\r
127         + "    60/60: <0<>>;\n"\r
128         // this rule set is used for values of 3,600 or more.  Minutes are always\r
129         // shown, and always shown with two digits\r
130         + "%%hr-min-sec:\n"\r
131         + "    0: :=00=;\n"\r
132         + "    60/60: <00<>>;\n"\r
133         + "    3600/60: <#,##0<:>>>;\n"\r
134         // the lenient-parse rules allow several different characters to be used\r
135         // as delimiters between hours, minutes, and seconds\r
136         + "%%lenient-parse:\n"\r
137         + "    & : = . = ' ' = -;\n";\r
138 \r
139     public void TestCoverage() {\r
140         // extra calls to boost coverage numbers\r
141         RuleBasedNumberFormat fmt0 = new RuleBasedNumberFormat(RuleBasedNumberFormat.SPELLOUT);\r
142         RuleBasedNumberFormat fmt1 = (RuleBasedNumberFormat)fmt0.clone();\r
143         RuleBasedNumberFormat fmt2 = new RuleBasedNumberFormat(RuleBasedNumberFormat.SPELLOUT);\r
144         if (!fmt0.equals(fmt0)) {\r
145             errln("self equality fails");\r
146         }\r
147         if (!fmt0.equals(fmt1)) {\r
148             errln("clone equality fails");\r
149         }\r
150         if (!fmt0.equals(fmt2)) {\r
151             errln("duplicate equality fails");\r
152         }\r
153         String str = fmt0.toString();\r
154         logln(str);\r
155 \r
156         RuleBasedNumberFormat fmt3 =  new RuleBasedNumberFormat(durationInSecondsRules);\r
157 \r
158         if (fmt0.equals(fmt3)) {\r
159             errln("nonequal fails");\r
160         }\r
161         if (!fmt3.equals(fmt3)) {\r
162             errln("self equal 2 fails");\r
163         }\r
164         str = fmt3.toString();\r
165         logln(str);\r
166 \r
167         String[] names = fmt3.getRuleSetNames();\r
168 \r
169         try {\r
170             fmt3.setDefaultRuleSet(null);\r
171             fmt3.setDefaultRuleSet("%%foo");\r
172             errln("sdrf %%foo didn't fail");\r
173         }\r
174         catch (Exception e) {\r
175             logln("Got the expected exception");\r
176         }\r
177 \r
178         try {\r
179             fmt3.setDefaultRuleSet("%bogus");\r
180             errln("sdrf %bogus didn't fail");\r
181         }\r
182         catch (Exception e) {\r
183             logln("Got the expected exception");\r
184         }\r
185 \r
186         try {\r
187             str = fmt3.format(2.3, names[0]);\r
188             logln(str);\r
189             str = fmt3.format(2.3, "%%foo");\r
190             errln("format double %%foo didn't fail");\r
191         }\r
192         catch (Exception e) {\r
193             logln("Got the expected exception");\r
194         }\r
195 \r
196         try {\r
197             str = fmt3.format(123L, names[0]);\r
198             logln(str);\r
199             str = fmt3.format(123L, "%%foo");\r
200             errln("format double %%foo didn't fail");\r
201         }\r
202         catch (Exception e) {\r
203             logln("Got the expected exception");\r
204         }\r
205 \r
206         RuleBasedNumberFormat fmt4 = new RuleBasedNumberFormat(fracRules, Locale.ENGLISH);\r
207         RuleBasedNumberFormat fmt5 = new RuleBasedNumberFormat(fracRules, Locale.ENGLISH);\r
208         str = fmt4.toString();\r
209         logln(str);\r
210         if (!fmt4.equals(fmt5)) {\r
211             errln("duplicate 2 equality failed");\r
212         }\r
213         str = fmt4.format(123L);\r
214         logln(str);\r
215         try {\r
216             Number num = fmt4.parse(str);\r
217             logln(num.toString());\r
218         }\r
219         catch (Exception e) {\r
220             errln("parse caught exception");\r
221         }\r
222 \r
223         str = fmt4.format(.000123);\r
224         logln(str);\r
225         try {\r
226             Number num = fmt4.parse(str);\r
227             logln(num.toString());\r
228         }\r
229         catch (Exception e) {\r
230             errln("parse caught exception");\r
231         }\r
232 \r
233         str = fmt4.format(456.000123);\r
234         logln(str);\r
235         try {\r
236             Number num = fmt4.parse(str);\r
237             logln(num.toString());\r
238         }\r
239         catch (Exception e) {\r
240             errln("parse caught exception");\r
241         }\r
242     }\r
243 \r
244     public void TestUndefinedSpellout() {\r
245         Locale greek = new Locale("el", "", "");\r
246         RuleBasedNumberFormat[] formatters = {\r
247             new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.SPELLOUT),\r
248             new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.ORDINAL),\r
249             new RuleBasedNumberFormat(greek, RuleBasedNumberFormat.DURATION),\r
250         };\r
251 \r
252         String[] data = {\r
253             "0",\r
254             "1",\r
255             "15",\r
256             "20",\r
257             "23",\r
258             "73",\r
259             "88",\r
260             "100",\r
261             "106",\r
262             "127",\r
263             "200",\r
264             "579",\r
265             "1,000",\r
266             "2,000",\r
267             "3,004",\r
268             "4,567",\r
269             "15,943",\r
270             "105,000",\r
271             "2,345,678",\r
272             "-36",\r
273             "-36.91215",\r
274             "234.56789"\r
275         };\r
276 \r
277         NumberFormat decFormat = NumberFormat.getInstance(Locale.US);\r
278         for (int j = 0; j < formatters.length; ++j) {\r
279             com.ibm.icu.text.NumberFormat formatter = formatters[j];\r
280             logln("formatter[" + j + "]");\r
281             for (int i = 0; i < data.length; ++i) {\r
282                 try {\r
283                     String result = formatter.format(decFormat.parse(data[i]));\r
284                     logln("[" + i + "] " + data[i] + " ==> " + result);\r
285                 }\r
286                 catch (Exception e) {\r
287                     errln("formatter[" + j + "], data[" + i + "] " + data[i] + " threw exception " + e.getMessage());\r
288                 }\r
289             }\r
290         }\r
291     }\r
292 \r
293     /**\r
294      * Perform a simple spot check on the English spellout rules\r
295      */\r
296     public void TestEnglishSpellout() {\r
297         RuleBasedNumberFormat formatter\r
298             = new RuleBasedNumberFormat(Locale.US,\r
299                                         RuleBasedNumberFormat.SPELLOUT);\r
300         String[][] testData = {\r
301             { "1", "one" },\r
302             { "15", "fifteen" },\r
303             { "20", "twenty" },\r
304             { "23", "twenty-three" },\r
305             { "73", "seventy-three" },\r
306             { "88", "eighty-eight" },\r
307             { "100", "one hundred" },\r
308             { "106", "one hundred six" },\r
309             { "127", "one hundred twenty-seven" },\r
310             { "200", "two hundred" },\r
311             { "579", "five hundred seventy-nine" },\r
312             { "1,000", "one thousand" },\r
313             { "2,000", "two thousand" },\r
314             { "3,004", "three thousand four" },\r
315             { "4,567", "four thousand five hundred sixty-seven" },\r
316             { "15,943", "fifteen thousand nine hundred forty-three" },\r
317             { "2,345,678", "two million three hundred forty-five "\r
318               + "thousand six hundred seventy-eight" },\r
319             { "-36", "minus thirty-six" },\r
320             { "234.567", "two hundred thirty-four point five six seven" }\r
321         };\r
322 \r
323         doTest(formatter, testData, true);\r
324     }\r
325 \r
326     /**\r
327      * Perform a simple spot check on the English ordinal-abbreviation rules\r
328      */\r
329     public void TestOrdinalAbbreviations() {\r
330         RuleBasedNumberFormat formatter\r
331             = new RuleBasedNumberFormat(Locale.US,\r
332                                         RuleBasedNumberFormat.ORDINAL);\r
333         String[][] testData = {\r
334             { "1", "1\u02e2\u1d57" },\r
335             { "2", "2\u207f\u1d48" },\r
336             { "3", "3\u02b3\u1d48" },\r
337             { "4", "4\u1d57\u02b0" },\r
338             { "7", "7\u1d57\u02b0" },\r
339             { "10", "10\u1d57\u02b0" },\r
340             { "11", "11\u1d57\u02b0" },\r
341             { "13", "13\u1d57\u02b0" },\r
342             { "20", "20\u1d57\u02b0" },\r
343             { "21", "21\u02e2\u1d57" },\r
344             { "22", "22\u207f\u1d48" },\r
345             { "23", "23\u02b3\u1d48" },\r
346             { "24", "24\u1d57\u02b0" },\r
347             { "33", "33\u02b3\u1d48" },\r
348             { "102", "102\u207f\u1d48" },\r
349             { "312", "312\u1d57\u02b0" },\r
350             { "12,345", "12,345\u1d57\u02b0" }\r
351         };\r
352 \r
353         doTest(formatter, testData, false);\r
354     }\r
355 \r
356     /**\r
357      * Perform a simple spot check on the duration-formatting rules\r
358      */\r
359     public void TestDurations() {\r
360         RuleBasedNumberFormat formatter\r
361             = new RuleBasedNumberFormat(Locale.US,\r
362                                         RuleBasedNumberFormat.DURATION);\r
363         String[][] testData = {\r
364             { "3,600", "1:00:00" },             //move me and I fail\r
365             { "0", "0 sec." },\r
366             { "1", "1 sec." },\r
367             { "24", "24 sec." },\r
368             { "60", "1:00" },\r
369             { "73", "1:13" },\r
370             { "145", "2:25" },\r
371             { "666", "11:06" },\r
372             //            { "3,600", "1:00:00" },\r
373             { "3,740", "1:02:20" },\r
374             { "10,293", "2:51:33" }\r
375         };\r
376 \r
377         doTest(formatter, testData, true);\r
378     }\r
379 \r
380     /**\r
381      * Perform a simple spot check on the Spanish spellout rules\r
382      */\r
383     public void TestSpanishSpellout() {\r
384         RuleBasedNumberFormat formatter\r
385             = new RuleBasedNumberFormat(new Locale("es", "es",\r
386                                                    ""), RuleBasedNumberFormat.SPELLOUT);\r
387         String[][] testData = {\r
388             { "1", "uno" },\r
389             { "6", "seis" },\r
390             { "16", "diecis\u00e9is" },\r
391             { "20", "veinte" },\r
392             { "24", "veinticuatro" },\r
393             { "26", "veintis\u00e9is" },\r
394             { "73", "setenta y tres" },\r
395             { "88", "ochenta y ocho" },\r
396             { "100", "cien" },\r
397             { "106", "ciento seis" },\r
398             { "127", "ciento veintisiete" },\r
399             { "200", "doscientos" },\r
400             { "579", "quinientos setenta y nueve" },\r
401             { "1,000", "mil" },\r
402             { "2,000", "dos mil" },\r
403             { "3,004", "tres mil cuatro" },\r
404             { "4,567", "cuatro mil quinientos sesenta y siete" },\r
405             { "15,943", "quince mil novecientos cuarenta y tres" },\r
406             { "2,345,678", "dos millones trescientos cuarenta y cinco mil "\r
407               + "seiscientos setenta y ocho"},\r
408             { "-36", "menos treinta y seis" },\r
409             { "234.567", "doscientos treinta y cuatro coma cinco seis siete" }\r
410         };\r
411 \r
412         doTest(formatter, testData, true);\r
413     }\r
414 \r
415     /**\r
416      * Perform a simple spot check on the French spellout rules\r
417      */\r
418     public void TestFrenchSpellout() {\r
419         RuleBasedNumberFormat formatter\r
420             = new RuleBasedNumberFormat(Locale.FRANCE,\r
421                                         RuleBasedNumberFormat.SPELLOUT);\r
422         String[][] testData = {\r
423             { "1", "un" },\r
424             { "15", "quinze" },\r
425             { "20", "vingt" },\r
426             { "21", "vingt-et-un" },\r
427             { "23", "vingt-trois" },\r
428             { "62", "soixante-deux" },\r
429             { "70", "soixante-dix" },\r
430             { "71", "soixante-et-onze" },\r
431             { "73", "soixante-treize" },\r
432             { "80", "quatre-vingts" },\r
433             { "88", "quatre-vingt-huit" },\r
434             { "100", "cent" },\r
435             { "106", "cent-six" },\r
436             { "127", "cent-vingt-sept" },\r
437             { "200", "deux-cents" },\r
438             { "579", "cinq-cent-soixante-dix-neuf" },\r
439             { "1,000", "mille" },\r
440             { "1,123", "mille-cent-vingt-trois" },\r
441             { "1,594", "mille-cinq-cent-quatre-vingt-quatorze" },\r
442             { "2,000", "deux-mille" },\r
443             { "3,004", "trois-mille-quatre" },\r
444             { "4,567", "quatre-mille-cinq-cent-soixante-sept" },\r
445             { "15,943", "quinze-mille-neuf-cent-quarante-trois" },\r
446             { "2,345,678", "deux millions trois-cent-quarante-cinq-mille-"\r
447               + "six-cent-soixante-dix-huit" },\r
448             { "-36", "moins trente-six" },\r
449             { "234.567", "deux-cent-trente-quatre virgule cinq six sept" }\r
450         };\r
451 \r
452         doTest(formatter, testData, true);\r
453     }\r
454 \r
455     /**\r
456      * Perform a simple spot check on the Swiss French spellout rules\r
457      */\r
458     public void TestSwissFrenchSpellout() {\r
459         RuleBasedNumberFormat formatter\r
460             = new RuleBasedNumberFormat(new Locale("fr", "CH",\r
461                                                    ""), RuleBasedNumberFormat.SPELLOUT);\r
462         String[][] testData = {\r
463             { "1", "un" },\r
464             { "15", "quinze" },\r
465             { "20", "vingt" },\r
466             { "21", "vingt-et-un" },\r
467             { "23", "vingt-trois" },\r
468             { "62", "soixante-deux" },\r
469             { "70", "septante" },\r
470             { "71", "septante-et-un" },\r
471             { "73", "septante-trois" },\r
472             { "80", "huitante" },\r
473             { "88", "huitante-huit" },\r
474             { "100", "cent" },\r
475             { "106", "cent-six" },\r
476             { "127", "cent-vingt-sept" },\r
477             { "200", "deux-cents" },\r
478             { "579", "cinq-cent-septante-neuf" },\r
479             { "1,000", "mille" },\r
480             { "1,123", "mille-cent-vingt-trois" },\r
481             { "1,594", "mille-cinq-cent-nonante-quatre" },\r
482             { "2,000", "deux-mille" },\r
483             { "3,004", "trois-mille-quatre" },\r
484             { "4,567", "quatre-mille-cinq-cent-soixante-sept" },\r
485             { "15,943", "quinze-mille-neuf-cent-quarante-trois" },\r
486             { "2,345,678", "deux millions trois-cent-quarante-cinq-mille-"\r
487               + "six-cent-septante-huit" },\r
488             { "-36", "moins trente-six" },\r
489             { "234.567", "deux-cent-trente-quatre virgule cinq six sept" }\r
490         };\r
491 \r
492         doTest(formatter, testData, true);\r
493     }\r
494 \r
495     /**\r
496      * Perform a simple spot check on the Italian spellout rules\r
497      */\r
498     public void TestItalianSpellout() {\r
499         RuleBasedNumberFormat formatter\r
500             = new RuleBasedNumberFormat(Locale.ITALIAN,\r
501                                         RuleBasedNumberFormat.SPELLOUT);\r
502         String[][] testData = {\r
503             { "1", "uno" },\r
504             { "15", "quindici" },\r
505             { "20", "venti" },\r
506             { "23", "venti\u00ADtr\u00E9" },\r
507             { "73", "settanta\u00ADtr\u00E9" },\r
508             { "88", "ottant\u00ADotto" },\r
509             { "100", "cento" },\r
510             { "106", "cento\u00ADsei" },\r
511             { "108", "cent\u00ADotto" },\r
512             { "127", "cento\u00ADventi\u00ADsette" },\r
513             { "181", "cent\u00ADottant\u00ADuno" },\r
514             { "200", "due\u00ADcento" },\r
515             { "579", "cinque\u00ADcento\u00ADsettanta\u00ADnove" },\r
516             { "1,000", "mille" },\r
517             { "2,000", "due\u00ADmila" },\r
518             { "3,004", "tre\u00ADmila\u00ADquattro" },\r
519             { "4,567", "quattro\u00ADmila\u00ADcinque\u00ADcento\u00ADsessanta\u00ADsette" },\r
520             { "15,943", "quindici\u00ADmila\u00ADnove\u00ADcento\u00ADquaranta\u00ADtr\u00E9" },\r
521             { "-36", "meno trenta\u00ADsei" },\r
522             { "234.567", "due\u00ADcento\u00ADtrenta\u00ADquattro virgola cinque sei sette" }\r
523         };\r
524 \r
525         doTest(formatter, testData, true);\r
526     }\r
527 \r
528     /**\r
529      * Perform a simple spot check on the German spellout rules\r
530      */\r
531     public void TestGermanSpellout() {\r
532         RuleBasedNumberFormat formatter\r
533             = new RuleBasedNumberFormat(Locale.GERMANY,\r
534                                         RuleBasedNumberFormat.SPELLOUT);\r
535         String[][] testData = {\r
536             { "1", "eins" },\r
537             { "15", "f\u00fcnfzehn" },\r
538             { "20", "zwanzig" },\r
539             { "23", "drei\u00ADund\u00ADzwanzig" },\r
540             { "73", "drei\u00ADund\u00ADsiebzig" },\r
541             { "88", "acht\u00ADund\u00ADachtzig" },\r
542             { "100", "ein\u00ADhundert" },\r
543             { "106", "ein\u00ADhundert\u00ADsechs" },\r
544             { "127", "ein\u00ADhundert\u00ADsieben\u00ADund\u00ADzwanzig" },\r
545             { "200", "zwei\u00ADhundert" },\r
546             { "579", "f\u00fcnf\u00ADhundert\u00ADneun\u00ADund\u00ADsiebzig" },\r
547             { "1,000", "ein\u00ADtausend" },\r
548             { "2,000", "zwei\u00ADtausend" },\r
549             { "3,004", "drei\u00ADtausend\u00ADvier" },\r
550             { "4,567", "vier\u00ADtausend\u00ADf\u00fcnf\u00ADhundert\u00ADsieben\u00ADund\u00ADsechzig" },\r
551             { "15,943", "f\u00fcnfzehn\u00ADtausend\u00ADneun\u00ADhundert\u00ADdrei\u00ADund\u00ADvierzig" },\r
552             { "2,345,678", "zwei Millionen drei\u00ADhundert\u00ADf\u00fcnf\u00ADund\u00ADvierzig\u00ADtausend\u00AD"\r
553               + "sechs\u00ADhundert\u00ADacht\u00ADund\u00ADsiebzig" }\r
554         };\r
555 \r
556         doTest(formatter, testData, true);\r
557     }\r
558 \r
559     /**\r
560      * Perform a simple spot check on the Thai spellout rules\r
561      */\r
562     public void TestThaiSpellout() {\r
563         RuleBasedNumberFormat formatter\r
564             = new RuleBasedNumberFormat(new Locale("th", "TH", ""),\r
565                                         RuleBasedNumberFormat.SPELLOUT);\r
566         String[][] testData = {\r
567             { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" },\r
568             { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" },\r
569             { "10", "\u0e2a\u0e34\u0e1a" },\r
570             { "11", "\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14" },\r
571             { "21", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14" },\r
572             { "101", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e23\u0e49\u0e2d\u0e22\u200b\u0e2b\u0e19\u0e36\u0e48\u0e07" },\r
573             { "1.234", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e2d\u0e07\u0e2a\u0e32\u0e21\u0e2a\u0e35\u0e48" },\r
574             { "21.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e40\u0e2d\u0e47\u0e14\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },\r
575             { "22.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e2d\u0e07\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },\r
576             { "23.45", "\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e32\u0e21\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },\r
577             { "123.45", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u200b\u0e23\u0e49\u0e2d\u0e22\u200b\u0e22\u0e35\u0e48\u200b\u0e2a\u0e34\u0e1a\u200b\u0e2a\u0e32\u0e21\u200b\u0e08\u0e38\u0e14\u200b\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" },\r
578             { "12,345.678", "\u0E2B\u0E19\u0E36\u0E48\u0E07\u200b\u0E2B\u0E21\u0E37\u0E48\u0E19\u200b\u0E2A\u0E2D\u0E07\u200b\u0E1E\u0E31\u0E19\u200b\u0E2A\u0E32\u0E21\u200b\u0E23\u0E49\u0E2D\u0E22\u200b\u0E2A\u0E35\u0E48\u200b\u0E2A\u0E34\u0E1A\u200b\u0E2B\u0E49\u0E32\u200b\u0E08\u0E38\u0E14\u200b\u0E2B\u0E01\u0E40\u0E08\u0E47\u0E14\u0E41\u0E1B\u0E14" },\r
579         };\r
580 \r
581         doTest(formatter, testData, true);\r
582     }\r
583 \r
584     public void TestFractionalRuleSet() {\r
585 \r
586 \r
587         RuleBasedNumberFormat formatter =\r
588             new RuleBasedNumberFormat(fracRules, Locale.ENGLISH);\r
589 \r
590         String[][] testData = {\r
591             { "0", "0" },\r
592             { "1", "1" },\r
593             { "10", "10" },\r
594             { ".1", "1/10" },\r
595             { ".11", "1/9" },\r
596             { ".125", "1/8" },\r
597             { ".1428", "1/7" },\r
598             { ".1667", "1/6" },\r
599             { ".2", "1/5" },\r
600             { ".25", "1/4" },\r
601             { ".333", "1/3" },\r
602             { ".5", "1/2" },\r
603             { "1.1", "1 1/10" },\r
604             { "2.11", "2 1/9" },\r
605             { "3.125", "3 1/8" },\r
606             { "4.1428", "4 1/7" },\r
607             { "5.1667", "5 1/6" },\r
608             { "6.2", "6 1/5" },\r
609             { "7.25", "7 1/4" },\r
610             { "8.333", "8 1/3" },\r
611             { "9.5", "9 1/2" },\r
612             { ".2222", "2/9" },\r
613             { ".4444", "4/9" },\r
614             { ".5555", "5/9" },\r
615             { "1.2856", "1 2/7" }\r
616         };\r
617         doTest(formatter, testData, false); // exact values aren't parsable from fractions\r
618     }\r
619 \r
620     public void TestSwedishSpellout()\r
621     {\r
622         Locale locale = new Locale("sv", "", "");\r
623         RuleBasedNumberFormat formatter = new RuleBasedNumberFormat(locale, RuleBasedNumberFormat.SPELLOUT);\r
624 \r
625         String[][] testDataDefault = {\r
626             { "101", "ett\u00ADhundra\u00ADett" },\r
627             { "123", "ett\u00ADhundra\u00ADtjugo\u00ADtre" },\r
628             { "1,001", "ettusen ett" },\r
629             { "1,100", "ettusen ett\u00ADhundra" },\r
630             { "1,101", "ettusen ett\u00ADhundra\u00ADett" },\r
631             { "1,234", "ettusen tv\u00e5\u00ADhundra\u00ADtrettio\u00ADfyra" },\r
632             { "10,001", "tio\u00ADtusen ett" },\r
633             { "11,000", "elva\u00ADtusen" },\r
634             { "12,000", "tolv\u00ADtusen" },\r
635             { "20,000", "tjugo-tusen" },\r
636             { "21,000", "tjugo\u00ADett-tusen" },\r
637             { "21,001", "tjugo\u00ADett-tusen ett" },\r
638             { "200,000", "tv\u00e5\u00ADhundra-tusen" },\r
639             { "201,000", "tv\u00e5\u00ADhundra\u00ADett-tusen" },\r
640             { "200,200", "tv\u00e5\u00ADhundra-tusen tv\u00e5\u00ADhundra" },\r
641             { "2,002,000", "tv\u00e5 miljoner tv\u00e5\u00ADtusen" },\r
642             { "12,345,678", "tolv miljoner tre\u00ADhundra\u00ADfyrtio\u00ADfem-tusen sex\u00ADhundra\u00ADsjuttio\u00AD\u00e5tta" },\r
643             { "123,456.789", "ett\u00ADhundra\u00ADtjugo\u00ADtre-tusen fyra\u00ADhundra\u00ADfemtio\u00ADsex komma sju \u00e5tta nio" },\r
644             { "-12,345.678", "minus tolv\u00ADtusen tre\u00ADhundra\u00ADfyrtio\u00ADfem komma sex sju \u00e5tta" }\r
645         };\r
646 \r
647         logln("testing default rules");\r
648         doTest(formatter, testDataDefault, true);\r
649 \r
650         String[][] testDataNeutrum = {\r
651             { "101", "ett\u00adhundra\u00aden" },\r
652             { "1,001", "ettusen en" },\r
653             { "1,101", "ettusen ett\u00adhundra\u00aden" },\r
654             { "10,001", "tio\u00adtusen en" },\r
655             { "21,001", "tjugo\u00aden\u00adtusen en" }\r
656         };\r
657 \r
658         formatter.setDefaultRuleSet("%spellout-cardinal-neutre");\r
659         logln("testing neutrum rules");\r
660         doTest(formatter, testDataNeutrum, true);\r
661 \r
662         String[][] testDataYear = {\r
663             { "101", "ett\u00adhundra\u00adett" },\r
664             { "900", "nio\u00adhundra" },\r
665             { "1,001", "ettusen ett" },\r
666             { "1,100", "elva\u00adhundra" },\r
667             { "1,101", "elva\u00adhundra\u00adett" },\r
668             { "1,234", "tolv\u00adhundra\u00adtrettio\u00adfyra" },\r
669             { "2,001", "tjugo\u00adhundra\u00adett" },\r
670             { "10,001", "tio\u00adtusen ett" }\r
671         };\r
672 \r
673         formatter.setDefaultRuleSet("%spellout-numbering-year");\r
674         logln("testing year rules");\r
675         doTest(formatter, testDataYear, true);\r
676     }\r
677 \r
678     public void TestBigNumbers() {\r
679         BigInteger bigI = new BigInteger("1234567890", 10);\r
680         StringBuffer buf = new StringBuffer();\r
681         RuleBasedNumberFormat fmt = new RuleBasedNumberFormat(RuleBasedNumberFormat.SPELLOUT);\r
682         fmt.format(bigI, buf, null);\r
683         logln("big int: " + buf.toString());\r
684 \r
685         buf.setLength(0);\r
686         java.math.BigDecimal bigD = new java.math.BigDecimal(bigI);\r
687         fmt.format(bigD, buf, null);\r
688         logln("big dec: " + buf.toString());\r
689     }\r
690 \r
691   public void TestTrailingSemicolon() {\r
692     String thaiRules = \r
693         "%default:\n" +\r
694         "  -x: \u0e25\u0e1a>>;\n" +\r
695         "  x.x: <<\u0e08\u0e38\u0e14>>>;\n" +\r
696         "  \u0e28\u0e39\u0e19\u0e22\u0e4c; \u0e2b\u0e19\u0e36\u0e48\u0e07; \u0e2a\u0e2d\u0e07; \u0e2a\u0e32\u0e21;\n" +\r
697         "  \u0e2a\u0e35\u0e48; \u0e2b\u0e49\u0e32; \u0e2b\u0e01; \u0e40\u0e08\u0e47\u0e14; \u0e41\u0e1b\u0e14;\n" +\r
698         "  \u0e40\u0e01\u0e49\u0e32; \u0e2a\u0e34\u0e1a; \u0e2a\u0e34\u0e1a\u0e40\u0e2d\u0e47\u0e14;\n" +\r
699         "  \u0e2a\u0e34\u0e1a\u0e2a\u0e2d\u0e07; \u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21;\n" +\r
700         "  \u0e2a\u0e34\u0e1a\u0e2a\u0e35\u0e48; \u0e2a\u0e34\u0e1a\u0e2b\u0e49\u0e32;\n" +\r
701         "  \u0e2a\u0e34\u0e1a\u0e2b\u0e01; \u0e2a\u0e34\u0e1a\u0e40\u0e08\u0e47\u0e14;\n" +\r
702         "  \u0e2a\u0e34\u0e1a\u0e41\u0e1b\u0e14; \u0e2a\u0e34\u0e1a\u0e40\u0e01\u0e49\u0e32;\n" +\r
703         "  20: \u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +\r
704         "  30: \u0e2a\u0e32\u0e21\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +\r
705         "  40: \u0e2a\u0e35\u0e48\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +\r
706         "  50: \u0e2b\u0e49\u0e32\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +\r
707         "  60: \u0e2b\u0e01\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +\r
708         "  70: \u0e40\u0e08\u0e47\u0e14\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +\r
709         "  80: \u0e41\u0e1b\u0e14\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +\r
710         "  90: \u0e40\u0e01\u0e49\u0e32\u0e2a\u0e34\u0e1a[>%%alt-ones>];\n" +\r
711         "  100: <<\u0e23\u0e49\u0e2d\u0e22[>>];\n" +\r
712         "  1000: <<\u0e1e\u0e31\u0e19[>>];\n" +\r
713         "  10000: <<\u0e2b\u0e21\u0e37\u0e48\u0e19[>>];\n" +\r
714         "  100000: <<\u0e41\u0e2a\u0e19[>>];\n" +\r
715         "  1,000,000: <<\u0e25\u0e49\u0e32\u0e19[>>];\n" +\r
716         "  1,000,000,000: <<\u0e1e\u0e31\u0e19\u0e25\u0e49\u0e32\u0e19[>>];\n" +\r
717         "  1,000,000,000,000: <<\u0e25\u0e49\u0e32\u0e19\u0e25\u0e49\u0e32\u0e19[>>];\n" +\r
718         "  1,000,000,000,000,000: =#,##0=;\n" +\r
719         "%%alt-ones:\n" +\r
720         "  \u0e28\u0e39\u0e19\u0e22\u0e4c;\n" +\r
721         "  \u0e40\u0e2d\u0e47\u0e14;\n" +\r
722         "  =%default=;\n ; ;; ";\r
723 \r
724         RuleBasedNumberFormat formatter\r
725             = new RuleBasedNumberFormat(thaiRules, new Locale("th", "TH", ""));\r
726 \r
727         String[][] testData = {\r
728             { "0", "\u0e28\u0e39\u0e19\u0e22\u0e4c" },\r
729             { "1", "\u0e2b\u0e19\u0e36\u0e48\u0e07" },\r
730             { "123.45", "\u0e2b\u0e19\u0e36\u0e48\u0e07\u0e23\u0e49\u0e2d\u0e22\u0e22\u0e35\u0e48\u0e2a\u0e34\u0e1a\u0e2a\u0e32\u0e21\u0e08\u0e38\u0e14\u0e2a\u0e35\u0e48\u0e2b\u0e49\u0e32" }\r
731         };\r
732         \r
733         doTest(formatter, testData, true);\r
734     }\r
735 \r
736     public void TestSmallValues() {\r
737     String[][] testData = {\r
738         { "0.001", "zero point zero zero one" },\r
739         { "0.0001", "zero point zero zero zero one" },\r
740         { "0.00001", "zero point zero zero zero zero one" },\r
741         { "0.000001", "zero point zero zero zero zero zero one" },\r
742         { "0.0000001", "zero point zero zero zero zero zero zero one" },\r
743         { "0.00000001", "zero point zero zero zero zero zero zero zero one" },\r
744         { "0.000000001", "zero point zero zero zero zero zero zero zero zero one" },\r
745         { "0.0000000001", "zero point zero zero zero zero zero zero zero zero zero one" },\r
746         { "0.00000000001", "zero point zero zero zero zero zero zero zero zero zero zero one" },\r
747         { "0.000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero one" },\r
748         { "0.0000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero one" },\r
749         { "0.00000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero one" },\r
750         { "0.000000000000001", "zero point zero zero zero zero zero zero zero zero zero zero zero zero zero zero one" },\r
751         { "10,000,000.001", "ten million point zero zero one" },\r
752         { "10,000,000.0001", "ten million point zero zero zero one" },\r
753         { "10,000,000.00001", "ten million point zero zero zero zero one" },\r
754         { "10,000,000.000001", "ten million point zero zero zero zero zero one" },\r
755         { "10,000,000.0000001", "ten million point zero zero zero zero zero zero one" },\r
756         { "10,000,000.00000001", "ten million point zero zero zero zero zero zero zero one" },\r
757         { "10,000,000.000000002", "ten million point zero zero zero zero zero zero zero zero two" },\r
758         { "10,000,000", "ten million" },\r
759         { "1,234,567,890.0987654", "one billion two hundred thirty-four million five hundred sixty-seven thousand eight hundred ninety point zero nine eight seven six five four" },\r
760         { "123,456,789.9876543", "one hundred twenty-three million four hundred fifty-six thousand seven hundred eighty-nine point nine eight seven six five four three" },\r
761         { "12,345,678.87654321", "twelve million three hundred forty-five thousand six hundred seventy-eight point eight seven six five four three two one" },\r
762         { "1,234,567.7654321", "one million two hundred thirty-four thousand five hundred sixty-seven point seven six five four three two one" },\r
763         { "123,456.654321", "one hundred twenty-three thousand four hundred fifty-six point six five four three two one" },\r
764         { "12,345.54321", "twelve thousand three hundred forty-five point five four three two one" },\r
765         { "1,234.4321", "one thousand two hundred thirty-four point four three two one" },\r
766         { "123.321", "one hundred twenty-three point three two one" },\r
767         { "0.0000000011754944", "zero point zero zero zero zero zero zero zero zero one one seven five four nine four four" },\r
768         { "0.000001175494351", "zero point zero zero zero zero zero one one seven five four nine four three five one" },\r
769     };\r
770 \r
771     RuleBasedNumberFormat formatter\r
772         = new RuleBasedNumberFormat(Locale.US, RuleBasedNumberFormat.SPELLOUT);\r
773     doTest(formatter, testData, true);\r
774     }\r
775 \r
776     public void TestRuleSetDisplayName() {\r
777         ULocale.setDefault(ULocale.US);\r
778         String[][] localizations = new String[][] {\r
779             /* public rule sets*/\r
780             {"%simplified", "%default", "%ordinal"},\r
781             /* display names in "en_US" locale*/\r
782             {"en_US", "Simplified", "Default", "Ordinal"},\r
783             /* display names in "zh_Hans" locale*/\r
784             {"zh_Hans", "\u7B80\u5316", "\u7F3A\u7701",  "\u5E8F\u5217"},\r
785             /* display names in a fake locale*/\r
786             {"foo_Bar_BAZ", "Simplified", "Default", "Ordinal"}\r
787         };\r
788         \r
789         //Construct RuleBasedNumberFormat by rule sets and localizations list\r
790         RuleBasedNumberFormat formatter\r
791             = new RuleBasedNumberFormat(ukEnglish, localizations, ULocale.US);\r
792         RuleBasedNumberFormat f2= new RuleBasedNumberFormat(ukEnglish, localizations);\r
793         assertTrue("Check the two formatters' equality", formatter.equals(f2));        \r
794 \r
795         //get displayName by name\r
796         String[] ruleSetNames = formatter.getRuleSetNames();\r
797         for (int i=0; i<ruleSetNames.length; i++) {\r
798             logln("Rule set name: " + ruleSetNames[i]);\r
799             String RSName_defLoc = formatter.getRuleSetDisplayName(ruleSetNames[i]);\r
800             assertEquals("Display name in default locale", localizations[1][i+1], RSName_defLoc);\r
801             String RSName_loc = formatter.getRuleSetDisplayName(ruleSetNames[i], ULocale.CHINA);\r
802             assertEquals("Display name in Chinese", localizations[2][i+1], RSName_loc);\r
803         }\r
804                 \r
805         // getDefaultRuleSetName\r
806         String defaultRS = formatter.getDefaultRuleSetName();\r
807         //you know that the default rule set is %simplified according to rule sets string ukEnglish\r
808         assertEquals("getDefaultRuleSetName", "%simplified", defaultRS);\r
809         \r
810         //get locales of localizations\r
811         ULocale[] locales = formatter.getRuleSetDisplayNameLocales();\r
812         for (int i=0; i<locales.length; i++) {\r
813             logln(locales[i].getName());\r
814         }\r
815         \r
816         //get displayNames\r
817         String[] RSNames_defLoc = formatter.getRuleSetDisplayNames();\r
818         for (int i=0; i<RSNames_defLoc.length; i++) {\r
819             assertEquals("getRuleSetDisplayNames in default locale", localizations[1][i+1], RSNames_defLoc[i]);\r
820         }\r
821         \r
822         String[] RSNames_loc = formatter.getRuleSetDisplayNames(ULocale.UK);\r
823         for (int i=0; i<RSNames_loc.length; i++) {\r
824             assertEquals("getRuleSetDisplayNames in English", localizations[1][i+1], RSNames_loc[i]);\r
825         }    \r
826         \r
827         RSNames_loc = formatter.getRuleSetDisplayNames(ULocale.CHINA);\r
828         for (int i=0; i<RSNames_loc.length; i++) {\r
829             assertEquals("getRuleSetDisplayNames in Chinese", localizations[2][i+1], RSNames_loc[i]);\r
830         }        \r
831 \r
832         RSNames_loc = formatter.getRuleSetDisplayNames(new ULocale("foo_Bar_BAZ"));\r
833         for (int i=0; i<RSNames_loc.length; i++) {\r
834             assertEquals("getRuleSetDisplayNames in fake locale", localizations[3][i+1], RSNames_loc[i]);\r
835         }              \r
836     }\r
837 \r
838     public void TestAllLocales() {\r
839         StringBuffer errors = null;\r
840         ULocale[] locales = ULocale.getAvailableLocales();\r
841         String[] names = {\r
842             " (spellout) ",\r
843             " (ordinal)  ",\r
844             " (duration) "\r
845         };\r
846         double[] numbers = {45.678, 1, 2, 10, 11, 100, 110, 200, 1000, 1111, -1111};\r
847         Random r = null;\r
848 \r
849         // RBNF parse is extremely slow when lenient option is enabled.\r
850         // For non-exhaustive mode, we only test a few locales.\r
851         // "nl_NL", "be" had crash problem reported by #6534\r
852         String[] parseLocales = {"en_US", "nl_NL", "be"};\r
853 \r
854         for (int i = 0; i < locales.length; ++i) {\r
855             ULocale loc = locales[i];\r
856             int count = numbers.length;\r
857             boolean testParse = true;\r
858             if (getInclusion() <= 5) {\r
859                 testParse = false;\r
860                 for (int k = 0; k < parseLocales.length; k++) {\r
861                     if (loc.toString().equals(parseLocales[k])) {\r
862                         testParse = true;\r
863                         break;\r
864                     }\r
865                 }\r
866             } else {\r
867                 //RBNF parse is too slow.  Increase count only for debugging purpose for now.\r
868                 //count = 100;\r
869             }\r
870 \r
871             for (int j = 0; j < 3; ++j) {\r
872                 RuleBasedNumberFormat fmt = new RuleBasedNumberFormat(loc, j+1);\r
873 \r
874                 for (int c = 0; c < count; c++) {\r
875                     double n;\r
876                     if (c < numbers.length) {\r
877                         n = numbers[c];\r
878                     } else {\r
879                         if (r == null) {\r
880                             r = createRandom();\r
881                         }\r
882                         n = ((int)(r.nextInt(10000) - 3000)) / 16d;\r
883                     }\r
884 \r
885                     String s = fmt.format(n);\r
886                     logln(loc.getName() + names[j] + "success format: " + n + " -> " + s);\r
887 \r
888                     if (testParse) {\r
889                         // We do not validate the result in this test case,\r
890                         // because there are cases which do not round trip by design.\r
891                         try {\r
892                             // non-lenient parse\r
893                             fmt.setLenientParseMode(false);\r
894                             Number num = fmt.parse(s);\r
895                             logln(loc.getName() + names[j] + "success parse: " + s + " -> " + num);\r
896                         } catch (ParseException pe) {\r
897                             String msg = loc.getName() + names[j] + "ERROR:" + pe.getMessage();\r
898                             logln(msg);\r
899                             if (errors == null) {\r
900                                 errors = new StringBuffer();\r
901                             }\r
902                             errors.append("\n" + msg);\r
903                         }\r
904                     }\r
905                 }\r
906             }\r
907         }\r
908         if (errors != null) {\r
909             //TODO: We need to fix parse problems - see #6895 / #6896\r
910             //errln(errors.toString());\r
911             logln(errors.toString());\r
912         }\r
913     }\r
914 \r
915     void doTest(RuleBasedNumberFormat formatter, String[][] testData,\r
916                 boolean testParsing) {\r
917     //        NumberFormat decFmt = NumberFormat.getInstance(Locale.US);\r
918     NumberFormat decFmt = new DecimalFormat("#,###.################");\r
919         try {\r
920             for (int i = 0; i < testData.length; i++) {\r
921                 String number = testData[i][0];\r
922                 String expectedWords = testData[i][1];\r
923                 logln("test[" + i + "] number: " + number + " target: " + expectedWords);\r
924                 Number num = decFmt.parse(number);\r
925                 String actualWords = formatter.format(num);\r
926 \r
927                 if (!actualWords.equals(expectedWords)) {\r
928                     errln("Spot check format failed: for " + number + ", expected\n    "\r
929                           + expectedWords + ", but got\n    " +\r
930                           actualWords);\r
931                 }\r
932                 else if (testParsing) {\r
933                     String actualNumber = decFmt.format(formatter\r
934                                                         .parse(actualWords));\r
935 \r
936                     if (!actualNumber.equals(number)) {\r
937                         errln("Spot check parse failed: for " + actualWords +\r
938                               ", expected " + number + ", but got " +\r
939                               actualNumber);\r
940                     }\r
941                 }\r
942             }\r
943         }\r
944         catch (Throwable e) {\r
945             e.printStackTrace();\r
946             errln("Test failed with exception: " + e.toString());\r
947         }\r
948     }\r
949 \r
950     /**\r
951      * Spellout rules for U.K. English.  \r
952      * I borrow the rule sets for TestRuleSetDisplayName()\r
953      */\r
954     public static final String ukEnglish =\r
955         "%simplified:\n"\r
956         + "    -x: minus >>;\n"\r
957         + "    x.x: << point >>;\n"\r
958         + "    zero; one; two; three; four; five; six; seven; eight; nine;\n"\r
959         + "    ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"\r
960         + "        seventeen; eighteen; nineteen;\n"\r
961         + "    20: twenty[->>];\n"\r
962         + "    30: thirty[->>];\n"\r
963         + "    40: forty[->>];\n"\r
964         + "    50: fifty[->>];\n"\r
965         + "    60: sixty[->>];\n"\r
966         + "    70: seventy[->>];\n"\r
967         + "    80: eighty[->>];\n"\r
968         + "    90: ninety[->>];\n"\r
969         + "    100: << hundred[ >>];\n"\r
970         + "    1000: << thousand[ >>];\n"\r
971         + "    1,000,000: << million[ >>];\n"\r
972         + "    1,000,000,000,000: << billion[ >>];\n"\r
973         + "    1,000,000,000,000,000: =#,##0=;\n"\r
974         + "%alt-teens:\n"\r
975         + "    =%simplified=;\n"\r
976         + "    1000>: <%%alt-hundreds<[ >>];\n"\r
977         + "    10,000: =%simplified=;\n"\r
978         + "    1,000,000: << million[ >%simplified>];\n"\r
979         + "    1,000,000,000,000: << billion[ >%simplified>];\n"\r
980         + "    1,000,000,000,000,000: =#,##0=;\n"\r
981         + "%%alt-hundreds:\n"\r
982         + "    0: SHOULD NEVER GET HERE!;\n"\r
983         + "    10: <%simplified< thousand;\n"\r
984         + "    11: =%simplified= hundred>%%empty>;\n"\r
985         + "%%empty:\n"\r
986         + "    0:;"\r
987         + "%ordinal:\n"\r
988         + "    zeroth; first; second; third; fourth; fifth; sixth; seventh;\n"\r
989         + "        eighth; ninth;\n"\r
990         + "    tenth; eleventh; twelfth; thirteenth; fourteenth;\n"\r
991         + "        fifteenth; sixteenth; seventeenth; eighteenth;\n"\r
992         + "        nineteenth;\n"\r
993         + "    twentieth; twenty->>;\n"\r
994         + "    30: thirtieth; thirty->>;\n"\r
995         + "    40: fortieth; forty->>;\n"\r
996         + "    50: fiftieth; fifty->>;\n"\r
997         + "    60: sixtieth; sixty->>;\n"\r
998         + "    70: seventieth; seventy->>;\n"\r
999         + "    80: eightieth; eighty->>;\n"\r
1000         + "    90: ninetieth; ninety->>;\n"\r
1001         + "    100: <%simplified< hundredth; <%simplified< hundred >>;\n"\r
1002         + "    1000: <%simplified< thousandth; <%simplified< thousand >>;\n"\r
1003         + "    1,000,000: <%simplified< millionth; <%simplified< million >>;\n"\r
1004         + "    1,000,000,000,000: <%simplified< billionth;\n"\r
1005         + "        <%simplified< billion >>;\n"\r
1006         + "    1,000,000,000,000,000: =#,##0=;"\r
1007         + "%default:\n"\r
1008         + "    -x: minus >>;\n"\r
1009         + "    x.x: << point >>;\n"\r
1010         + "    =%simplified=;\n"\r
1011         + "    100: << hundred[ >%%and>];\n"\r
1012         + "    1000: << thousand[ >%%and>];\n"\r
1013         + "    100,000>>: << thousand[>%%commas>];\n"\r
1014         + "    1,000,000: << million[>%%commas>];\n"\r
1015         + "    1,000,000,000,000: << billion[>%%commas>];\n"\r
1016         + "    1,000,000,000,000,000: =#,##0=;\n"\r
1017         + "%%and:\n"\r
1018         + "    and =%default=;\n"\r
1019         + "    100: =%default=;\n"\r
1020         + "%%commas:\n"\r
1021         + "    ' and =%default=;\n"\r
1022         + "    100: , =%default=;\n"\r
1023         + "    1000: , <%default< thousand, >%default>;\n"\r
1024         + "    1,000,000: , =%default=;"\r
1025         + "%%lenient-parse:\n"\r
1026         + "    & ' ' , ',' ;\n";\r
1027     \r
1028     /* Tests the method\r
1029      *      public boolean equals(Object that)\r
1030      */\r
1031     public void TestEquals(){\r
1032         // Tests when "if (!(that instanceof RuleBasedNumberFormat))" is true\r
1033         RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat("dummy");\r
1034         if( rbnf.equals(new String("dummy")) != false ||\r
1035             rbnf.equals(new Character('a')) != false ||\r
1036             rbnf.equals(new Object()) != false ||\r
1037             rbnf.equals(-1) != false ||\r
1038             rbnf.equals(0) != false ||\r
1039             rbnf.equals(1) != false ||\r
1040             rbnf.equals(-1.0) != false ||\r
1041             rbnf.equals(0.0) != false ||\r
1042             rbnf.equals(1.0) != false){\r
1043             errln("RuleBasedNumberFormat.equals(Object that) was suppose to " +\r
1044                     "be false for an invalid object.");\r
1045         }\r
1046         \r
1047         // Tests when\r
1048         // "if (!locale.equals(that2.locale) || lenientParse != that2.lenientParse)"\r
1049         // is true\r
1050         RuleBasedNumberFormat rbnf1 = new RuleBasedNumberFormat("dummy", new Locale("en"));\r
1051         RuleBasedNumberFormat rbnf2 = new RuleBasedNumberFormat("dummy", new Locale("jp"));\r
1052         RuleBasedNumberFormat rbnf3 = new RuleBasedNumberFormat("dummy", new Locale("sp"));\r
1053         RuleBasedNumberFormat rbnf4 = new RuleBasedNumberFormat("dummy", new Locale("fr"));\r
1054         \r
1055         if(rbnf1.equals(rbnf2) != false || rbnf1.equals(rbnf3) != false ||\r
1056                 rbnf1.equals(rbnf4) != false || rbnf2.equals(rbnf3) != false ||\r
1057                 rbnf2.equals(rbnf4) != false || rbnf3.equals(rbnf4) != false){\r
1058             errln("RuleBasedNumberFormat.equals(Object that) was suppose to " +\r
1059             "be false for an invalid object.");\r
1060         }\r
1061         \r
1062         if(rbnf1.equals(rbnf1) == false){\r
1063             errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " +\r
1064             "be false for an invalid object.");\r
1065         }\r
1066         \r
1067         if(rbnf2.equals(rbnf2) == false){\r
1068             errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " +\r
1069             "be false for an invalid object.");\r
1070         }\r
1071         \r
1072         if(rbnf3.equals(rbnf3) == false){\r
1073             errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " +\r
1074             "be false for an invalid object.");\r
1075         }\r
1076         \r
1077         if(rbnf4.equals(rbnf4) == false){\r
1078             errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " +\r
1079             "be false for an invalid object.");\r
1080         }\r
1081         \r
1082         RuleBasedNumberFormat rbnf5 = new RuleBasedNumberFormat("dummy", new Locale("en"));\r
1083         RuleBasedNumberFormat rbnf6 = new RuleBasedNumberFormat("dummy", new Locale("en"));\r
1084         \r
1085         if(rbnf5.equals(rbnf6) == false){\r
1086             errln("RuleBasedNumberFormat.equals(Object that) was not suppose to " +\r
1087             "be false for an invalid object.");\r
1088         }\r
1089         rbnf6.setLenientParseMode(true);\r
1090         \r
1091         if(rbnf5.equals(rbnf6) != false){\r
1092             errln("RuleBasedNumberFormat.equals(Object that) was suppose to " +\r
1093             "be false for an invalid object.");\r
1094         }\r
1095 \r
1096         // Tests when "if (!ruleSets[i].equals(that2.ruleSets[i]))" is true\r
1097         RuleBasedNumberFormat rbnf7 = new RuleBasedNumberFormat("not_dummy", new Locale("en"));\r
1098         if(rbnf5.equals(rbnf7) != false){\r
1099             errln("RuleBasedNumberFormat.equals(Object that) was suppose to " +\r
1100             "be false for an invalid object.");\r
1101         }\r
1102     }\r
1103     \r
1104     /* Tests the method\r
1105      *      public ULocale[] getRuleSetDisplayNameLocales()\r
1106      */\r
1107     public void TestGetRuleDisplayNameLocales(){\r
1108         // Tests when "if (ruleSetDisplayNames != null" is false\r
1109         RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat("dummy");\r
1110         rbnf.getRuleSetDisplayNameLocales();\r
1111         if(rbnf.getRuleSetDisplayNameLocales() != null){\r
1112             errln("RuleBasedNumberFormat.getRuleDisplayNameLocales() was suppose to " +\r
1113             "return null.");\r
1114         }\r
1115     }\r
1116     \r
1117     /* Tests the method\r
1118      *      private String[] getNameListForLocale(ULocale loc)\r
1119      *      public String[] getRuleSetDisplayNames(ULocale loc)\r
1120      */\r
1121     public void TestGetNameListForLocale(){\r
1122         // Tests when "if (names != null)" is false and\r
1123         //  "if (loc != null && ruleSetDisplayNames != null)" is false\r
1124         RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat("dummy");\r
1125         rbnf.getRuleSetDisplayNames(null);\r
1126         try{\r
1127             rbnf.getRuleSetDisplayNames(null);\r
1128         } catch(Exception e){\r
1129             errln("RuleBasedNumberFormat.getRuleSetDisplayNames(ULocale loc) " +\r
1130                     "was not suppose to have an exception.");\r
1131         }\r
1132     }\r
1133 \r
1134     /* Tests the method\r
1135      *      public String getRuleSetDisplayName(String ruleSetName, ULocale loc)\r
1136      */\r
1137     public void TestGetRulesSetDisplayName(){\r
1138         RuleBasedNumberFormat rbnf = new RuleBasedNumberFormat("dummy");\r
1139         //rbnf.getRuleSetDisplayName("dummy", new ULocale("en_US"));\r
1140         \r
1141         // Tests when "if (names != null) " is true\r
1142 \r
1143         // Tests when the method throws an exception\r
1144         try{\r
1145             rbnf.getRuleSetDisplayName("", new ULocale("en_US"));\r
1146             errln("RuleBasedNumberFormat.getRuleSetDisplayName(String ruleSetName, ULocale loc) " +\r
1147                 "was suppose to have an exception.");\r
1148         } catch(Exception e){}\r
1149         \r
1150         try{\r
1151             rbnf.getRuleSetDisplayName("dummy", new ULocale("en_US"));\r
1152             errln("RuleBasedNumberFormat.getRuleSetDisplayName(String ruleSetName, ULocale loc) " +\r
1153                 "was suppose to have an exception.");\r
1154         } catch(Exception e){}\r
1155     }\r
1156     \r
1157     /* Test the method\r
1158      *      public void process(StringBuffer buf, NFRuleSet ruleSet)\r
1159      */\r
1160     public void TestChineseProcess(){\r
1161         String ruleWithChinese =\r
1162             "%simplified:\n"\r
1163             + "    -x: minus >>;\n"\r
1164             + "    x.x: << point >>;\n"\r
1165             + "    zero; one; two; three; four; five; six; seven; eight; nine;\n"\r
1166             + "    ten; eleven; twelve; thirteen; fourteen; fifteen; sixteen;\n"\r
1167             + "        seventeen; eighteen; nineteen;\n"\r
1168             + "    20: twenty[->>];\n"\r
1169             + "    30: thirty[->>];\n"\r
1170             + "    40: forty[->>];\n"\r
1171             + "    50: fifty[->>];\n"\r
1172             + "    60: sixty[->>];\n"\r
1173             + "    70: seventy[->>];\n"\r
1174             + "    80: eighty[->>];\n"\r
1175             + "    90: ninety[->>];\n"\r
1176             + "    100: << hundred[ >>];\n"\r
1177             + "    1000: << thousand[ >>];\n"\r
1178             + "    1,000,000: << million[ >>];\n"\r
1179             + "    1,000,000,000,000: << billion[ >>];\n"\r
1180             + "    1,000,000,000,000,000: =#,##0=;\n"\r
1181             + "%alt-teens:\n"\r
1182             + "    =%simplified=;\n"\r
1183             + "    1000>: <%%alt-hundreds<[ >>];\n"\r
1184             + "    10,000: =%simplified=;\n"\r
1185             + "    1,000,000: << million[ >%simplified>];\n"\r
1186             + "    1,000,000,000,000: << billion[ >%simplified>];\n"\r
1187             + "    1,000,000,000,000,000: =#,##0=;\n"\r
1188             + "%%alt-hundreds:\n"\r
1189             + "    0: SHOULD NEVER GET HERE!;\n"\r
1190             + "    10: <%simplified< thousand;\n"\r
1191             + "    11: =%simplified= hundred>%%empty>;\n"\r
1192             + "%%empty:\n"\r
1193             + "    0:;"\r
1194             + "%accounting:\n"\r
1195             + "    \u842c; \u842c; \u842c; \u842c; \u842c; \u842c; \u842c; \u842c;\n"\r
1196             + "        \u842c; \u842c;\n"\r
1197             + "    \u842c; \u842c; \u842c; \u842c; \u842c;\n"\r
1198             + "        \u842c; \u842c; \u842c; \u842c;\n"\r
1199             + "        \u842c;\n"\r
1200             + "    twentieth; \u96f6|>>;\n"\r
1201             + "    30: \u96f6; \u96f6|>>;\n"\r
1202             + "    40: \u96f6; \u96f6|>>;\n"\r
1203             + "    50: \u96f6; \u96f6|>>;\n"\r
1204             + "    60: \u96f6; \u96f6|>>;\n"\r
1205             + "    70: \u96f6; \u96f6|>>;\n"\r
1206             + "    80: \u96f6; \u96f6|>>;\n"\r
1207             + "    90: \u96f6; \u96f6|>>;\n"\r
1208             + "    100: <%simplified< \u96f6; <%simplified< \u96f6 >>;\n"\r
1209             + "    1000: <%simplified< \u96f6; <%simplified< \u96f6 >>;\n"\r
1210             + "    1,000,000: <%simplified< \u96f6; <%simplified< \u96f6 >>;\n"\r
1211             + "    1,000,000,000,000: <%simplified< \u96f6;\n"\r
1212             + "        <%simplified< \u96f6 >>;\n"\r
1213             + "    1,000,000,000,000,000: =#,##0=;"\r
1214             + "%default:\n"\r
1215             + "    -x: minus >>;\n"\r
1216             + "    x.x: << point >>;\n"\r
1217             + "    =%simplified=;\n"\r
1218             + "    100: << hundred[ >%%and>];\n"\r
1219             + "    1000: << thousand[ >%%and>];\n"\r
1220             + "    100,000>>: << thousand[>%%commas>];\n"\r
1221             + "    1,000,000: << million[>%%commas>];\n"\r
1222             + "    1,000,000,000,000: << billion[>%%commas>];\n"\r
1223             + "    1,000,000,000,000,000: =#,##0=;\n"\r
1224             + "%%and:\n"\r
1225             + "    and =%default=;\n"\r
1226             + "    100: =%default=;\n"\r
1227             + "%%commas:\n"\r
1228             + "    ' and =%default=;\n"\r
1229             + "    100: , =%default=;\n"\r
1230             + "    1000: , <%default< thousand, >%default>;\n"\r
1231             + "    1,000,000: , =%default=;"\r
1232             + "%traditional:\n"\r
1233             + "    -x: \u3007| >>;\n"\r
1234             + "    x.x: << \u9ede >>;\n"\r
1235             + "    \u842c; \u842c; \u842c; \u842c; \u842c; \u842c; \u842c; \u842c; \u842c; \u842c;\n"\r
1236             + "    \u842c; \u842c; \u842c; \u842c; \u842c; \u842c; \u842c;\n"\r
1237             + "        \u842c; \u842c; \u842c;\n"\r
1238             + "    20: \u842c[->>];\n"\r
1239             + "    30: \u842c[->>];\n"\r
1240             + "    40: \u842c[->>];\n"\r
1241             + "    50: \u842c[->>];\n"\r
1242             + "    60: \u842c[->>];\n"\r
1243             + "    70: \u842c[->>];\n"\r
1244             + "    80: \u842c[->>];\n"\r
1245             + "    90: \u842c[->>];\n"\r
1246             + "    100: << \u842c[ >>];\n"\r
1247             + "    1000: << \u842c[ >>];\n"\r
1248             + "    1,000,000: << \u842c[ >>];\n"\r
1249             + "    1,000,000,000,000: << \u842c[ >>];\n"\r
1250             + "    1,000,000,000,000,000: =#,##0=;\n"\r
1251             + "%time:\n"\r
1252             + "    =0= sec.;\n"\r
1253             + "    60: =%%min-sec=;\n"\r
1254             + "    3600: =%%hr-min-sec=;\n"\r
1255             + "%%min-sec:\n"\r
1256             + "    0: *=00=;\n"\r
1257             + "    60/60: <0<>>;\n"\r
1258             + "%%hr-min-sec:\n"\r
1259             + "    0: *=00=;\n"\r
1260             + "    60/60: <00<>>;\n"\r
1261             + "    3600/60: <#,##0<:>>>;\n"\r
1262             + "%%post-process:com.ibm.icu.text.RBNFChinesePostProcessor\n";\r
1263         \r
1264         RuleBasedNumberFormat rbnf =  new RuleBasedNumberFormat(ruleWithChinese, ULocale.CHINESE);\r
1265         String[] ruleNames = rbnf.getRuleSetNames();\r
1266         try{\r
1267             // Test with "null" rules\r
1268             rbnf.format(0.0,null);\r
1269             errln("This was suppose to return an exception for a null format");\r
1270         } catch(Exception e){}\r
1271         for(int i=0; i<ruleNames.length; i++){\r
1272             try{\r
1273                 rbnf.format(-123450.6789,ruleNames[i]);\r
1274             } catch(Exception e){\r
1275                 errln("RBNFChinesePostProcessor was not suppose to return an exception " +\r
1276                         "when being formatted with parameters 0.0 and " + ruleNames[i]);\r
1277             }\r
1278         }\r
1279     }\r
1280 }\r