// © 2016 and later: Unicode, Inc. and others. // License & terms of use: http://www.unicode.org/copyright.html #include "unicode/utypes.h" #if !UCONFIG_NO_FORMATTING #include <set> #include "unicode/formattedvalue.h" #include "unicode/unum.h" #include "unicode/udat.h" #include "intltest.h" #include "itformat.h" class FormattedValueTest : public IntlTest { public: void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par=0); private: void testBasic(); void testSetters(); void testLocalPointer(); void assertAllPartsEqual( UnicodeString messagePrefix, const ConstrainedFieldPosition& cfpos, int32_t matching, UFieldCategory category, int32_t field, int32_t start, int32_t limit, int64_t context); }; void FormattedValueTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char *) { if (exec) { logln("TestSuite FormattedValueTest: "); } TESTCASE_AUTO_BEGIN; TESTCASE_AUTO(testBasic); TESTCASE_AUTO(testSetters); TESTCASE_AUTO(testLocalPointer); TESTCASE_AUTO_END; } void FormattedValueTest::testBasic() { IcuTestErrorCode status(*this, "testBasic"); ConstrainedFieldPosition cfpos; assertAllPartsEqual( u"basic", cfpos, 7, UFIELD_CATEGORY_UNDEFINED, 0, 0, 0, 0LL); } void FormattedValueTest::testSetters() { IcuTestErrorCode status(*this, "testSetters"); ConstrainedFieldPosition cfpos; cfpos.constrainCategory(UFIELD_CATEGORY_DATE); assertAllPartsEqual( u"setters 0", cfpos, 4, UFIELD_CATEGORY_DATE, 0, 0, 0, 0LL); cfpos.constrainField(UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD); assertAllPartsEqual( u"setters 1", cfpos, 2, UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD, 0, 0, 0LL); cfpos.setInt64IterationContext(42424242424242LL); assertAllPartsEqual( u"setters 2", cfpos, 2, UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD, 0, 0, 42424242424242LL); cfpos.setState(UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD, 5, 10); assertAllPartsEqual( u"setters 3", cfpos, 2, UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD, 5, 10, 42424242424242LL); cfpos.reset(); assertAllPartsEqual( u"setters 4", cfpos, 7, UFIELD_CATEGORY_UNDEFINED, 0, 0, 0, 0LL); } void FormattedValueTest::testLocalPointer() { UErrorCode status = U_ZERO_ERROR; LocalUConstrainedFieldPositionPointer ucfpos(ucfpos_open(&status)); assertSuccess("Openining LocalUConstrainedFieldPositionPointer", status); assertEquals(u"Test that object is valid", 0LL, ucfpos_getInt64IterationContext(ucfpos.getAlias(), &status)); assertSuccess("Using LocalUConstrainedFieldPositionPointer", status); } /** For matching, turn on these bits: * * 1 = UNUM_INTEGER_FIELD * 2 = UNUM_COMPACT_FIELD * 4 = UDAT_AM_PM_FIELD */ void FormattedValueTest::assertAllPartsEqual( UnicodeString messagePrefix, const ConstrainedFieldPosition& cfpos, int32_t matching, UFieldCategory category, int32_t field, int32_t start, int32_t limit, int64_t context) { assertEquals(messagePrefix + u": category", category, cfpos.getCategory()); assertEquals(messagePrefix + u": field", field, cfpos.getField()); assertEquals(messagePrefix + u": start", start, cfpos.getStart()); assertEquals(messagePrefix + u": limit", limit, cfpos.getLimit()); assertEquals(messagePrefix + u": context", context, cfpos.getInt64IterationContext()); assertEquals(messagePrefix + u": integer field", (UBool) ((matching & 1) != 0), cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_INTEGER_FIELD)); assertEquals(messagePrefix + u": compact field", (UBool) ((matching & 2) != 0), cfpos.matchesField(UFIELD_CATEGORY_NUMBER, UNUM_COMPACT_FIELD)); assertEquals(messagePrefix + u": date field", (UBool) ((matching & 4) != 0), cfpos.matchesField(UFIELD_CATEGORY_DATE, UDAT_AM_PM_FIELD)); } void IntlTestWithFieldPosition::checkFormattedValue( const char16_t* message, const FormattedValue& fv, UnicodeString expectedString, UFieldCategory expectedCategory, const UFieldPosition* expectedFieldPositions, int32_t length) { LocalArray<UFieldPositionWithCategory> converted(new UFieldPositionWithCategory[length]); for (int32_t i=0; i<length; i++) { converted[i].category = expectedCategory; converted[i].field = expectedFieldPositions[i].field; converted[i].beginIndex = expectedFieldPositions[i].beginIndex; converted[i].endIndex = expectedFieldPositions[i].endIndex; } checkMixedFormattedValue(message, fv, expectedString, converted.getAlias(), length); } UnicodeString CFPosToUnicodeString(const ConstrainedFieldPosition& cfpos) { UnicodeString sb; sb.append(u"CFPos["); sb.append(Int64ToUnicodeString(cfpos.getStart())); sb.append(u'-'); sb.append(Int64ToUnicodeString(cfpos.getLimit())); sb.append(u' '); sb.append(Int64ToUnicodeString(cfpos.getCategory())); sb.append(u':'); sb.append(Int64ToUnicodeString(cfpos.getField())); sb.append(u']'); return sb; } void IntlTestWithFieldPosition::checkMixedFormattedValue( const char16_t* message, const FormattedValue& fv, UnicodeString expectedString, const UFieldPositionWithCategory* expectedFieldPositions, int32_t length) { IcuTestErrorCode status(*this, "checkMixedFormattedValue"); UnicodeString baseMessage = UnicodeString(message) + u": " + fv.toString(status) + u": "; // Check string values assertEquals(baseMessage + u"string", expectedString, fv.toString(status)); assertEquals(baseMessage + u"temp string", expectedString, fv.toTempString(status)); // The temp string is guaranteed to be NUL-terminated UnicodeString readOnlyAlias = fv.toTempString(status); if (!status.errIfFailureAndReset()) { assertEquals(baseMessage + u"NUL-terminated", 0, readOnlyAlias.getBuffer()[readOnlyAlias.length()]); } // Check nextPosition over all fields ConstrainedFieldPosition cfpos; for (int32_t i = 0; i < length; i++) { assertTrue(baseMessage + u"A has next position @ " + Int64ToUnicodeString(i), fv.nextPosition(cfpos, status)); int32_t expectedCategory = expectedFieldPositions[i].category; int32_t expectedField = expectedFieldPositions[i].field; int32_t expectedStart = expectedFieldPositions[i].beginIndex; int32_t expectedLimit = expectedFieldPositions[i].endIndex; assertEquals(baseMessage + u"A category @ " + Int64ToUnicodeString(i), expectedCategory, cfpos.getCategory()); assertEquals(baseMessage + u"A field @ " + Int64ToUnicodeString(i), expectedField, cfpos.getField()); assertEquals(baseMessage + u"A start @ " + Int64ToUnicodeString(i), expectedStart, cfpos.getStart()); assertEquals(baseMessage + u"A limit @ " + Int64ToUnicodeString(i), expectedLimit, cfpos.getLimit()); } UBool afterLoopResult = fv.nextPosition(cfpos, status); assertFalse(baseMessage + u"A after loop: " + CFPosToUnicodeString(cfpos), afterLoopResult); afterLoopResult = fv.nextPosition(cfpos, status); assertFalse(baseMessage + u"A after loop again: " + CFPosToUnicodeString(cfpos), afterLoopResult); // Check nextPosition constrained over each category one at a time for (int32_t category=0; category<UFIELD_CATEGORY_COUNT+1; category++) { if (category == UFIELD_CATEGORY_COUNT) { category = UFIELD_CATEGORY_LIST_SPAN; } cfpos.reset(); cfpos.constrainCategory(static_cast<UFieldCategory>(category)); for (int32_t i = 0; i < length; i++) { if (expectedFieldPositions[i].category != category) { continue; } assertTrue(baseMessage + u"B has next position @ " + Int64ToUnicodeString(i), fv.nextPosition(cfpos, status)); int32_t expectedCategory = expectedFieldPositions[i].category; int32_t expectedField = expectedFieldPositions[i].field; int32_t expectedStart = expectedFieldPositions[i].beginIndex; int32_t expectedLimit = expectedFieldPositions[i].endIndex; assertEquals(baseMessage + u"B category @ " + Int64ToUnicodeString(i), expectedCategory, cfpos.getCategory()); assertEquals(baseMessage + u"B field @ " + Int64ToUnicodeString(i), expectedField, cfpos.getField()); assertEquals(baseMessage + u"B start @ " + Int64ToUnicodeString(i), expectedStart, cfpos.getStart()); assertEquals(baseMessage + u"B limit @ " + Int64ToUnicodeString(i), expectedLimit, cfpos.getLimit()); } UBool afterLoopResult = fv.nextPosition(cfpos, status); assertFalse(baseMessage + u"B after loop @ " + CFPosToUnicodeString(cfpos), afterLoopResult); afterLoopResult = fv.nextPosition(cfpos, status); assertFalse(baseMessage + u"B after loop again @ " + CFPosToUnicodeString(cfpos), afterLoopResult); } // Check nextPosition constrained over each field one at a time std::set<std::pair<UFieldCategory, int32_t>> uniqueFields; for (int32_t i = 0; i < length; i++) { uniqueFields.insert({expectedFieldPositions[i].category, expectedFieldPositions[i].field}); } for (std::pair<UFieldCategory, int32_t> categoryAndField : uniqueFields) { cfpos.reset(); cfpos.constrainField(categoryAndField.first, categoryAndField.second); for (int32_t i = 0; i < length; i++) { if (expectedFieldPositions[i].category != categoryAndField.first) { continue; } if (expectedFieldPositions[i].field != categoryAndField.second) { continue; } assertTrue(baseMessage + u"C has next position @ " + Int64ToUnicodeString(i), fv.nextPosition(cfpos, status)); int32_t expectedCategory = expectedFieldPositions[i].category; int32_t expectedField = expectedFieldPositions[i].field; int32_t expectedStart = expectedFieldPositions[i].beginIndex; int32_t expectedLimit = expectedFieldPositions[i].endIndex; assertEquals(baseMessage + u"C category @ " + Int64ToUnicodeString(i), expectedCategory, cfpos.getCategory()); assertEquals(baseMessage + u"C field @ " + Int64ToUnicodeString(i), expectedField, cfpos.getField()); assertEquals(baseMessage + u"C start @ " + Int64ToUnicodeString(i), expectedStart, cfpos.getStart()); assertEquals(baseMessage + u"C limit @ " + Int64ToUnicodeString(i), expectedLimit, cfpos.getLimit()); } UBool afterLoopResult = fv.nextPosition(cfpos, status); assertFalse(baseMessage + u"C after loop: " + CFPosToUnicodeString(cfpos), afterLoopResult); afterLoopResult = fv.nextPosition(cfpos, status); assertFalse(baseMessage + u"C after loop again: " + CFPosToUnicodeString(cfpos), afterLoopResult); } } extern IntlTest *createFormattedValueTest() { return new FormattedValueTest(); } #endif /* !UCONFIG_NO_FORMATTING */