1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 2005-2012, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6#include "unicode/utypes.h"
7
8#if !UCONFIG_NO_FORMATTING
9#include "unicode/unum.h"
10#include "unicode/ucurr.h"
11#include "unicode/ustring.h"
12#include "cintltst.h"
13#include "cstring.h"
14
15static void expectInList(const char *isoCurrency, uint32_t currencyType, UBool isExpected) {
16    UErrorCode status = U_ZERO_ERROR;
17    const char *foundCurrency = NULL;
18    const char *currentCurrency;
19    UEnumeration *en = ucurr_openISOCurrencies(currencyType, &status);
20    if (U_FAILURE(status)) {
21       log_err("Error: ucurr_openISOCurrencies returned %s\n", myErrorName(status));
22       return;
23    }
24
25    while ((currentCurrency = uenum_next(en, NULL, &status)) != NULL) {
26        if (strcmp(isoCurrency, currentCurrency) == 0) {
27            foundCurrency = currentCurrency;
28            break;
29        }
30    }
31
32    if ((foundCurrency != NULL) != isExpected) {
33       log_err("Error: could not find %s as expected. isExpected = %s type=0x%X\n",
34           isoCurrency, isExpected ? "TRUE" : "FALSE", currencyType);
35    }
36    uenum_close(en);
37}
38
39static void TestEnumList(void) {
40    expectInList("ADP", UCURR_ALL, TRUE); /* First in list */
41    expectInList("ZWD", UCURR_ALL, TRUE); /* Last in list */
42
43    expectInList("USD", UCURR_ALL, TRUE);
44    expectInList("USD", UCURR_COMMON, TRUE);
45    expectInList("USD", UCURR_UNCOMMON, FALSE);
46    expectInList("USD", UCURR_DEPRECATED, FALSE);
47    expectInList("USD", UCURR_NON_DEPRECATED, TRUE);
48    expectInList("USD", UCURR_COMMON|UCURR_DEPRECATED, FALSE);
49    expectInList("USD", UCURR_COMMON|UCURR_NON_DEPRECATED, TRUE);
50    expectInList("USD", UCURR_UNCOMMON|UCURR_DEPRECATED, FALSE);
51    expectInList("USD", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, FALSE);
52
53    expectInList("USN", UCURR_ALL, TRUE);
54    expectInList("USN", UCURR_COMMON, FALSE);
55    expectInList("USN", UCURR_UNCOMMON, TRUE);
56    expectInList("USN", UCURR_DEPRECATED, FALSE);
57    expectInList("USN", UCURR_NON_DEPRECATED, TRUE);
58    expectInList("USN", UCURR_COMMON|UCURR_DEPRECATED, FALSE);
59    expectInList("USN", UCURR_COMMON|UCURR_NON_DEPRECATED, FALSE);
60    expectInList("USN", UCURR_UNCOMMON|UCURR_DEPRECATED, FALSE);
61    expectInList("USN", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, TRUE);
62
63    expectInList("DEM", UCURR_ALL, TRUE);
64    expectInList("DEM", UCURR_COMMON, TRUE);
65    expectInList("DEM", UCURR_UNCOMMON, FALSE);
66    expectInList("DEM", UCURR_DEPRECATED, TRUE);
67    expectInList("DEM", UCURR_NON_DEPRECATED, FALSE);
68    expectInList("DEM", UCURR_COMMON|UCURR_DEPRECATED, TRUE);
69    expectInList("DEM", UCURR_COMMON|UCURR_NON_DEPRECATED, FALSE);
70    expectInList("DEM", UCURR_UNCOMMON|UCURR_DEPRECATED, FALSE);
71    expectInList("DEM", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, FALSE);
72
73    expectInList("XEU", UCURR_ALL, TRUE);
74    expectInList("XEU", UCURR_COMMON, FALSE);
75    expectInList("XEU", UCURR_UNCOMMON, TRUE);
76    expectInList("XEU", UCURR_DEPRECATED, TRUE);
77    expectInList("XEU", UCURR_NON_DEPRECATED, FALSE);
78    expectInList("XEU", UCURR_COMMON|UCURR_DEPRECATED, FALSE);
79    expectInList("XEU", UCURR_COMMON|UCURR_NON_DEPRECATED, FALSE);
80    expectInList("XEU", UCURR_UNCOMMON|UCURR_DEPRECATED, TRUE);
81    expectInList("XEU", UCURR_UNCOMMON|UCURR_NON_DEPRECATED, FALSE);
82
83}
84
85static void TestEnumListReset(void) {
86    UErrorCode status = U_ZERO_ERROR;
87    const char *currency1;
88    const char *currency2;
89    UEnumeration *en = ucurr_openISOCurrencies(UCURR_ALL, &status);
90    if (U_FAILURE(status)) {
91       log_err("Error: ucurr_openISOCurrencies returned %s\n", myErrorName(status));
92       return;
93    }
94
95    currency1 = uenum_next(en, NULL, &status);
96    uenum_reset(en, &status);
97    currency2 = uenum_next(en, NULL, &status);
98    if (U_FAILURE(status)) {
99       log_err("Error: uenum_next or uenum_reset returned %s\n", myErrorName(status));
100       return;
101    }
102    /* The first item's pointer in the list should be the same between resets. */
103    if (currency1 != currency2) {
104       log_err("Error: reset doesn't work %s != %s\n", currency1, currency2);
105    }
106    uenum_close(en);
107}
108
109static int32_t checkItemCount(uint32_t currencyType) {
110    UErrorCode status = U_ZERO_ERROR;
111    int32_t originalCount, count;
112    UEnumeration *en = ucurr_openISOCurrencies(currencyType, &status);
113    int32_t expectedLen = 3, len;
114    if (U_FAILURE(status)) {
115       log_err("Error: ucurr_openISOCurrencies returned %s\n", myErrorName(status));
116       return -1;
117    }
118
119    originalCount = uenum_count(en, &status);
120    for (count=0;;count++) {
121        const char *str = uenum_next(en, &len, &status);
122        if (str == NULL || len != expectedLen || strlen(str) != expectedLen) {
123            break;
124        }
125    }
126
127    if (originalCount != count) {
128        log_err("Error: uenum_count returned the wrong value (type = 0x%X). Got: %d Expected %d\n",
129           currencyType, count, originalCount);
130    }
131    if (U_FAILURE(status)) {
132        log_err("Error: uenum_next got an error: %s\n", u_errorName(status));
133    }
134    uenum_close(en);
135    return count;
136}
137
138static void TestEnumListCount(void) {
139    checkItemCount(UCURR_ALL);
140    checkItemCount(UCURR_COMMON);
141    checkItemCount(UCURR_UNCOMMON);
142    checkItemCount(UCURR_DEPRECATED);
143    checkItemCount(UCURR_NON_DEPRECATED);
144    checkItemCount(UCURR_COMMON|UCURR_DEPRECATED);
145    checkItemCount(UCURR_COMMON|UCURR_NON_DEPRECATED);
146    checkItemCount(UCURR_UNCOMMON|UCURR_DEPRECATED);
147    checkItemCount(UCURR_UNCOMMON|UCURR_NON_DEPRECATED);
148
149    if (checkItemCount(UCURR_DEPRECATED|UCURR_NON_DEPRECATED) != 0) {
150        log_err("Error: UCURR_DEPRECATED|UCURR_NON_DEPRECATED should return 0 items\n");
151    }
152    if (checkItemCount(UCURR_COMMON|UCURR_UNCOMMON) != 0) {
153        log_err("Error: UCURR_DEPRECATED|UCURR_NON_DEPRECATED should return 0 items\n");
154    }
155}
156
157static void TestFractionDigitOverride(void) {
158    UErrorCode status = U_ZERO_ERROR;
159    UNumberFormat *fmt = unum_open(UNUM_CURRENCY, NULL, 0, "hu_HU", NULL, &status);
160    UChar buffer[256];
161    UChar expectedBuf[256];
162    const char expectedFirst[] = "123\\u00A0Ft";
163    const char expectedSecond[] = "123,46\\u00A0Ft";
164    const char expectedThird[] = "123,456\\u00A0Ft";
165    if (U_FAILURE(status)) {
166       log_data_err("Error: unum_open returned %s (Are you missing data?)\n", myErrorName(status));
167       return;
168    }
169    /* Make sure that you can format normal fraction digits. */
170    unum_formatDouble(fmt, 123.456, buffer, sizeof(buffer)/sizeof(buffer[0]), NULL, &status);
171    u_unescape(expectedFirst, expectedBuf, strlen(expectedFirst)+1);
172    if (u_strcmp(buffer, expectedBuf) != 0) {
173       log_err("Error: unum_formatDouble didn't return %s\n", expectedFirst);
174    }
175    /* Make sure that you can format 2 fraction digits. */
176    unum_setAttribute(fmt, UNUM_FRACTION_DIGITS, 2);
177    unum_formatDouble(fmt, 123.456, buffer, sizeof(buffer)/sizeof(buffer[0]), NULL, &status);
178    u_unescape(expectedSecond, expectedBuf, strlen(expectedSecond)+1);
179    if (u_strcmp(buffer, expectedBuf) != 0) {
180       log_err("Error: unum_formatDouble didn't return %s\n", expectedSecond);
181    }
182    /* Make sure that you can format more fraction digits. */
183    unum_setAttribute(fmt, UNUM_FRACTION_DIGITS, 3);
184    unum_formatDouble(fmt, 123.456, buffer, sizeof(buffer)/sizeof(buffer[0]), NULL, &status);
185    u_unescape(expectedThird, expectedBuf, strlen(expectedThird)+1);
186    if (u_strcmp(buffer, expectedBuf) != 0) {
187       log_err("Error: unum_formatDouble didn't return %s\n", expectedThird);
188    }
189    unum_close(fmt);
190}
191
192static void TestPrefixSuffix(void) {
193    int32_t	pos;
194    UErrorCode status;
195    double result1 = 0.0, result2 = 0.0;
196    UNumberFormat* parser;
197    UChar buffer[4];
198    static const UChar TEST_NUMBER[] = {0x0024,0x0031,0x0032,0x002E,0x0030,0x0030,0}; /* $12.00 */
199    static const UChar NEG_PREFIX[] = {0x005B,0}; /* "[" */
200    static const UChar NEG_SUFFIX[] = {0x005D,0}; /* "]" */
201
202
203	status = U_ZERO_ERROR;
204	parser = unum_open(UNUM_CURRENCY, NULL, -1, "en_US", NULL, &status);
205    if (U_FAILURE(status)) {
206       log_data_err("Error: unum_open returned %s (Are you missing data?)\n", u_errorName(status));
207       return;
208    }
209
210	pos = 0;
211	status = U_ZERO_ERROR;
212	result1 = unum_parseDoubleCurrency(parser, TEST_NUMBER, -1, &pos, buffer, &status);
213
214	unum_setTextAttribute(parser, UNUM_NEGATIVE_SUFFIX, NEG_SUFFIX, -1, &status);
215	unum_setTextAttribute(parser, UNUM_NEGATIVE_PREFIX, NEG_PREFIX, -1, &status);
216    if (U_FAILURE(status)) {
217       log_err("Error: unum_setTextAttribute returned %s\n", u_errorName(status));
218       return;
219    }
220
221	pos = 0;
222	result2 = unum_parseDoubleCurrency(parser, TEST_NUMBER, -1, &pos, buffer, &status);
223    if (result1 != result2 || U_FAILURE(status)) {
224       log_err("Error: unum_parseDoubleCurrency didn't return the same value for same string %f %f %s\n",
225           result1, result2, u_errorName(status));
226    }
227    unum_close(parser);
228}
229
230typedef struct {
231    const char* alphaCode;
232    int32_t     numericCode;
233} NumCodeTestEntry;
234
235static const NumCodeTestEntry NUMCODE_TESTDATA[] = {
236    {"USD", 840},
237    {"Usd", 840},   /* mixed casing */
238    {"EUR", 978},
239    {"JPY", 392},
240    {"XFU", 0},     /* XFU: no numeric code  */
241    {"ZZZ", 0},     /* ZZZ: undefined ISO currency code */
242    {"bogus", 0},   /* bogus code */
243    {0, 0},
244};
245
246static void TestNumericCode(void) {
247    UChar code[4];
248    int32_t i;
249    int32_t numCode;
250
251    for (i = 0; NUMCODE_TESTDATA[i].alphaCode; i++) {
252        u_charsToUChars(NUMCODE_TESTDATA[i].alphaCode, code, sizeof(code)/sizeof(code[0]));
253        numCode = ucurr_getNumericCode(code);
254        if (numCode != NUMCODE_TESTDATA[i].numericCode) {
255            log_data_err("Error: ucurr_getNumericCode returned %d for currency %s, expected - %d\n",
256                numCode, NUMCODE_TESTDATA[i].alphaCode, NUMCODE_TESTDATA[i].numericCode);
257        }
258    }
259}
260
261void addCurrencyTest(TestNode** root);
262
263#define TESTCASE(x) addTest(root, &x, "tsformat/currtest/" #x)
264
265void addCurrencyTest(TestNode** root)
266{
267    TESTCASE(TestEnumList);
268    TESTCASE(TestEnumListReset);
269    TESTCASE(TestEnumListCount);
270    TESTCASE(TestFractionDigitOverride);
271    TESTCASE(TestPrefixSuffix);
272    TESTCASE(TestNumericCode);
273}
274
275#endif /* #if !UCONFIG_NO_FORMATTING */
276