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