1/*
2*******************************************************************************
3* Copyright (C) 1997-2013, International Business Machines Corporation and    *
4* others. All Rights Reserved.                                                *
5*******************************************************************************
6*
7* File COMPACTDECIMALFORMATTEST.CPP
8*
9********************************************************************************
10*/
11#include <stdio.h>
12#include <stdlib.h>
13
14#include "intltest.h"
15
16#if !UCONFIG_NO_FORMATTING
17
18#include "unicode/compactdecimalformat.h"
19#include "unicode/unum.h"
20
21#define LENGTHOF(array) (int32_t)(sizeof(array) / sizeof((array)[0]))
22
23typedef struct ExpectedResult {
24  double value;
25  const char *expected;
26} ExpectedResult;
27
28static const char *kShortStr = "Short";
29static const char *kLongStr = "Long";
30
31static ExpectedResult kEnglishShort[] = {
32  {0.0, "0"},
33  {0.17, "0.17"},
34  {1.0, "1"},
35  {1234.0, "1.2K"},
36  {12345.0, "12K"},
37  {123456.0, "120K"},
38  {1234567.0, "1.2M"},
39  {12345678.0, "12M"},
40  {123456789.0, "120M"},
41  {1.23456789E9, "1.2B"},
42  {1.23456789E10, "12B"},
43  {1.23456789E11, "120B"},
44  {1.23456789E12, "1.2T"},
45  {1.23456789E13, "12T"},
46  {1.23456789E14, "120T"},
47  {1.23456789E15, "1200T"}};
48
49static ExpectedResult kSerbianShort[] = {
50  {1234.0, "1200"},
51  {12345.0, "12\\u00a0\\u0445\\u0438\\u0459"},
52  {20789.0, "21\\u00a0\\u0445\\u0438\\u0459"},
53  {123456.0, "120\\u00a0\\u0445\\u0438\\u0459"},
54  {1234567.0, "1,2\\u00A0\\u043C\\u0438\\u043B"},
55  {12345678.0, "12\\u00A0\\u043C\\u0438\\u043B"},
56  {123456789.0, "120\\u00A0\\u043C\\u0438\\u043B"},
57  {1.23456789E9, "1,2\\u00A0\\u043C\\u043B\\u0440\\u0434"},
58  {1.23456789E10, "12\\u00A0\\u043C\\u043B\\u0440\\u0434"},
59  {1.23456789E11, "120\\u00A0\\u043C\\u043B\\u0440\\u0434"},
60  {1.23456789E12, "1,2\\u00A0\\u0431\\u0438\\u043B"},
61  {1.23456789E13, "12\\u00A0\\u0431\\u0438\\u043B"},
62  {1.23456789E14, "120\\u00A0\\u0431\\u0438\\u043B"},
63  {1.23456789E15, "1200\\u00A0\\u0431\\u0438\\u043B"}};
64
65static ExpectedResult kSerbianLong[] = {
66  {1234.0, "1,2 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"}, // 10^3 few
67  {12345.0, "12 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"}, // 10^3 other
68  {21789.0, "22 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"}, // 10^3 few
69  {123456.0, "120 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"}, // 10^3 other
70  {999999.0, "1 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D"}, // 10^6 one
71  {1234567.0, "1,2 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^6 few
72  {12345678.0, "12 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^6 other
73  {123456789.0, "120 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^6 other
74  {1.23456789E9, "1,2 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"}, // 10^9 few
75  {1.23456789E10, "12 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"}, // 10^9 other
76  {2.08901234E10, "21 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0430"}, // 10^9 one
77  {2.18901234E10, "22 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"}, // 10^9 few
78  {1.23456789E11, "120 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"}, // 10^9 other
79  {1.23456789E12, "1,2 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^12 few
80  {1.23456789E13, "12 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^12 other
81  {1.23456789E14, "120 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}, // 10^12 other
82  {1.23456789E15, "1200 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}}; // 10^12 other
83
84static ExpectedResult kSerbianLongNegative[] = {
85  {-1234.0, "-1,2 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"},
86  {-12345.0, "-12 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"},
87  {-21789.0, "-22 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0435"},
88  {-123456.0, "-120 \\u0445\\u0438\\u0459\\u0430\\u0434\\u0430"},
89  {-999999.0, "-1 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D"},
90  {-1234567.0, "-1,2 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"},
91  {-12345678.0, "-12 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"},
92  {-123456789.0, "-120 \\u043C\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"},
93  {-1.23456789E9, "-1,2 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"},
94  {-1.23456789E10, "-12 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"},
95  {-2.08901234E10, "-21 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0430"},
96  {-2.18901234E10, "-22 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0435"},
97  {-1.23456789E11, "-120 \\u043C\\u0438\\u043B\\u0438\\u0458\\u0430\\u0440\\u0434\\u0438"},
98  {-1.23456789E12, "-1,2 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"},
99  {-1.23456789E13, "-12 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"},
100  {-1.23456789E14, "-120 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"},
101  {-1.23456789E15, "-1200 \\u0442\\u0440\\u0438\\u043B\\u0438\\u043E\\u043D\\u0430"}};
102
103static ExpectedResult kJapaneseShort[] = {
104  {1234.0, "1.2\\u5343"},
105  {12345.0, "1.2\\u4E07"},
106  {123456.0, "12\\u4E07"},
107  {1234567.0, "120\\u4E07"},
108  {12345678.0, "1200\\u4E07"},
109  {123456789.0, "1.2\\u5104"},
110  {1.23456789E9, "12\\u5104"},
111  {1.23456789E10, "120\\u5104"},
112  {1.23456789E11, "1200\\u5104"},
113  {1.23456789E12, "1.2\\u5146"},
114  {1.23456789E13, "12\\u5146"},
115  {1.23456789E14, "120\\u5146"}};
116
117static ExpectedResult kSwahiliShort[] = {
118  {1234.0, "elfu\\u00a01.2"},
119  {12345.0, "elfu\\u00a012"},
120  {123456.0, "laki1.2"},
121  {1234567.0, "M1.2"},
122  {12345678.0, "M12"},
123  {123456789.0, "M120"},
124  {1.23456789E9, "B1.2"},
125  {1.23456789E10, "B12"},
126  {1.23456789E11, "B120"},
127  {1.23456789E12, "T1.2"},
128  {1.23456789E13, "T12"},
129  {1.23456789E15, "T1200"}};
130
131static ExpectedResult kCsShort[] = {
132  {1000.0, "1\\u00a0tis."},
133  {1500.0, "1,5\\u00a0tis."},
134  {5000.0, "5\\u00a0tis."},
135  {23000.0, "23\\u00a0tis."},
136  {127123.0, "130\\u00a0tis."},
137  {1271234.0, "1,3\\u00a0mil."},
138  {12712345.0, "13\\u00a0mil."},
139  {127123456.0, "130\\u00a0mil."},
140  {1.27123456E9, "1,3\\u00a0mld."},
141  {1.27123456E10, "13\\u00a0mld."},
142  {1.27123456E11, "130\\u00a0mld."},
143  {1.27123456E12, "1,3\\u00a0bil."},
144  {1.27123456E13, "13\\u00a0bil."},
145  {1.27123456E14, "130\\u00a0bil."}};
146
147static ExpectedResult kSkLong[] = {
148  {1000.0, "1 tis\\u00edc"},
149  {1572.0, "1,6 tis\\u00edc"},
150  {5184.0, "5,2 tis\\u00edc"}};
151
152static ExpectedResult kSwahiliShortNegative[] = {
153  {-1234.0, "elfu\\u00a0-1.2"},
154  {-12345.0, "elfu\\u00a0-12"},
155  {-123456.0, "laki-1.2"},
156  {-1234567.0, "M-1.2"},
157  {-12345678.0, "M-12"},
158  {-123456789.0, "M-120"},
159  {-1.23456789E9, "B-1.2"},
160  {-1.23456789E10, "B-12"},
161  {-1.23456789E11, "B-120"},
162  {-1.23456789E12, "T-1.2"},
163  {-1.23456789E13, "T-12"},
164  {-1.23456789E15, "T-1200"}};
165
166static ExpectedResult kArabicLong[] = {
167  {-5300.0, "\\u200F-\\u0665\\u066B\\u0663 \\u0623\\u0644\\u0641"}};
168
169
170class CompactDecimalFormatTest : public IntlTest {
171public:
172    CompactDecimalFormatTest() {
173    }
174
175    void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0);
176private:
177    void TestEnglishShort();
178    void TestSerbianShort();
179    void TestSerbianLong();
180    void TestSerbianLongNegative();
181    void TestJapaneseShort();
182    void TestSwahiliShort();
183    void TestCsShort();
184    void TestSkLong();
185    void TestSwahiliShortNegative();
186    void TestArabicLong();
187    void TestFieldPosition();
188    void TestSignificantDigits();
189    void CheckLocale(
190        const Locale& locale, UNumberCompactStyle style,
191        const ExpectedResult* expectedResult, int32_t expectedResultLength);
192    void CheckExpectedResult(
193        const CompactDecimalFormat* cdf, const ExpectedResult* expectedResult,
194        const char* description);
195    CompactDecimalFormat* createCDFInstance(const Locale& locale, UNumberCompactStyle style, UErrorCode& status);
196    static const char *StyleStr(UNumberCompactStyle style);
197};
198
199void CompactDecimalFormatTest::runIndexedTest(
200    int32_t index, UBool exec, const char *&name, char *) {
201  if (exec) {
202    logln("TestSuite CompactDecimalFormatTest: ");
203  }
204  TESTCASE_AUTO_BEGIN;
205  TESTCASE_AUTO(TestEnglishShort);
206  TESTCASE_AUTO(TestSerbianShort);
207  TESTCASE_AUTO(TestSerbianLong);
208  TESTCASE_AUTO(TestSerbianLongNegative);
209  TESTCASE_AUTO(TestJapaneseShort);
210  TESTCASE_AUTO(TestSwahiliShort);
211  TESTCASE_AUTO(TestCsShort);
212  TESTCASE_AUTO(TestSkLong);
213  TESTCASE_AUTO(TestSwahiliShortNegative);
214  TESTCASE_AUTO(TestArabicLong);
215  TESTCASE_AUTO(TestFieldPosition);
216  TESTCASE_AUTO(TestSignificantDigits);
217  TESTCASE_AUTO_END;
218}
219
220void CompactDecimalFormatTest::TestEnglishShort() {
221  CheckLocale("en", UNUM_SHORT, kEnglishShort, LENGTHOF(kEnglishShort));
222}
223
224void CompactDecimalFormatTest::TestSerbianShort() {
225  CheckLocale("sr", UNUM_SHORT, kSerbianShort, LENGTHOF(kSerbianShort));
226}
227
228void CompactDecimalFormatTest::TestSerbianLong() {
229  CheckLocale("sr", UNUM_LONG, kSerbianLong, LENGTHOF(kSerbianLong));
230}
231
232void CompactDecimalFormatTest::TestSerbianLongNegative() {
233  CheckLocale("sr", UNUM_LONG, kSerbianLongNegative, LENGTHOF(kSerbianLongNegative));
234}
235
236void CompactDecimalFormatTest::TestJapaneseShort() {
237  CheckLocale(Locale::getJapan(), UNUM_SHORT, kJapaneseShort, LENGTHOF(kJapaneseShort));
238}
239
240void CompactDecimalFormatTest::TestSwahiliShort() {
241  CheckLocale("sw", UNUM_SHORT, kSwahiliShort, LENGTHOF(kSwahiliShort));
242}
243
244void CompactDecimalFormatTest::TestFieldPosition() {
245  // Swahili uses prefixes which forces offsets in field position to change
246  UErrorCode status = U_ZERO_ERROR;
247  LocalPointer<CompactDecimalFormat> cdf(createCDFInstance("sw", UNUM_SHORT, status));
248  if (U_FAILURE(status)) {
249    dataerrln("Unable to create format object - %s", u_errorName(status));
250    return;
251  }
252  FieldPosition fp(UNUM_INTEGER_FIELD);
253  UnicodeString result;
254  cdf->format(1234567.0, result, fp);
255  UnicodeString subString = result.tempSubString(fp.getBeginIndex(), fp.getEndIndex() - fp.getBeginIndex());
256  if (subString != UnicodeString("1", -1, US_INV)) {
257    errln(UnicodeString("Expected 1, got ") + subString);
258  }
259}
260
261void CompactDecimalFormatTest::TestCsShort() {
262  CheckLocale("cs", UNUM_SHORT, kCsShort, LENGTHOF(kCsShort));
263}
264
265void CompactDecimalFormatTest::TestSkLong() {
266  // In CLDR we have:
267  // 1000 {
268  //   few{"0"}
269  //   one{"0"}
270  //   other{"0"}
271  CheckLocale("sk", UNUM_LONG, kSkLong, LENGTHOF(kSkLong));
272}
273
274void CompactDecimalFormatTest::TestSwahiliShortNegative() {
275  CheckLocale("sw", UNUM_SHORT, kSwahiliShortNegative, LENGTHOF(kSwahiliShortNegative));
276}
277
278void CompactDecimalFormatTest::TestArabicLong() {
279  CheckLocale("ar", UNUM_LONG, kArabicLong, LENGTHOF(kArabicLong));
280}
281
282void CompactDecimalFormatTest::TestSignificantDigits() {
283  UErrorCode status = U_ZERO_ERROR;
284  LocalPointer<CompactDecimalFormat> cdf(CompactDecimalFormat::createInstance("en", UNUM_SHORT, status));
285  if (U_FAILURE(status)) {
286    dataerrln("Unable to create format object - %s", u_errorName(status));
287    return;
288  }
289  UnicodeString actual;
290  cdf->format(123456.0, actual);
291  // We expect 3 significant digits by default
292  UnicodeString expected("123K", -1, US_INV);
293  if (actual != expected) {
294    errln(UnicodeString("Fail: Expected: ") + expected + UnicodeString(" Got: ") + actual);
295  }
296}
297
298void CompactDecimalFormatTest::CheckLocale(const Locale& locale, UNumberCompactStyle style, const ExpectedResult* expectedResults, int32_t expectedResultLength) {
299  UErrorCode status = U_ZERO_ERROR;
300  LocalPointer<CompactDecimalFormat> cdf(createCDFInstance(locale, style, status));
301  if (U_FAILURE(status)) {
302    dataerrln("Unable to create format object - %s", u_errorName(status));
303    return;
304  }
305  char description[256];
306  sprintf(description,"%s - %s", locale.getName(), StyleStr(style));
307  for (int32_t i = 0; i < expectedResultLength; i++) {
308    CheckExpectedResult(cdf.getAlias(), &expectedResults[i], description);
309  }
310}
311
312void CompactDecimalFormatTest::CheckExpectedResult(
313    const CompactDecimalFormat* cdf, const ExpectedResult* expectedResult, const char* description) {
314  UnicodeString actual;
315  cdf->format(expectedResult->value, actual);
316  UnicodeString expected(expectedResult->expected, -1, US_INV);
317  expected = expected.unescape();
318  if (actual != expected) {
319    errln(UnicodeString("Fail: Expected: ") + expected
320          + UnicodeString(" Got: ") + actual
321          + UnicodeString(" for: ") + UnicodeString(description));
322  }
323}
324
325CompactDecimalFormat*
326CompactDecimalFormatTest::createCDFInstance(const Locale& locale, UNumberCompactStyle style, UErrorCode& status) {
327  CompactDecimalFormat* result = CompactDecimalFormat::createInstance(locale, style, status);
328  if (U_FAILURE(status)) {
329    return NULL;
330  }
331  // All tests are written for two significant digits, so we explicitly set here
332  // in case default significant digits change.
333  result->setMaximumSignificantDigits(2);
334  return result;
335}
336
337const char *CompactDecimalFormatTest::StyleStr(UNumberCompactStyle style) {
338  if (style == UNUM_SHORT) {
339    return kShortStr;
340  }
341  return kLongStr;
342}
343
344extern IntlTest *createCompactDecimalFormatTest() {
345  return new CompactDecimalFormatTest();
346}
347
348#endif
349