1/*
2 *******************************************************************************
3 * Copyright (C) 1996-2015, Google, International Business Machines Corporation and
4 * others. All Rights Reserved.                                                *
5 *******************************************************************************
6 */
7package com.ibm.icu.dev.test.format;
8
9import java.text.AttributedCharacterIterator;
10import java.text.CharacterIterator;
11import java.text.FieldPosition;
12import java.util.Collection;
13import java.util.HashMap;
14import java.util.LinkedHashSet;
15import java.util.Locale;
16import java.util.Map;
17
18import com.ibm.icu.dev.test.TestFmwk;
19import com.ibm.icu.text.CompactDecimalFormat;
20import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
21import com.ibm.icu.text.DecimalFormatSymbols;
22import com.ibm.icu.text.NumberFormat;
23import com.ibm.icu.text.PluralRules;
24import com.ibm.icu.util.ULocale;
25
26public class CompactDecimalFormatTest extends TestFmwk {
27
28    public static void main(String[] args) {
29        new CompactDecimalFormatTest().run(args);
30    }
31
32    Object[][] EnglishTestData = {
33            // default is 2 digits of accuracy
34            {0.0d, "0"},
35            {0.01d, "0.01"},
36            {0.1d, "0.1"},
37            {1d, "1"},
38            {12, "12"},
39            {123, "120"},
40            {1234, "1.2K"},
41            {1000, "1K"},
42            {1049, "1K"},
43            {12345, "12K"},
44            {123456, "120K"},
45            {1234567, "1.2M"},
46            {12345678, "12M"},
47            {123456789, "120M"},
48            {1234567890, "1.2B"},
49            {12345678901f, "12B"},
50            {123456789012f, "120B"},
51            {1234567890123f, "1.2T"},
52            {12345678901234f, "12T"},
53            {123456789012345f, "120T"},
54            {12345678901234567890f, "12000000T"},
55    };
56
57    Object[][] SerbianTestDataShort = {
58            {1234, "1,2\u00A0\u0445\u0438\u0459."},
59            {12345, "12\u00a0хиљ."},
60            {20789, "21\u00a0хиљ."},
61            {123456, "120\u00a0хиљ."},
62            {1234567, "1,2\u00a0мил."},
63            {12345678, "12\u00a0мил."},
64            {123456789, "120\u00a0мил."},
65            {1234567890, "1,2\u00a0млрд."},
66            {12345678901f, "12\u00a0млрд."},
67            {123456789012f, "120\u00a0млрд."},
68            {1234567890123f, "1,2\u00a0бил."},
69            {12345678901234f, "12\u00a0бил."},
70            {123456789012345f, "120\u00a0бил."},
71            {1234567890123456f, "1200\u00a0бил."},
72    };
73
74    Object[][] SerbianTestDataLong = {
75            {1234, "1,2 хиљаде"},
76            {12345, "12 хиљада"},
77            {21789, "22 хиљаде"},
78            {123456, "120 хиљада"},
79            {999999, "1 милион"},
80            {1234567, "1,2 милиона"},
81            {12345678, "12 милиона"},
82            {123456789, "120 милиона"},
83            {1234567890, "1,2 милијарде"},
84            {12345678901f, "12 милијарди"},
85            {20890123456f, "21 милијарда"},
86            {21890123456f, "22 милијарде"},
87            {123456789012f, "120 милијарди"},
88            {1234567890123f, "1,2 трилиона"},
89            {12345678901234f, "12 трилиона"},
90            {123456789012345f, "120 трилиона"},
91            {1234567890123456f, "1.200 трилиона"},
92    };
93
94    Object[][] SerbianTestDataLongNegative = {
95            {-1234, "-1,2 хиљаде"},
96            {-12345, "-12 хиљада"},
97            {-21789, "-22 хиљаде"},
98            {-123456, "-120 хиљада"},
99            {-999999, "-1 милион"},
100            {-1234567, "-1,2 милиона"},
101            {-12345678, "-12 милиона"},
102            {-123456789, "-120 милиона"},
103            {-1234567890, "-1,2 милијарде"},
104            {-12345678901f, "-12 милијарди"},
105            {-20890123456f, "-21 милијарда"},
106            {-21890123456f, "-22 милијарде"},
107            {-123456789012f, "-120 милијарди"},
108            {-1234567890123f, "-1,2 трилиона"},
109            {-12345678901234f, "-12 трилиона"},
110            {-123456789012345f, "-120 трилиона"},
111            {-1234567890123456f, "-1.200 трилиона"},
112    };
113
114    Object[][] JapaneseTestData = {
115            {1234f, "1200"},
116            {12345f, "1.2万"},
117            {123456f, "12万"},
118            {1234567f, "120万"},
119            {12345678f, "1200万"},
120            {123456789f, "1.2億"},
121            {1234567890f, "12億"},
122            {12345678901f, "120億"},
123            {123456789012f, "1200億"},
124            {1234567890123f, "1.2兆"},
125            {12345678901234f, "12兆"},
126            {123456789012345f, "120兆"},
127    };
128
129    Object[][] SwahiliTestData = {
130            {1234f, "elfu\u00a01.2"},
131            {12345f, "elfu\u00a012"},
132            {123456f, "elfu\u00A0120"},
133            {1234567f, "M1.2"},
134            {12345678f, "M12"},
135            {123456789f, "M120"},
136            {1234567890f, "B1.2"},
137            {12345678901f, "B12"},
138            {123456789012f, "B120"},
139            {1234567890123f, "T1.2"},
140            {12345678901234f, "T12"},
141            {12345678901234567890f, "T12000000"},
142    };
143
144    Object[][] CsTestDataShort = {
145            {1000, "1\u00a0tis."},
146            {1500, "1,5\u00a0tis."},
147            {5000, "5\u00a0tis."},
148            {23000, "23\u00a0tis."},
149            {127123, "130\u00a0tis."},
150            {1271234, "1,3\u00a0mil."},
151            {12712345, "13\u00a0mil."},
152            {127123456, "130\u00a0mil."},
153            {1271234567f, "1,3\u00a0mld."},
154            {12712345678f, "13\u00a0mld."},
155            {127123456789f, "130\u00a0mld."},
156            {1271234567890f, "1,3\u00a0bil."},
157            {12712345678901f, "13\u00a0bil."},
158            {127123456789012f, "130\u00a0bil."},
159    };
160
161    Object[][] SkTestDataLong = {
162            {1000, "1 tis\u00edc"},
163            {1572, "1,6 tis\u00edca"},
164            {5184, "5,2 tis\u00edca"},
165    };
166
167    Object[][] SwahiliTestDataNegative = {
168            {-1234f, "elfu\u00a0-1.2"},
169            {-12345f, "elfu\u00a0-12"},
170            {-123456f, "elfu\u00A0-120"},
171            {-1234567f, "M-1.2"},
172            {-12345678f, "M-12"},
173            {-123456789f, "M-120"},
174            {-1234567890f, "B-1.2"},
175            {-12345678901f, "B-12"},
176            {-123456789012f, "B-120"},
177            {-1234567890123f, "T-1.2"},
178            {-12345678901234f, "T-12"},
179            {-12345678901234567890f, "T-12000000"},
180    };
181
182    Object[][] TestACoreCompactFormatList = {
183            {1000, "1K"},
184            {1100, "1,1K"},
185            {1200, "1,2Ks"},
186            {2000, "2Ks"},
187    };
188
189    Object[][] TestACoreCompactFormatListCurrency = {
190            {1000, "1K$"},
191            {1100, "1,1K$"},
192            {1200, "1,2Ks$s"},
193            {2000, "2Ks$s"},
194    };
195
196    public void TestACoreCompactFormat() {
197        Map<String,String[][]> affixes = new HashMap();
198        affixes.put("one", new String[][] {
199                {"","",}, {"","",}, {"","",},
200                {"","K"}, {"","K"}, {"","K"},
201                {"","M"}, {"","M"}, {"","M"},
202                {"","B"}, {"","B"}, {"","B"},
203                {"","T"}, {"","T"}, {"","T"},
204        });
205        affixes.put("other", new String[][] {
206                {"","",}, {"","",}, {"","",},
207                {"","Ks"}, {"","Ks"}, {"","Ks"},
208                {"","Ms"}, {"","Ms"}, {"","Ms"},
209                {"","Bs"}, {"","Bs"}, {"","Bs"},
210                {"","Ts"}, {"","Ts"}, {"","Ts"},
211        });
212
213        Map<String,String[]> currencyAffixes = new HashMap();
214        currencyAffixes.put("one", new String[] {"", "$"});
215        currencyAffixes.put("other", new String[] {"", "$s"});
216
217        long[] divisors = new long[] {
218                0,0,0,
219                1000, 1000, 1000,
220                1000000, 1000000, 1000000,
221                1000000000L, 1000000000L, 1000000000L,
222                1000000000000L, 1000000000000L, 1000000000000L};
223        checkCore(affixes, null, divisors, TestACoreCompactFormatList);
224        checkCore(affixes, currencyAffixes, divisors, TestACoreCompactFormatListCurrency);
225    }
226
227    private void checkCore(Map<String, String[][]> affixes, Map<String, String[]> currencyAffixes, long[] divisors, Object[][] testItems) {
228        Collection<String> debugCreationErrors = new LinkedHashSet();
229        CompactDecimalFormat cdf = new CompactDecimalFormat(
230                "#,###.00",
231                DecimalFormatSymbols.getInstance(new ULocale("fr")),
232                CompactStyle.SHORT, PluralRules.createRules("one: j is 1 or f is 1"),
233                divisors, affixes, currencyAffixes,
234                debugCreationErrors
235                );
236        if (debugCreationErrors.size() != 0) {
237            for (String s : debugCreationErrors) {
238                errln("Creation error: " + s);
239            }
240        } else {
241            checkCdf("special cdf ", cdf, testItems);
242        }
243    }
244
245    public void TestDefaultSignificantDigits() {
246        // We are expecting two significant digits as default.
247        CompactDecimalFormat cdf =
248                CompactDecimalFormat.getInstance(ULocale.ENGLISH, CompactStyle.SHORT);
249        assertEquals("Default significant digits", "12K", cdf.format(12345));
250        assertEquals("Default significant digits", "1.2K", cdf.format(1234));
251        assertEquals("Default significant digits", "120", cdf.format(123));
252    }
253
254    public void TestCharacterIterator() {
255        CompactDecimalFormat cdf =
256                getCDFInstance(ULocale.forLanguageTag("sw"), CompactStyle.SHORT);
257        AttributedCharacterIterator iter = cdf.formatToCharacterIterator(1234567);
258        assertEquals("CharacterIterator", "M1.2", iterToString(iter));
259        iter = cdf.formatToCharacterIterator(1234567);
260        iter.setIndex(1);
261        assertEquals("Attributes", NumberFormat.Field.INTEGER, iter.getAttribute(NumberFormat.Field.INTEGER));
262        assertEquals("Attributes", 1, iter.getRunStart());
263        assertEquals("Attributes", 2, iter.getRunLimit());
264    }
265
266    public void TestEnglishShort() {
267        checkLocale(ULocale.ENGLISH, CompactStyle.SHORT, EnglishTestData);
268    }
269
270    public void TestArabicLongStyle() {
271        NumberFormat cdf =
272                CompactDecimalFormat.getInstance(new Locale("ar"), CompactStyle.LONG);
273        assertEquals("Arabic Long", "\u200F-\u0665\u066B\u0663 \u0623\u0644\u0641", cdf.format(-5300));
274    }
275
276    public void TestCsShort() {
277        checkLocale(ULocale.forLanguageTag("cs"), CompactStyle.SHORT, CsTestDataShort);
278    }
279
280    public void TestSkLong() {
281        checkLocale(ULocale.forLanguageTag("sk"), CompactStyle.LONG, SkTestDataLong);
282    }
283
284    public void TestSerbianShort() {
285        checkLocale(ULocale.forLanguageTag("sr"), CompactStyle.SHORT, SerbianTestDataShort);
286    }
287
288    public void TestSerbianLong() {
289        checkLocale(ULocale.forLanguageTag("sr"), CompactStyle.LONG, SerbianTestDataLong);
290    }
291
292    public void TestSerbianLongNegative() {
293        checkLocale(ULocale.forLanguageTag("sr"), CompactStyle.LONG, SerbianTestDataLongNegative);
294    }
295
296    public void TestJapaneseShort() {
297        checkLocale(ULocale.JAPANESE, CompactStyle.SHORT, JapaneseTestData);
298    }
299
300    public void TestSwahiliShort() {
301        checkLocale(ULocale.forLanguageTag("sw"), CompactStyle.SHORT, SwahiliTestData);
302    }
303
304    public void TestSwahiliShortNegative() {
305        checkLocale(ULocale.forLanguageTag("sw"), CompactStyle.SHORT, SwahiliTestDataNegative);
306    }
307
308    public void TestFieldPosition() {
309        CompactDecimalFormat cdf = getCDFInstance(
310                ULocale.forLanguageTag("sw"), CompactStyle.SHORT);
311        FieldPosition fp = new FieldPosition(0);
312        StringBuffer sb = new StringBuffer();
313        cdf.format(1234567f, sb, fp);
314        assertEquals("fp string", "M1.2", sb.toString());
315        assertEquals("fp start", 1, fp.getBeginIndex());
316        assertEquals("fp end", 2, fp.getEndIndex());
317    }
318
319    public void TestEquals() {
320        CompactDecimalFormat cdf = CompactDecimalFormat.getInstance(
321                ULocale.forLanguageTag("sw"), CompactStyle.SHORT);
322        CompactDecimalFormat equalsCdf = CompactDecimalFormat.getInstance(
323                ULocale.forLanguageTag("sw"), CompactStyle.SHORT);
324        CompactDecimalFormat notEqualsCdf = CompactDecimalFormat.getInstance(
325                ULocale.forLanguageTag("sw"), CompactStyle.LONG);
326        assertEquals("equals", cdf, equalsCdf);
327        assertNotEquals("not equals", cdf, notEqualsCdf);
328
329    }
330
331    public void checkLocale(ULocale locale, CompactStyle style, Object[][] testData) {
332        CompactDecimalFormat cdf = getCDFInstance(locale, style);
333        checkCdf(locale + " (" + locale.getDisplayName(locale) + ") for ", cdf, testData);
334    }
335
336    private void checkCdf(String title, CompactDecimalFormat cdf, Object[][] testData) {
337        for (Object[] row : testData) {
338            Object source = row[0];
339            Object expected = row[1];
340            assertEquals(title + source, expected,
341                    cdf.format(source));
342        }
343    }
344
345    private static String iterToString(CharacterIterator iter) {
346        StringBuilder builder = new StringBuilder();
347        for (char c = iter.current(); c != CharacterIterator.DONE; c = iter.next()) {
348            builder.append(c);
349        }
350        return builder.toString();
351    }
352
353    private static CompactDecimalFormat getCDFInstance(ULocale locale, CompactStyle style) {
354        CompactDecimalFormat result = CompactDecimalFormat.getInstance(locale, style);
355        // Our tests are written for two significant digits. We set explicitly here
356        // because default significant digits may change.
357        result.setMaximumSignificantDigits(2);
358        return result;
359    }
360}
361