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