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 void testIssue22378(); 107 108 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 109 110 private: 111 CurrencyUnit USD; 112 CurrencyUnit GBP; 113 CurrencyUnit CZK; 114 CurrencyUnit CAD; 115 CurrencyUnit ESP; 116 CurrencyUnit PTE; 117 CurrencyUnit RON; 118 CurrencyUnit TWD; 119 CurrencyUnit TRY; 120 CurrencyUnit CNY; 121 122 MeasureUnit METER; 123 MeasureUnit METER_PER_SECOND; 124 MeasureUnit DAY; 125 MeasureUnit SQUARE_METER; 126 MeasureUnit FAHRENHEIT; 127 MeasureUnit SECOND; 128 MeasureUnit POUND; 129 MeasureUnit POUND_FORCE; 130 MeasureUnit SQUARE_MILE; 131 MeasureUnit SQUARE_INCH; 132 MeasureUnit JOULE; 133 MeasureUnit FURLONG; 134 MeasureUnit KELVIN; 135 136 NumberingSystem MATHSANB; 137 NumberingSystem LATN; 138 139 DecimalFormatSymbols FRENCH_SYMBOLS; 140 DecimalFormatSymbols SWISS_SYMBOLS; 141 DecimalFormatSymbols MYANMAR_SYMBOLS; 142 143 /** 144 * skeleton is the full length skeleton, which must round-trip. 145 * 146 * conciseSkeleton should be the shortest available skeleton. 147 * The concise skeleton can be read but not printed. 148 */ 149 void assertFormatDescending( 150 const char16_t* message, 151 const char16_t* skeleton, 152 const char16_t* conciseSkeleton, 153 const UnlocalizedNumberFormatter& f, 154 Locale locale, 155 ...); 156 157 /** See notes above regarding skeleton vs conciseSkeleton */ 158 void assertFormatDescendingBig( 159 const char16_t* message, 160 const char16_t* skeleton, 161 const char16_t* conciseSkeleton, 162 const UnlocalizedNumberFormatter& f, 163 Locale locale, 164 ...); 165 166 /** See notes above regarding skeleton vs conciseSkeleton */ 167 FormattedNumber assertFormatSingle( 168 const char16_t* message, 169 const char16_t* skeleton, 170 const char16_t* conciseSkeleton, 171 const UnlocalizedNumberFormatter& f, 172 Locale locale, 173 double input, 174 const UnicodeString& expected); 175 176 void assertUndefinedSkeleton(const UnlocalizedNumberFormatter& f); 177 178 void assertNumberFieldPositions( 179 const char16_t* message, 180 const FormattedNumber& formattedNumber, 181 const UFieldPosition* expectedFieldPositions, 182 int32_t length); 183 184 struct UnitInflectionTestCase { 185 const char *unitIdentifier; 186 const char *locale; 187 const char *unitDisplayCase; 188 double value; 189 const UChar *expected; 190 }; 191 192 void runUnitInflectionsTestCases(UnlocalizedNumberFormatter unf, 193 UnicodeString skeleton, 194 const UnitInflectionTestCase *cases, 195 int32_t numCases, 196 IcuTestErrorCode &status); 197 }; 198 199 class DecimalQuantityTest : public IntlTest { 200 public: 201 void testDecimalQuantityBehaviorStandalone(); 202 void testSwitchStorage(); 203 void testCopyMove(); 204 void testAppend(); 205 void testConvertToAccurateDouble(); 206 void testUseApproximateDoubleWhenAble(); 207 void testHardDoubleConversion(); 208 void testFitsInLong(); 209 void testToDouble(); 210 void testMaxDigits(); 211 void testNickelRounding(); 212 void testScientificAndCompactSuppressedExponent(); 213 void testSuppressedExponentUnchangedByInitialScaling(); 214 void testDecimalQuantityParseFormatRoundTrip(); 215 216 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 217 218 private: 219 void assertDoubleEquals(UnicodeString message, double a, double b); 220 void assertHealth(const DecimalQuantity &fq); 221 void assertToStringAndHealth(const DecimalQuantity &fq, const UnicodeString &expected); 222 void checkDoubleBehavior(double d, bool explicitRequired); 223 }; 224 225 class DoubleConversionTest : public IntlTest { 226 public: 227 void testDoubleConversionApi(); 228 229 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 230 }; 231 232 class ModifiersTest : public IntlTest { 233 public: 234 void testConstantAffixModifier(); 235 void testConstantMultiFieldModifier(); 236 void testSimpleModifier(); 237 void testCurrencySpacingEnabledModifier(); 238 239 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 240 241 private: 242 void assertModifierEquals(const Modifier &mod, int32_t expectedPrefixLength, bool expectedStrong, 243 UnicodeString expectedChars, UnicodeString expectedFields, 244 UErrorCode &status); 245 246 void assertModifierEquals(const Modifier &mod, FormattedStringBuilder &sb, int32_t expectedPrefixLength, 247 bool expectedStrong, UnicodeString expectedChars, 248 UnicodeString expectedFields, UErrorCode &status); 249 }; 250 251 class PatternModifierTest : public IntlTest { 252 public: 253 void testBasic(); 254 void testPatternWithNoPlaceholder(); 255 void testMutableEqualsImmutable(); 256 257 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 258 259 private: 260 UnicodeString getPrefix(const MutablePatternModifier &mod, UErrorCode &status); 261 UnicodeString getSuffix(const MutablePatternModifier &mod, UErrorCode &status); 262 }; 263 264 class PatternStringTest : public IntlTestWithFieldPosition { 265 public: 266 void testLocalized(); 267 void testToPatternSimple(); 268 void testExceptionOnInvalid(); 269 void testBug13117(); 270 void testCurrencyDecimal(); 271 272 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 273 274 private: 275 }; 276 277 class NumberParserTest : public IntlTest { 278 public: 279 void testBasic(); 280 void testLocaleFi(); 281 void testSeriesMatcher(); 282 void testCombinedCurrencyMatcher(); 283 void testAffixPatternMatcher(); 284 void testGroupingDisabled(); 285 void testCaseFolding(); 286 void test20360_BidiOverflow(); 287 void testInfiniteRecursion(); 288 289 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 290 }; 291 292 class NumberSkeletonTest : public IntlTest { 293 public: 294 void validTokens(); 295 void invalidTokens(); 296 void unknownTokens(); 297 void unexpectedTokens(); 298 void duplicateValues(); 299 void stemsRequiringOption(); 300 void defaultTokens(); 301 void flexibleSeparators(); 302 void wildcardCharacters(); 303 void perUnitInArabic(); 304 void perUnitToSkeleton(); 305 306 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 307 308 private: 309 void expectedErrorSkeleton(const char16_t** cases, int32_t casesLen); 310 }; 311 312 class NumberRangeFormatterTest : public IntlTestWithFieldPosition { 313 public: 314 NumberRangeFormatterTest(); 315 NumberRangeFormatterTest(UErrorCode &status); 316 317 void testSanity(); 318 void testBasic(); 319 void testCollapse(); 320 void testIdentity(); 321 void testDifferentFormatters(); 322 void testNaNInfinity(); 323 void testPlurals(); 324 void testFieldPositions(); 325 void testCopyMove(); 326 void toObject(); 327 void testGetDecimalNumbers(); 328 void test21684_Performance(); 329 void test21358_SignPosition(); 330 void test21683_StateLeak(); 331 void testCreateLNRFFromNumberingSystemInSkeleton(); 332 333 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 334 335 private: 336 CurrencyUnit USD; 337 CurrencyUnit CHF; 338 CurrencyUnit GBP; 339 CurrencyUnit PTE; 340 341 MeasureUnit METER; 342 MeasureUnit KILOMETER; 343 MeasureUnit FAHRENHEIT; 344 MeasureUnit KELVIN; 345 346 void assertFormatRange( 347 const char16_t* message, 348 const UnlocalizedNumberRangeFormatter& f, 349 Locale locale, 350 const char16_t* expected_10_50, 351 const char16_t* expected_49_51, 352 const char16_t* expected_50_50, 353 const char16_t* expected_00_30, 354 const char16_t* expected_00_00, 355 const char16_t* expected_30_3K, 356 const char16_t* expected_30K_50K, 357 const char16_t* expected_49K_51K, 358 const char16_t* expected_50K_50K, 359 const char16_t* expected_50K_50M); 360 361 FormattedNumberRange assertFormattedRangeEquals( 362 const char16_t* message, 363 const LocalizedNumberRangeFormatter& l, 364 double first, 365 double second, 366 const char16_t* expected); 367 }; 368 369 class NumberPermutationTest : public IntlTest { 370 public: 371 void testPermutations(); 372 373 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override; 374 }; 375 376 377 // NOTE: This macro is identical to the one in itformat.cpp 378 #define TESTCLASS(id, TestClass) \ 379 case id: \ 380 name = #TestClass; \ 381 if (exec) { \ 382 logln(#TestClass " test---"); \ 383 logln((UnicodeString)""); \ 384 TestClass test; \ 385 callTest(test, par); \ 386 } \ 387 break 388 389 class NumberTest : public IntlTest { 390 public: 391 void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override { 392 if (exec) { 393 logln("TestSuite NumberTest: "); 394 } 395 396 switch (index) { 397 TESTCLASS(0, AffixUtilsTest); 398 TESTCLASS(1, NumberFormatterApiTest); 399 TESTCLASS(2, DecimalQuantityTest); 400 TESTCLASS(3, ModifiersTest); 401 TESTCLASS(4, PatternModifierTest); 402 TESTCLASS(5, PatternStringTest); 403 TESTCLASS(6, DoubleConversionTest); 404 TESTCLASS(7, NumberParserTest); 405 TESTCLASS(8, NumberSkeletonTest); 406 TESTCLASS(9, NumberRangeFormatterTest); 407 TESTCLASS(10, NumberPermutationTest); 408 default: name = ""; break; // needed to end loop 409 } 410 } 411 }; 412 413 #endif /* #if !UCONFIG_NO_FORMATTING */ 414