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