// Copyright (C) 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html /*********************************************************************** * COPYRIGHT: * Copyright (c) 1997-2010, International Business Machines Corporation * and others. All Rights Reserved. ***********************************************************************/ #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING #include "nmfmapts.h" #include "unicode/numfmt.h" #include "unicode/decimfmt.h" #include "unicode/locid.h" #include "unicode/unum.h" #include "unicode/strenum.h" // This is an API test, not a unit test. It doesn't test very many cases, and doesn't // try to test the full functionality. It just calls each function in the class and // verifies that it works on a basic level. void IntlTestNumberFormatAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) { if (exec) logln("TestSuite NumberFormatAPI"); switch (index) { case 0: name = "NumberFormat API test"; if (exec) { logln("NumberFormat API test---"); logln(""); UErrorCode status = U_ZERO_ERROR; Locale saveLocale; Locale::setDefault(Locale::getEnglish(), status); if(U_FAILURE(status)) { errln("ERROR: Could not set default locale, test may not give correct results"); } testAPI(/* par */); Locale::setDefault(saveLocale, status); } break; case 1: name = "NumberFormatRegistration"; if (exec) { logln("NumberFormat Registration test---"); logln(""); UErrorCode status = U_ZERO_ERROR; Locale saveLocale; Locale::setDefault(Locale::getEnglish(), status); if(U_FAILURE(status)) { errln("ERROR: Could not set default locale, test may not give correct results"); } testRegistration(); Locale::setDefault(saveLocale, status); } break; default: name = ""; break; } } /** * This test does round-trip testing (format -> parse -> format -> parse -> etc.) of * NumberFormat. */ void IntlTestNumberFormatAPI::testAPI(/* char* par */) { UErrorCode status = U_ZERO_ERROR; // ======= Test constructors logln("Testing NumberFormat constructors"); NumberFormat *def = NumberFormat::createInstance(status); if(U_FAILURE(status)) { dataerrln("ERROR: Could not create NumberFormat (default) - %s", u_errorName(status)); } status = U_ZERO_ERROR; NumberFormat *fr = NumberFormat::createInstance(Locale::getFrench(), status); if(U_FAILURE(status)) { dataerrln("ERROR: Could not create NumberFormat (French) - %s", u_errorName(status)); } NumberFormat *cur = NumberFormat::createCurrencyInstance(status); if(U_FAILURE(status)) { dataerrln("ERROR: Could not create NumberFormat (currency, default) - %s", u_errorName(status)); } status = U_ZERO_ERROR; NumberFormat *cur_fr = NumberFormat::createCurrencyInstance(Locale::getFrench(), status); if(U_FAILURE(status)) { dataerrln("ERROR: Could not create NumberFormat (currency, French) - %s", u_errorName(status)); } NumberFormat *per = NumberFormat::createPercentInstance(status); if(U_FAILURE(status)) { dataerrln("ERROR: Could not create NumberFormat (percent, default) - %s", u_errorName(status)); } status = U_ZERO_ERROR; NumberFormat *per_fr = NumberFormat::createPercentInstance(Locale::getFrench(), status); if(U_FAILURE(status)) { dataerrln("ERROR: Could not create NumberFormat (percent, French) - %s", u_errorName(status)); } // ======= Test equality if (per_fr != NULL && cur_fr != NULL) { logln("Testing equality operator"); if( *per_fr == *cur_fr || ! ( *per_fr != *cur_fr) ) { errln("ERROR: == failed"); } } // ======= Test various format() methods if (cur_fr != NULL) { logln("Testing various format() methods"); double d = -10456.0037; int32_t l = 100000000; Formattable fD(d); Formattable fL(l); UnicodeString res1, res2, res3, res4, res5, res6; FieldPosition pos1(FieldPosition::DONT_CARE), pos2(FieldPosition::DONT_CARE), pos3(FieldPosition::DONT_CARE), pos4(FieldPosition::DONT_CARE); res1 = cur_fr->format(d, res1); logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res1); res2 = cur_fr->format(l, res2); logln((UnicodeString) "" + (int32_t) l + " formatted to " + res2); res3 = cur_fr->format(d, res3, pos1); logln( (UnicodeString) "" + (int32_t) d + " formatted to " + res3); res4 = cur_fr->format(l, res4, pos2); logln((UnicodeString) "" + (int32_t) l + " formatted to " + res4); status = U_ZERO_ERROR; res5 = cur_fr->format(fD, res5, pos3, status); if(U_FAILURE(status)) { errln("ERROR: format(Formattable [double]) failed"); } logln((UnicodeString) "" + (int32_t) fD.getDouble() + " formatted to " + res5); status = U_ZERO_ERROR; res6 = cur_fr->format(fL, res6, pos4, status); if(U_FAILURE(status)) { errln("ERROR: format(Formattable [long]) failed"); } logln((UnicodeString) "" + fL.getLong() + " formatted to " + res6); } // ======= Test parse() if (fr != NULL) { logln("Testing parse()"); double d = -10456.0037; UnicodeString text("-10,456.0037"); Formattable result1, result2, result3; ParsePosition pos(0), pos01(0); fr->parseObject(text, result1, pos); if(result1.getType() != Formattable::kDouble && result1.getDouble() != d) { errln("ERROR: Roundtrip failed (via parse()) for " + text); } logln(text + " parsed into " + (int32_t) result1.getDouble()); fr->parse(text, result2, pos01); if(result2.getType() != Formattable::kDouble && result2.getDouble() != d) { errln("ERROR: Roundtrip failed (via parse()) for " + text); } logln(text + " parsed into " + (int32_t) result2.getDouble()); status = U_ZERO_ERROR; fr->parse(text, result3, status); if(U_FAILURE(status)) { errln("ERROR: parse() failed"); } if(result3.getType() != Formattable::kDouble && result3.getDouble() != d) { errln("ERROR: Roundtrip failed (via parse()) for " + text); } logln(text + " parsed into " + (int32_t) result3.getDouble()); } // ======= Test getters and setters if (fr != NULL && def != NULL) { logln("Testing getters and setters"); int32_t count = 0; const Locale *locales = NumberFormat::getAvailableLocales(count); logln((UnicodeString) "Got " + count + " locales" ); for(int32_t i = 0; i < count; i++) { UnicodeString name(locales[i].getName(),""); logln(name); } fr->setParseIntegerOnly( def->isParseIntegerOnly() ); if(fr->isParseIntegerOnly() != def->isParseIntegerOnly() ) { errln("ERROR: setParseIntegerOnly() failed"); } fr->setGroupingUsed( def->isGroupingUsed() ); if(fr->isGroupingUsed() != def->isGroupingUsed() ) { errln("ERROR: setGroupingUsed() failed"); } fr->setMaximumIntegerDigits( def->getMaximumIntegerDigits() ); if(fr->getMaximumIntegerDigits() != def->getMaximumIntegerDigits() ) { errln("ERROR: setMaximumIntegerDigits() failed"); } fr->setMinimumIntegerDigits( def->getMinimumIntegerDigits() ); if(fr->getMinimumIntegerDigits() != def->getMinimumIntegerDigits() ) { errln("ERROR: setMinimumIntegerDigits() failed"); } fr->setMaximumFractionDigits( def->getMaximumFractionDigits() ); if(fr->getMaximumFractionDigits() != def->getMaximumFractionDigits() ) { errln("ERROR: setMaximumFractionDigits() failed"); } fr->setMinimumFractionDigits( def->getMinimumFractionDigits() ); if(fr->getMinimumFractionDigits() != def->getMinimumFractionDigits() ) { errln("ERROR: setMinimumFractionDigits() failed"); } } // ======= Test getStaticClassID() logln("Testing getStaticClassID()"); status = U_ZERO_ERROR; NumberFormat *test = new DecimalFormat(status); if(U_FAILURE(status)) { errcheckln(status, "ERROR: Couldn't create a NumberFormat - %s", u_errorName(status)); } if(test->getDynamicClassID() != DecimalFormat::getStaticClassID()) { errln("ERROR: getDynamicClassID() didn't return the expected value"); } delete test; delete def; delete fr; delete cur; delete cur_fr; delete per; delete per_fr; } #if !UCONFIG_NO_SERVICE #define SRC_LOC Locale::getFrance() #define SWAP_LOC Locale::getUS() class NFTestFactory : public SimpleNumberFormatFactory { NumberFormat* currencyStyle; public: NFTestFactory() : SimpleNumberFormatFactory(SRC_LOC, TRUE) { UErrorCode status = U_ZERO_ERROR; currencyStyle = NumberFormat::createInstance(SWAP_LOC, status); } virtual ~NFTestFactory() { delete currencyStyle; } virtual NumberFormat* createFormat(const Locale& /* loc */, UNumberFormatStyle formatType) { if (formatType == UNUM_CURRENCY) { return (NumberFormat*)currencyStyle->clone(); } return NULL; } virtual inline UClassID getDynamicClassID() const { return (UClassID)&gID; } static inline UClassID getStaticClassID() { return (UClassID)&gID; } private: static char gID; }; char NFTestFactory::gID = 0; #endif void IntlTestNumberFormatAPI::testRegistration() { #if !UCONFIG_NO_SERVICE UErrorCode status = U_ZERO_ERROR; LocalPointer f0(NumberFormat::createInstance(SWAP_LOC, status)); LocalPointer f1(NumberFormat::createInstance(SRC_LOC, status)); LocalPointer f2(NumberFormat::createCurrencyInstance(SRC_LOC, status)); URegistryKey key = NumberFormat::registerFactory(new NFTestFactory(), status); LocalPointer f3(NumberFormat::createCurrencyInstance(SRC_LOC, status)); LocalPointer f3a(NumberFormat::createCurrencyInstance(SRC_LOC, status)); LocalPointer f4(NumberFormat::createInstance(SRC_LOC, status)); StringEnumeration* locs = NumberFormat::getAvailableLocales(); LocalUNumberFormatPointer uf3(unum_open(UNUM_CURRENCY, NULL, 0, SRC_LOC.getName(), NULL, &status)); LocalUNumberFormatPointer uf4(unum_open(UNUM_DEFAULT, NULL, 0, SRC_LOC.getName(), NULL, &status)); const UnicodeString* res; for (res = locs->snext(status); res; res = locs->snext(status)) { logln(*res); // service is still in synch } NumberFormat::unregister(key, status); // restore for other tests LocalPointer f5(NumberFormat::createCurrencyInstance(SRC_LOC, status)); LocalUNumberFormatPointer uf5(unum_open(UNUM_CURRENCY, NULL, 0, SRC_LOC.getName(), NULL, &status)); if (U_FAILURE(status)) { dataerrln("Error creating instnaces."); return; } else { float n = 1234.567f; UnicodeString res0, res1, res2, res3, res4, res5; UChar ures3[50]; UChar ures4[50]; UChar ures5[50]; f0->format(n, res0); f1->format(n, res1); f2->format(n, res2); f3->format(n, res3); f4->format(n, res4); f5->format(n, res5); unum_formatDouble(uf3.getAlias(), n, ures3, 50, NULL, &status); unum_formatDouble(uf4.getAlias(), n, ures4, 50, NULL, &status); unum_formatDouble(uf5.getAlias(), n, ures5, 50, NULL, &status); logln((UnicodeString)"f0 swap int: " + res0); logln((UnicodeString)"f1 src int: " + res1); logln((UnicodeString)"f2 src cur: " + res2); logln((UnicodeString)"f3 reg cur: " + res3); logln((UnicodeString)"f4 reg int: " + res4); logln((UnicodeString)"f5 unreg cur: " + res5); log("uf3 reg cur: "); logln(ures3); log("uf4 reg int: "); logln(ures4); log("uf5 ureg cur: "); logln(ures5); if (f3.getAlias() == f3a.getAlias()) { errln("did not get new instance from service"); f3a.orphan(); } if (res3 != res0) { errln("registered service did not match"); } if (res4 != res1) { errln("registered service did not inherit"); } if (res5 != res2) { errln("unregistered service did not match original"); } if (res0 != ures3) { errln("registered service did not match / unum"); } if (res1 != ures4) { errln("registered service did not inherit / unum"); } if (res2 != ures5) { errln("unregistered service did not match original / unum"); } } for (res = locs->snext(status); res; res = locs->snext(status)) { errln(*res); // service should be out of synch } locs->reset(status); // now in synch again, we hope for (res = locs->snext(status); res; res = locs->snext(status)) { logln(*res); } delete locs; #endif } #endif /* #if !UCONFIG_NO_FORMATTING */