1 /***********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 1997-2010, International Business Machines Corporation
4 * and others. All Rights Reserved.
5 ***********************************************************************/
6
7 #include "unicode/utypes.h"
8
9 #if !UCONFIG_NO_FORMATTING
10
11 #include "nmfmapts.h"
12
13 #include "unicode/numfmt.h"
14 #include "unicode/decimfmt.h"
15 #include "unicode/locid.h"
16 #include "unicode/unum.h"
17 #include "unicode/strenum.h"
18
19 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't
20 // try to test the full functionality. It just calls each function in the class and
21 // verifies that it works on a basic level.
22
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)23 void IntlTestNumberFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
24 {
25 if (exec) logln("TestSuite NumberFormatAPI");
26 switch (index) {
27 case 0: name = "NumberFormat API test";
28 if (exec) {
29 logln("NumberFormat API test---"); logln("");
30 UErrorCode status = U_ZERO_ERROR;
31 Locale saveLocale;
32 Locale::setDefault(Locale::getEnglish(), status);
33 if(U_FAILURE(status)) {
34 errln("ERROR: Could not set default locale, test may not give correct results");
35 }
36 testAPI(/* par */);
37 Locale::setDefault(saveLocale, status);
38 }
39 break;
40 case 1: name = "NumberFormatRegistration";
41 if (exec) {
42 logln("NumberFormat Registration test---"); logln("");
43 UErrorCode status = U_ZERO_ERROR;
44 Locale saveLocale;
45 Locale::setDefault(Locale::getEnglish(), status);
46 if(U_FAILURE(status)) {
47 errln("ERROR: Could not set default locale, test may not give correct results");
48 }
49 testRegistration();
50 Locale::setDefault(saveLocale, status);
51 }
52 break;
53 default: name = ""; break;
54 }
55 }
56
57 /**
58 * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of
59 * NumberFormat.
60 */
testAPI()61 void IntlTestNumberFormatAPI::testAPI(/* char* par */)
62 {
63 UErrorCode status = U_ZERO_ERROR;
64
65 // ======= Test constructors
66
67 logln("Testing NumberFormat constructors");
68
69 NumberFormat *def = NumberFormat::createInstance(status);
70 if(U_FAILURE(status)) {
71 dataerrln("ERROR: Could not create NumberFormat (default) - %s", u_errorName(status));
72 }
73
74 status = U_ZERO_ERROR;
75 NumberFormat *fr = NumberFormat::createInstance(Locale::getFrench(), status);
76 if(U_FAILURE(status)) {
77 dataerrln("ERROR: Could not create NumberFormat (French) - %s", u_errorName(status));
78 }
79
80 NumberFormat *cur = NumberFormat::createCurrencyInstance(status);
81 if(U_FAILURE(status)) {
82 dataerrln("ERROR: Could not create NumberFormat (currency, default) - %s", u_errorName(status));
83 }
84
85 status = U_ZERO_ERROR;
86 NumberFormat *cur_fr = NumberFormat::createCurrencyInstance(Locale::getFrench(), status);
87 if(U_FAILURE(status)) {
88 dataerrln("ERROR: Could not create NumberFormat (currency, French) - %s", u_errorName(status));
89 }
90
91 NumberFormat *per = NumberFormat::createPercentInstance(status);
92 if(U_FAILURE(status)) {
93 dataerrln("ERROR: Could not create NumberFormat (percent, default) - %s", u_errorName(status));
94 }
95
96 status = U_ZERO_ERROR;
97 NumberFormat *per_fr = NumberFormat::createPercentInstance(Locale::getFrench(), status);
98 if(U_FAILURE(status)) {
99 dataerrln("ERROR: Could not create NumberFormat (percent, French) - %s", u_errorName(status));
100 }
101
102 // ======= Test equality
103 if (per_fr != NULL && cur_fr != NULL)
104 {
105 logln("Testing equality operator");
106
107 if( *per_fr == *cur_fr || ! ( *per_fr != *cur_fr) ) {
108 errln("ERROR: == failed");
109 }
110 }
111
112 // ======= Test various format() methods
113 if (cur_fr != NULL)
114 {
115 logln("Testing various format() methods");
116
117 double d = -10456.0037;
118 int32_t l = 100000000;
119 Formattable fD(d);
120 Formattable fL(l);
121
122 UnicodeString res1, res2, res3, res4, res5, res6;
123 FieldPosition pos1(0), pos2(0), pos3(0), pos4(0);
124
125 res1 = cur_fr->format(d, res1);
126 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1);
127
128 res2 = cur_fr->format(l, res2);
129 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2);
130
131 res3 = cur_fr->format(d, res3, pos1);
132 logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res3);
133
134 res4 = cur_fr->format(l, res4, pos2);
135 logln((UnicodeString) "" + (int32_t) l + " formatted to " + res4);
136
137 status = U_ZERO_ERROR;
138 res5 = cur_fr->format(fD, res5, pos3, status);
139 if(U_FAILURE(status)) {
140 errln("ERROR: format(Formattable [double]) failed");
141 }
142 logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res5);
143
144 status = U_ZERO_ERROR;
145 res6 = cur_fr->format(fL, res6, pos4, status);
146 if(U_FAILURE(status)) {
147 errln("ERROR: format(Formattable [long]) failed");
148 }
149 logln((UnicodeString) "" + fL.getLong() + " formatted to " + res6);
150 }
151
152 // ======= Test parse()
153 if (fr != NULL)
154 {
155 logln("Testing parse()");
156
157 double d = -10456.0037;
158 UnicodeString text("-10,456.0037");
159 Formattable result1, result2, result3;
160 ParsePosition pos(0), pos01(0);
161 fr->parseObject(text, result1, pos);
162 if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) {
163 errln("ERROR: Roundtrip failed (via parse()) for " + text);
164 }
165 logln(text + " parsed into " + (int32_t) result1.getDouble());
166
167 fr->parse(text, result2, pos01);
168 if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) {
169 errln("ERROR: Roundtrip failed (via parse()) for " + text);
170 }
171 logln(text + " parsed into " + (int32_t) result2.getDouble());
172
173 status = U_ZERO_ERROR;
174 fr->parse(text, result3, status);
175 if(U_FAILURE(status)) {
176 errln("ERROR: parse() failed");
177 }
178 if(result3.getType() != Formattable::kDouble && result3.getDouble() != d) {
179 errln("ERROR: Roundtrip failed (via parse()) for " + text);
180 }
181 logln(text + " parsed into " + (int32_t) result3.getDouble());
182 }
183
184 // ======= Test getters and setters
185 if (fr != NULL && def != NULL)
186 {
187 logln("Testing getters and setters");
188
189 int32_t count = 0;
190 const Locale *locales = NumberFormat::getAvailableLocales(count);
191 logln((UnicodeString) "Got " + count + " locales" );
192 for(int32_t i = 0; i < count; i++) {
193 UnicodeString name(locales[i].getName(),"");
194 logln(name);
195 }
196
197 fr->setParseIntegerOnly( def->isParseIntegerOnly() );
198 if(fr->isParseIntegerOnly() != def->isParseIntegerOnly() ) {
199 errln("ERROR: setParseIntegerOnly() failed");
200 }
201
202 fr->setGroupingUsed( def->isGroupingUsed() );
203 if(fr->isGroupingUsed() != def->isGroupingUsed() ) {
204 errln("ERROR: setGroupingUsed() failed");
205 }
206
207 fr->setMaximumIntegerDigits( def->getMaximumIntegerDigits() );
208 if(fr->getMaximumIntegerDigits() != def->getMaximumIntegerDigits() ) {
209 errln("ERROR: setMaximumIntegerDigits() failed");
210 }
211
212 fr->setMinimumIntegerDigits( def->getMinimumIntegerDigits() );
213 if(fr->getMinimumIntegerDigits() != def->getMinimumIntegerDigits() ) {
214 errln("ERROR: setMinimumIntegerDigits() failed");
215 }
216
217 fr->setMaximumFractionDigits( def->getMaximumFractionDigits() );
218 if(fr->getMaximumFractionDigits() != def->getMaximumFractionDigits() ) {
219 errln("ERROR: setMaximumFractionDigits() failed");
220 }
221
222 fr->setMinimumFractionDigits( def->getMinimumFractionDigits() );
223 if(fr->getMinimumFractionDigits() != def->getMinimumFractionDigits() ) {
224 errln("ERROR: setMinimumFractionDigits() failed");
225 }
226 }
227
228 // ======= Test getStaticClassID()
229
230 logln("Testing getStaticClassID()");
231
232 status = U_ZERO_ERROR;
233 NumberFormat *test = new DecimalFormat(status);
234 if(U_FAILURE(status)) {
235 errcheckln(status, "ERROR: Couldn't create a NumberFormat - %s", u_errorName(status));
236 }
237
238 if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) {
239 errln("ERROR: getDynamicClassID() didn't return the expected value");
240 }
241
242 delete test;
243 delete def;
244 delete fr;
245 delete cur;
246 delete cur_fr;
247 delete per;
248 delete per_fr;
249 }
250
251 #if !UCONFIG_NO_SERVICE
252
253 #define SRC_LOC Locale::getFrance()
254 #define SWAP_LOC Locale::getUS()
255
256 class NFTestFactory : public SimpleNumberFormatFactory {
257 NumberFormat* currencyStyle;
258
259 public:
NFTestFactory()260 NFTestFactory()
261 : SimpleNumberFormatFactory(SRC_LOC, TRUE)
262 {
263 UErrorCode status = U_ZERO_ERROR;
264 currencyStyle = NumberFormat::createInstance(SWAP_LOC, status);
265 }
266
~NFTestFactory()267 virtual ~NFTestFactory()
268 {
269 delete currencyStyle;
270 }
271
createFormat(const Locale &,UNumberFormatStyle formatType)272 virtual NumberFormat* createFormat(const Locale& /* loc */, UNumberFormatStyle formatType)
273 {
274 if (formatType == UNUM_CURRENCY) {
275 return (NumberFormat*)currencyStyle->clone();
276 }
277 return NULL;
278 }
279
getDynamicClassID() const280 virtual inline UClassID getDynamicClassID() const
281 {
282 return (UClassID)&gID;
283 }
284
getStaticClassID()285 static inline UClassID getStaticClassID()
286 {
287 return (UClassID)&gID;
288 }
289
290 private:
291 static char gID;
292 };
293
294 char NFTestFactory::gID = 0;
295 #endif
296
297 void
testRegistration()298 IntlTestNumberFormatAPI::testRegistration()
299 {
300 #if !UCONFIG_NO_SERVICE
301 UErrorCode status = U_ZERO_ERROR;
302
303 LocalPointer<NumberFormat> f0(NumberFormat::createInstance(SWAP_LOC, status));
304 LocalPointer<NumberFormat> f1(NumberFormat::createInstance(SRC_LOC, status));
305 LocalPointer<NumberFormat> f2(NumberFormat::createCurrencyInstance(SRC_LOC, status));
306 URegistryKey key = NumberFormat::registerFactory(new NFTestFactory(), status);
307 LocalPointer<NumberFormat> f3(NumberFormat::createCurrencyInstance(SRC_LOC, status));
308 LocalPointer<NumberFormat> f3a(NumberFormat::createCurrencyInstance(SRC_LOC, status));
309 LocalPointer<NumberFormat> f4(NumberFormat::createInstance(SRC_LOC, status));
310
311 StringEnumeration* locs = NumberFormat::getAvailableLocales();
312
313 LocalUNumberFormatPointer uf3(unum_open(UNUM_CURRENCY, NULL, 0, SRC_LOC.getName(), NULL, &status));
314 LocalUNumberFormatPointer uf4(unum_open(UNUM_DEFAULT, NULL, 0, SRC_LOC.getName(), NULL, &status));
315
316 const UnicodeString* res;
317 for (res = locs->snext(status); res; res = locs->snext(status)) {
318 logln(*res); // service is still in synch
319 }
320
321 NumberFormat::unregister(key, status); // restore for other tests
322 LocalPointer<NumberFormat> f5(NumberFormat::createCurrencyInstance(SRC_LOC, status));
323 LocalUNumberFormatPointer uf5(unum_open(UNUM_CURRENCY, NULL, 0, SRC_LOC.getName(), NULL, &status));
324
325 if (U_FAILURE(status)) {
326 dataerrln("Error creating instnaces.");
327 return;
328 } else {
329 float n = 1234.567f;
330 UnicodeString res0, res1, res2, res3, res4, res5;
331 UChar ures3[50];
332 UChar ures4[50];
333 UChar ures5[50];
334
335 f0->format(n, res0);
336 f1->format(n, res1);
337 f2->format(n, res2);
338 f3->format(n, res3);
339 f4->format(n, res4);
340 f5->format(n, res5);
341
342 unum_formatDouble(uf3.getAlias(), n, ures3, 50, NULL, &status);
343 unum_formatDouble(uf4.getAlias(), n, ures4, 50, NULL, &status);
344 unum_formatDouble(uf5.getAlias(), n, ures5, 50, NULL, &status);
345
346 logln((UnicodeString)"f0 swap int: " + res0);
347 logln((UnicodeString)"f1 src int: " + res1);
348 logln((UnicodeString)"f2 src cur: " + res2);
349 logln((UnicodeString)"f3 reg cur: " + res3);
350 logln((UnicodeString)"f4 reg int: " + res4);
351 logln((UnicodeString)"f5 unreg cur: " + res5);
352 log("uf3 reg cur: ");
353 logln(ures3);
354 log("uf4 reg int: ");
355 logln(ures4);
356 log("uf5 ureg cur: ");
357 logln(ures5);
358
359 if (f3.getAlias() == f3a.getAlias()) {
360 errln("did not get new instance from service");
361 f3a.orphan();
362 }
363 if (res3 != res0) {
364 errln("registered service did not match");
365 }
366 if (res4 != res1) {
367 errln("registered service did not inherit");
368 }
369 if (res5 != res2) {
370 errln("unregistered service did not match original");
371 }
372
373 if (res0 != ures3) {
374 errln("registered service did not match / unum");
375 }
376 if (res1 != ures4) {
377 errln("registered service did not inherit / unum");
378 }
379 if (res2 != ures5) {
380 errln("unregistered service did not match original / unum");
381 }
382 }
383
384 for (res = locs->snext(status); res; res = locs->snext(status)) {
385 errln(*res); // service should be out of synch
386 }
387
388 locs->reset(status); // now in synch again, we hope
389 for (res = locs->snext(status); res; res = locs->snext(status)) {
390 logln(*res);
391 }
392
393 delete locs;
394 #endif
395 }
396
397
398 #endif /* #if !UCONFIG_NO_FORMATTING */
399