1 // © 2017 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 4 #include "unicode/utypes.h" 5 6 #if !UCONFIG_NO_FORMATTING 7 #pragma once 8 9 #include "formatted_string_builder.h" 10 #include "intltest.h" 11 #include "itformat.h" 12 #include "number_affixutils.h" 13 #include "string_segment.h" 14 #include "numrange_impl.h" 15 #include "unicode/locid.h" 16 #include "unicode/numberformatter.h" 17 #include "unicode/numberrangeformatter.h" 18 19 // ICU-20241 Solaris #defines ESP in sys/regset.h 20 #ifdef ESP 21 # undef ESP 22 #endif 23 24 using namespace icu::number; 25 using namespace icu::number::impl; 26 using namespace icu::numparse; 27 using namespace icu::numparse::impl; 28 29 //////////////////////////////////////////////////////////////////////////////////////// 30 // INSTRUCTIONS: // 31 // To add new NumberFormat unit test classes, create a new class like the ones below, // 32 // and then add it as a switch statement in NumberTest at the bottom of this file. ///////// 33 // To add new methods to existing unit test classes, add the method to the class declaration // 34 // below, and also add it to the class's implementation of runIndexedTest(). // 35 /////////////////////////////////////////////////////////////////////////////////////////////// 36 37 class AffixUtilsTest : public IntlTest { 38 public: 39 void testEscape(); 40 void testUnescape(); 41 void testContainsReplaceType(); 42 void testInvalid(); 43 void testUnescapeWithSymbolProvider(); 44 45 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 46 47 private: 48 UnicodeString unescapeWithDefaults(const SymbolProvider &defaultProvider, UnicodeString input, 49 UErrorCode &status); 50 }; 51 52 class NumberFormatterApiTest : public IntlTestWithFieldPosition { 53 public: 54 NumberFormatterApiTest(); 55 NumberFormatterApiTest(UErrorCode &status); 56 57 void notationSimple(); 58 void notationScientific(); 59 void notationCompact(); 60 void unitMeasure(); 61 void unitCompoundMeasure(); 62 void unitArbitraryMeasureUnits(); 63 void unitSkeletons(); 64 void unitUsage(); 65 void unitUsageErrorCodes(); 66 void unitUsageSkeletons(); 67 void unitCurrency(); 68 void unitInflections(); 69 void unitNounClass(); 70 void unitGender(); 71 void unitNotConvertible(); 72 void unitPercent(); 73 void unitLocaleTags(); 74 void percentParity(); 75 void roundingFraction(); 76 void roundingFigures(); 77 void roundingFractionFigures(); 78 void roundingOther(); 79 void roundingIncrementRegressionTest(); 80 void roundingPriorityCoverageTest(); 81 void grouping(); 82 void padding(); 83 void integerWidth(); 84 void symbols(); 85 // TODO: Add this method if currency symbols override support is added. 86 //void symbolsOverride(); 87 void sign(); 88 void signNearZero(); 89 void signCoverage(); 90 void decimal(); 91 void scale(); 92 void locale(); 93 void skeletonUserGuideExamples(); 94 void formatTypes(); 95 void fieldPositionLogic(); 96 void fieldPositionCoverage(); 97 void toFormat(); 98 void errors(); 99 void validRanges(); 100 void copyMove(); 101 void localPointerCAPI(); 102 void toObject(); 103 void toDecimalNumber(); 104 void microPropsInternals(); 105 void formatUnitsAliases(); 106 107 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 108 109 private: 110 CurrencyUnit USD; 111 CurrencyUnit GBP; 112 CurrencyUnit CZK; 113 CurrencyUnit CAD; 114 CurrencyUnit ESP; 115 CurrencyUnit PTE; 116 CurrencyUnit RON; 117 CurrencyUnit TWD; 118 CurrencyUnit TRY; 119 CurrencyUnit CNY; 120 121 MeasureUnit METER; 122 MeasureUnit METER_PER_SECOND; 123 MeasureUnit DAY; 124 MeasureUnit SQUARE_METER; 125 MeasureUnit FAHRENHEIT; 126 MeasureUnit SECOND; 127 MeasureUnit POUND; 128 MeasureUnit POUND_FORCE; 129 MeasureUnit SQUARE_MILE; 130 MeasureUnit SQUARE_INCH; 131 MeasureUnit JOULE; 132 MeasureUnit FURLONG; 133 MeasureUnit KELVIN; 134 135 NumberingSystem MATHSANB; 136 NumberingSystem LATN; 137 138 DecimalFormatSymbols FRENCH_SYMBOLS; 139 DecimalFormatSymbols SWISS_SYMBOLS; 140 DecimalFormatSymbols MYANMAR_SYMBOLS; 141 142 /** 143 * skeleton is the full length skeleton, which must round-trip. 144 * 145 * conciseSkeleton should be the shortest available skeleton. 146 * The concise skeleton can be read but not printed. 147 */ 148 void assertFormatDescending( 149 const char16_t* message, 150 const char16_t* skeleton, 151 const char16_t* conciseSkeleton, 152 const UnlocalizedNumberFormatter& f, 153 Locale locale, 154 ...); 155 156 /** See notes above regarding skeleton vs conciseSkeleton */ 157 void assertFormatDescendingBig( 158 const char16_t* message, 159 const char16_t* skeleton, 160 const char16_t* conciseSkeleton, 161 const UnlocalizedNumberFormatter& f, 162 Locale locale, 163 ...); 164 165 /** See notes above regarding skeleton vs conciseSkeleton */ 166 FormattedNumber assertFormatSingle( 167 const char16_t* message, 168 const char16_t* skeleton, 169 const char16_t* conciseSkeleton, 170 const UnlocalizedNumberFormatter& f, 171 Locale locale, 172 double input, 173 const UnicodeString& expected); 174 175 void assertUndefinedSkeleton(const UnlocalizedNumberFormatter& f); 176 177 void assertNumberFieldPositions( 178 const char16_t* message, 179 const FormattedNumber& formattedNumber, 180 const UFieldPosition* expectedFieldPositions, 181 int32_t length); 182 183 struct UnitInflectionTestCase { 184 const char *unitIdentifier; 185 const char *locale; 186 const char *unitDisplayCase; 187 double value; 188 const UChar *expected; 189 }; 190 191 void runUnitInflectionsTestCases(UnlocalizedNumberFormatter unf, 192 UnicodeString skeleton, 193 const UnitInflectionTestCase *cases, 194 int32_t numCases, 195 IcuTestErrorCode &status); 196 }; 197 198 class DecimalQuantityTest : public IntlTest { 199 public: 200 void testDecimalQuantityBehaviorStandalone(); 201 void testSwitchStorage(); 202 void testCopyMove(); 203 void testAppend(); 204 void testConvertToAccurateDouble(); 205 void testUseApproximateDoubleWhenAble(); 206 void testHardDoubleConversion(); 207 void testFitsInLong(); 208 void testToDouble(); 209 void testMaxDigits(); 210 void testNickelRounding(); 211 void testScientificAndCompactSuppressedExponent(); 212 void testSuppressedExponentUnchangedByInitialScaling(); 213 void testDecimalQuantityParseFormatRoundTrip(); 214 215 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 216 217 private: 218 void assertDoubleEquals(UnicodeString message, double a, double b); 219 void assertHealth(const DecimalQuantity &fq); 220 void assertToStringAndHealth(const DecimalQuantity &fq, const UnicodeString &expected); 221 void checkDoubleBehavior(double d, bool explicitRequired); 222 }; 223 224 class DoubleConversionTest : public IntlTest { 225 public: 226 void testDoubleConversionApi(); 227 228 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 229 }; 230 231 class ModifiersTest : public IntlTest { 232 public: 233 void testConstantAffixModifier(); 234 void testConstantMultiFieldModifier(); 235 void testSimpleModifier(); 236 void testCurrencySpacingEnabledModifier(); 237 238 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 239 240 private: 241 void assertModifierEquals(const Modifier &mod, int32_t expectedPrefixLength, bool expectedStrong, 242 UnicodeString expectedChars, UnicodeString expectedFields, 243 UErrorCode &status); 244 245 void assertModifierEquals(const Modifier &mod, FormattedStringBuilder &sb, int32_t expectedPrefixLength, 246 bool expectedStrong, UnicodeString expectedChars, 247 UnicodeString expectedFields, UErrorCode &status); 248 }; 249 250 class PatternModifierTest : public IntlTest { 251 public: 252 void testBasic(); 253 void testPatternWithNoPlaceholder(); 254 void testMutableEqualsImmutable(); 255 256 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 257 258 private: 259 UnicodeString getPrefix(const MutablePatternModifier &mod, UErrorCode &status); 260 UnicodeString getSuffix(const MutablePatternModifier &mod, UErrorCode &status); 261 }; 262 263 class PatternStringTest : public IntlTestWithFieldPosition { 264 public: 265 void testLocalized(); 266 void testToPatternSimple(); 267 void testExceptionOnInvalid(); 268 void testBug13117(); 269 void testCurrencyDecimal(); 270 271 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 272 273 private: 274 }; 275 276 class NumberParserTest : public IntlTest { 277 public: 278 void testBasic(); 279 void testLocaleFi(); 280 void testSeriesMatcher(); 281 void testCombinedCurrencyMatcher(); 282 void testAffixPatternMatcher(); 283 void testGroupingDisabled(); 284 void testCaseFolding(); 285 void test20360_BidiOverflow(); 286 void testInfiniteRecursion(); 287 288 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 289 }; 290 291 class NumberSkeletonTest : public IntlTest { 292 public: 293 void validTokens(); 294 void invalidTokens(); 295 void unknownTokens(); 296 void unexpectedTokens(); 297 void duplicateValues(); 298 void stemsRequiringOption(); 299 void defaultTokens(); 300 void flexibleSeparators(); 301 void wildcardCharacters(); 302 void perUnitInArabic(); 303 void perUnitToSkeleton(); 304 305 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 306 307 private: 308 void expectedErrorSkeleton(const char16_t** cases, int32_t casesLen); 309 }; 310 311 class NumberRangeFormatterTest : public IntlTestWithFieldPosition { 312 public: 313 NumberRangeFormatterTest(); 314 NumberRangeFormatterTest(UErrorCode &status); 315 316 void testSanity(); 317 void testBasic(); 318 void testCollapse(); 319 void testIdentity(); 320 void testDifferentFormatters(); 321 void testNaNInfinity(); 322 void testPlurals(); 323 void testFieldPositions(); 324 void testCopyMove(); 325 void toObject(); 326 void testGetDecimalNumbers(); 327 void test21684_Performance(); 328 void test21358_SignPosition(); 329 void test21683_StateLeak(); 330 void testCreateLNRFFromNumberingSystemInSkeleton(); 331 332 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 333 334 private: 335 CurrencyUnit USD; 336 CurrencyUnit CHF; 337 CurrencyUnit GBP; 338 CurrencyUnit PTE; 339 340 MeasureUnit METER; 341 MeasureUnit KILOMETER; 342 MeasureUnit FAHRENHEIT; 343 MeasureUnit KELVIN; 344 345 void assertFormatRange( 346 const char16_t* message, 347 const UnlocalizedNumberRangeFormatter& f, 348 Locale locale, 349 const char16_t* expected_10_50, 350 const char16_t* expected_49_51, 351 const char16_t* expected_50_50, 352 const char16_t* expected_00_30, 353 const char16_t* expected_00_00, 354 const char16_t* expected_30_3K, 355 const char16_t* expected_30K_50K, 356 const char16_t* expected_49K_51K, 357 const char16_t* expected_50K_50K, 358 const char16_t* expected_50K_50M); 359 360 FormattedNumberRange assertFormattedRangeEquals( 361 const char16_t* message, 362 const LocalizedNumberRangeFormatter& l, 363 double first, 364 double second, 365 const char16_t* expected); 366 }; 367 368 class NumberPermutationTest : public IntlTest { 369 public: 370 void testPermutations(); 371 372 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 373 }; 374 375 376 // NOTE: This macro is identical to the one in itformat.cpp 377 #define TESTCLASS(id, TestClass) \ 378 case id: \ 379 name = #TestClass; \ 380 if (exec) { \ 381 logln(#TestClass " test---"); \ 382 logln((UnicodeString)""); \ 383 TestClass test; \ 384 callTest(test, par); \ 385 } \ 386 break 387 388 class NumberTest : public IntlTest { 389 public: 390 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override { 391 if (exec) { 392 logln("TestSuite NumberTest: "); 393 } 394 395 switch (index) { 396 TESTCLASS(0, AffixUtilsTest); 397 TESTCLASS(1, NumberFormatterApiTest); 398 TESTCLASS(2, DecimalQuantityTest); 399 TESTCLASS(3, ModifiersTest); 400 TESTCLASS(4, PatternModifierTest); 401 TESTCLASS(5, PatternStringTest); 402 TESTCLASS(6, DoubleConversionTest); 403 TESTCLASS(7, NumberParserTest); 404 TESTCLASS(8, NumberSkeletonTest); 405 TESTCLASS(9, NumberRangeFormatterTest); 406 TESTCLASS(10, NumberPermutationTest); 407 default: name = ""; break; // needed to end loop 408 } 409 } 410 }; 411 412 #endif /* #if !UCONFIG_NO_FORMATTING */ 413