blob: 802b8bb725d09b945a857332dfe517195f028d9f [file] [log] [blame]
// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
#include "unicode/utypes.h"
#if !UCONFIG_NO_FORMATTING
#pragma once
#include "formatted_string_builder.h"
#include "intltest.h"
#include "itformat.h"
#include "number_affixutils.h"
#include "string_segment.h"
#include "numrange_impl.h"
#include "unicode/locid.h"
#include "unicode/numberformatter.h"
#include "unicode/numberrangeformatter.h"
using namespace icu::number;
using namespace icu::number::impl;
using namespace icu::numparse;
using namespace icu::numparse::impl;
////////////////////////////////////////////////////////////////////////////////////////
// INSTRUCTIONS: //
// To add new NumberFormat unit test classes, create a new class like the ones below, //
// and then add it as a switch statement in NumberTest at the bottom of this file. /////////
// To add new methods to existing unit test classes, add the method to the class declaration //
// below, and also add it to the class's implementation of runIndexedTest(). //
///////////////////////////////////////////////////////////////////////////////////////////////
class AffixUtilsTest : public IntlTest {
public:
void testEscape();
void testUnescape();
void testContainsReplaceType();
void testInvalid();
void testUnescapeWithSymbolProvider();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
private:
UnicodeString unescapeWithDefaults(const SymbolProvider &defaultProvider, UnicodeString input,
UErrorCode &status);
};
class NumberFormatterApiTest : public IntlTestWithFieldPosition {
public:
NumberFormatterApiTest();
NumberFormatterApiTest(UErrorCode &status);
void notationSimple();
void notationScientific();
void notationCompact();
void unitMeasure();
void unitCompoundMeasure();
void unitUsage();
void unitUsageErrorCodes();
void unitUsageSkeletons();
void unitCurrency();
void unitPercent();
void percentParity();
void roundingFraction();
void roundingFigures();
void roundingFractionFigures();
void roundingOther();
void grouping();
void padding();
void integerWidth();
void symbols();
// TODO: Add this method if currency symbols override support is added.
//void symbolsOverride();
void sign();
void signNearZero();
void signCoverage();
void decimal();
void scale();
void locale();
void skeletonUserGuideExamples();
void formatTypes();
void fieldPositionLogic();
void fieldPositionCoverage();
void toFormat();
void errors();
void validRanges();
void copyMove();
void localPointerCAPI();
void toObject();
void toDecimalNumber();
void microPropsInternals();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
private:
CurrencyUnit USD;
CurrencyUnit GBP;
CurrencyUnit CZK;
CurrencyUnit CAD;
CurrencyUnit ESP;
CurrencyUnit PTE;
CurrencyUnit RON;
CurrencyUnit TWD;
CurrencyUnit TRY;
CurrencyUnit CNY;
MeasureUnit METER;
MeasureUnit DAY;
MeasureUnit SQUARE_METER;
MeasureUnit FAHRENHEIT;
MeasureUnit SECOND;
MeasureUnit POUND;
MeasureUnit SQUARE_MILE;
MeasureUnit JOULE;
MeasureUnit FURLONG;
MeasureUnit KELVIN;
NumberingSystem MATHSANB;
NumberingSystem LATN;
DecimalFormatSymbols FRENCH_SYMBOLS;
DecimalFormatSymbols SWISS_SYMBOLS;
DecimalFormatSymbols MYANMAR_SYMBOLS;
/**
* skeleton is the full length skeleton, which must round-trip.
*
* conciseSkeleton should be the shortest available skeleton.
* The concise skeleton can be read but not printed.
*/
void assertFormatDescending(
const char16_t* message,
const char16_t* skeleton,
const char16_t* conciseSkeleton,
const UnlocalizedNumberFormatter& f,
Locale locale,
...);
/** See notes above regarding skeleton vs conciseSkeleton */
void assertFormatDescendingBig(
const char16_t* message,
const char16_t* skeleton,
const char16_t* conciseSkeleton,
const UnlocalizedNumberFormatter& f,
Locale locale,
...);
/** See notes above regarding skeleton vs conciseSkeleton */
FormattedNumber assertFormatSingle(
const char16_t* message,
const char16_t* skeleton,
const char16_t* conciseSkeleton,
const UnlocalizedNumberFormatter& f,
Locale locale,
double input,
const UnicodeString& expected);
void assertUndefinedSkeleton(const UnlocalizedNumberFormatter& f);
void assertNumberFieldPositions(
const char16_t* message,
const FormattedNumber& formattedNumber,
const UFieldPosition* expectedFieldPositions,
int32_t length);
};
class DecimalQuantityTest : public IntlTest {
public:
void testDecimalQuantityBehaviorStandalone();
void testSwitchStorage();
void testCopyMove();
void testAppend();
void testConvertToAccurateDouble();
void testUseApproximateDoubleWhenAble();
void testHardDoubleConversion();
void testToDouble();
void testMaxDigits();
void testNickelRounding();
void testCompactDecimalSuppressedExponent();
void testSuppressedExponentUnchangedByInitialScaling();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
private:
void assertDoubleEquals(UnicodeString message, double a, double b);
void assertHealth(const DecimalQuantity &fq);
void assertToStringAndHealth(const DecimalQuantity &fq, const UnicodeString &expected);
void checkDoubleBehavior(double d, bool explicitRequired);
};
class DoubleConversionTest : public IntlTest {
public:
void testDoubleConversionApi();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
};
class ModifiersTest : public IntlTest {
public:
void testConstantAffixModifier();
void testConstantMultiFieldModifier();
void testSimpleModifier();
void testCurrencySpacingEnabledModifier();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
private:
void assertModifierEquals(const Modifier &mod, int32_t expectedPrefixLength, bool expectedStrong,
UnicodeString expectedChars, UnicodeString expectedFields,
UErrorCode &status);
void assertModifierEquals(const Modifier &mod, FormattedStringBuilder &sb, int32_t expectedPrefixLength,
bool expectedStrong, UnicodeString expectedChars,
UnicodeString expectedFields, UErrorCode &status);
};
class PatternModifierTest : public IntlTest {
public:
void testBasic();
void testPatternWithNoPlaceholder();
void testMutableEqualsImmutable();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
private:
UnicodeString getPrefix(const MutablePatternModifier &mod, UErrorCode &status);
UnicodeString getSuffix(const MutablePatternModifier &mod, UErrorCode &status);
};
class PatternStringTest : public IntlTest {
public:
void testLocalized();
void testToPatternSimple();
void testExceptionOnInvalid();
void testBug13117();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
private:
};
class NumberParserTest : public IntlTest {
public:
void testBasic();
void testLocaleFi();
void testSeriesMatcher();
void testCombinedCurrencyMatcher();
void testAffixPatternMatcher();
void testGroupingDisabled();
void testCaseFolding();
void test20360_BidiOverflow();
void testInfiniteRecursion();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
};
class NumberSkeletonTest : public IntlTest {
public:
void validTokens();
void invalidTokens();
void unknownTokens();
void unexpectedTokens();
void duplicateValues();
void stemsRequiringOption();
void defaultTokens();
void flexibleSeparators();
void wildcardCharacters();
void perUnitInArabic();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
private:
void expectedErrorSkeleton(const char16_t** cases, int32_t casesLen);
};
class NumberRangeFormatterTest : public IntlTestWithFieldPosition {
public:
NumberRangeFormatterTest();
NumberRangeFormatterTest(UErrorCode &status);
void testSanity();
void testBasic();
void testCollapse();
void testIdentity();
void testDifferentFormatters();
void testPlurals();
void testFieldPositions();
void testCopyMove();
void toObject();
void testGetDecimalNumbers();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
private:
CurrencyUnit USD;
CurrencyUnit GBP;
CurrencyUnit PTE;
MeasureUnit METER;
MeasureUnit KILOMETER;
MeasureUnit FAHRENHEIT;
MeasureUnit KELVIN;
void assertFormatRange(
const char16_t* message,
const UnlocalizedNumberRangeFormatter& f,
Locale locale,
const char16_t* expected_10_50,
const char16_t* expected_49_51,
const char16_t* expected_50_50,
const char16_t* expected_00_30,
const char16_t* expected_00_00,
const char16_t* expected_30_3K,
const char16_t* expected_30K_50K,
const char16_t* expected_49K_51K,
const char16_t* expected_50K_50K,
const char16_t* expected_50K_50M);
FormattedNumberRange assertFormattedRangeEquals(
const char16_t* message,
const LocalizedNumberRangeFormatter& l,
double first,
double second,
const char16_t* expected);
};
class NumberPermutationTest : public IntlTest {
public:
void testPermutations();
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0);
};
// NOTE: This macro is identical to the one in itformat.cpp
#define TESTCLASS(id, TestClass) \
case id: \
name = #TestClass; \
if (exec) { \
logln(#TestClass " test---"); \
logln((UnicodeString)""); \
TestClass test; \
callTest(test, par); \
} \
break
class NumberTest : public IntlTest {
public:
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) {
if (exec) {
logln("TestSuite NumberTest: ");
}
switch (index) {
TESTCLASS(0, AffixUtilsTest);
TESTCLASS(1, NumberFormatterApiTest);
TESTCLASS(2, DecimalQuantityTest);
TESTCLASS(3, ModifiersTest);
TESTCLASS(4, PatternModifierTest);
TESTCLASS(5, PatternStringTest);
TESTCLASS(6, DoubleConversionTest);
TESTCLASS(7, NumberParserTest);
TESTCLASS(8, NumberSkeletonTest);
TESTCLASS(9, NumberRangeFormatterTest);
TESTCLASS(10, NumberPermutationTest);
default: name = ""; break; // needed to end loop
}
}
};
#endif /* #if !UCONFIG_NO_FORMATTING */