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 8 #include "numbertest.h" 9 #include "number_microprops.h" 10 #include "number_patternmodifier.h" 11 12 void PatternModifierTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char *) { 13 if (exec) { 14 logln("TestSuite PatternModifierTest: "); 15 } 16 TESTCASE_AUTO_BEGIN; 17 TESTCASE_AUTO(testBasic); 18 TESTCASE_AUTO(testPatternWithNoPlaceholder); 19 TESTCASE_AUTO(testMutableEqualsImmutable); 20 TESTCASE_AUTO_END; 21 } 22 23 void PatternModifierTest::testBasic() { 24 UErrorCode status = U_ZERO_ERROR; 25 MutablePatternModifier mod(false); 26 ParsedPatternInfo patternInfo; 27 PatternParser::parseToPatternInfo(u"a0b", patternInfo, status); 28 assertSuccess("Spot 1", status); 29 mod.setPatternInfo(&patternInfo); 30 mod.setPatternAttributes(UNUM_SIGN_AUTO, false); 31 DecimalFormatSymbols symbols(Locale::getEnglish(), status); 32 CurrencySymbols currencySymbols({u"USD", status}, "en", status); 33 if (!assertSuccess("Spot 2", status, true)) { 34 return; 35 } 36 mod.setSymbols(&symbols, ¤cySymbols, UNUM_UNIT_WIDTH_SHORT, nullptr); 37 38 mod.setNumberProperties(1, StandardPlural::Form::COUNT); 39 assertEquals("Pattern a0b", u"a", getPrefix(mod, status)); 40 assertEquals("Pattern a0b", u"b", getSuffix(mod, status)); 41 mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false); 42 assertEquals("Pattern a0b", u"+a", getPrefix(mod, status)); 43 assertEquals("Pattern a0b", u"b", getSuffix(mod, status)); 44 mod.setNumberProperties(0, StandardPlural::Form::COUNT); 45 assertEquals("Pattern a0b", u"+a", getPrefix(mod, status)); 46 assertEquals("Pattern a0b", u"b", getSuffix(mod, status)); 47 mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false); 48 assertEquals("Pattern a0b", u"a", getPrefix(mod, status)); 49 assertEquals("Pattern a0b", u"b", getSuffix(mod, status)); 50 mod.setNumberProperties(-1, StandardPlural::Form::COUNT); 51 assertEquals("Pattern a0b", u"-a", getPrefix(mod, status)); 52 assertEquals("Pattern a0b", u"b", getSuffix(mod, status)); 53 mod.setPatternAttributes(UNUM_SIGN_NEVER, false); 54 assertEquals("Pattern a0b", u"a", getPrefix(mod, status)); 55 assertEquals("Pattern a0b", u"b", getSuffix(mod, status)); 56 assertSuccess("Spot 3", status); 57 58 ParsedPatternInfo patternInfo2; 59 PatternParser::parseToPatternInfo(u"a0b;c-0d", patternInfo2, status); 60 assertSuccess("Spot 4", status); 61 mod.setPatternInfo(&patternInfo2); 62 mod.setPatternAttributes(UNUM_SIGN_AUTO, false); 63 mod.setNumberProperties(1, StandardPlural::Form::COUNT); 64 assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status)); 65 assertEquals("Pattern a0b;c-0d", u"b", getSuffix(mod, status)); 66 mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false); 67 assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status)); 68 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status)); 69 mod.setNumberProperties(0, StandardPlural::Form::COUNT); 70 assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status)); 71 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status)); 72 mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false); 73 assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status)); 74 assertEquals("Pattern a0b;c-0d", u"b", getSuffix(mod, status)); 75 mod.setNumberProperties(-1, StandardPlural::Form::COUNT); 76 assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status)); 77 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status)); 78 mod.setPatternAttributes(UNUM_SIGN_NEVER, false); 79 // TODO: What should this behavior be? 80 assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status)); 81 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status)); 82 assertSuccess("Spot 5", status); 83 } 84 85 void PatternModifierTest::testPatternWithNoPlaceholder() { 86 UErrorCode status = U_ZERO_ERROR; 87 MutablePatternModifier mod(false); 88 ParsedPatternInfo patternInfo; 89 PatternParser::parseToPatternInfo(u"abc", patternInfo, status); 90 assertSuccess("Spot 1", status); 91 mod.setPatternInfo(&patternInfo); 92 mod.setPatternAttributes(UNUM_SIGN_AUTO, false); 93 DecimalFormatSymbols symbols(Locale::getEnglish(), status); 94 CurrencySymbols currencySymbols({u"USD", status}, "en", status); 95 if (!assertSuccess("Spot 2", status, true)) { 96 return; 97 } 98 mod.setSymbols(&symbols, ¤cySymbols, UNUM_UNIT_WIDTH_SHORT, nullptr); 99 mod.setNumberProperties(1, StandardPlural::Form::COUNT); 100 101 // Unsafe Code Path 102 NumberStringBuilder nsb; 103 nsb.append(u"x123y", UNUM_FIELD_COUNT, status); 104 assertSuccess("Spot 3", status); 105 mod.apply(nsb, 1, 4, status); 106 assertSuccess("Spot 4", status); 107 assertEquals("Unsafe Path", u"xabcy", nsb.toUnicodeString()); 108 109 // Safe Code Path 110 nsb.clear(); 111 nsb.append(u"x123y", UNUM_FIELD_COUNT, status); 112 assertSuccess("Spot 5", status); 113 MicroProps micros; 114 LocalPointer<ImmutablePatternModifier> imod(mod.createImmutable(status), status); 115 if (U_FAILURE(status)) { 116 dataerrln("%s %d Error in ImmutablePatternModifier creation", 117 __FILE__, __LINE__); 118 assertSuccess("Spot 6", status); 119 return; 120 } 121 DecimalQuantity quantity; 122 imod->applyToMicros(micros, quantity); 123 micros.modMiddle->apply(nsb, 1, 4, status); 124 assertSuccess("Spot 7", status); 125 assertEquals("Safe Path", u"xabcy", nsb.toUnicodeString()); 126 } 127 128 void PatternModifierTest::testMutableEqualsImmutable() { 129 UErrorCode status = U_ZERO_ERROR; 130 MutablePatternModifier mod(false); 131 ParsedPatternInfo patternInfo; 132 PatternParser::parseToPatternInfo("a0b;c-0d", patternInfo, status); 133 assertSuccess("Spot 1", status); 134 mod.setPatternInfo(&patternInfo); 135 mod.setPatternAttributes(UNUM_SIGN_AUTO, false); 136 DecimalFormatSymbols symbols(Locale::getEnglish(), status); 137 CurrencySymbols currencySymbols({u"USD", status}, "en", status); 138 assertSuccess("Spot 2", status); 139 if (U_FAILURE(status)) { return; } 140 mod.setSymbols(&symbols, ¤cySymbols, UNUM_UNIT_WIDTH_SHORT, nullptr); 141 DecimalQuantity fq; 142 fq.setToInt(1); 143 144 NumberStringBuilder nsb1; 145 MicroProps micros1; 146 mod.addToChain(µs1); 147 mod.processQuantity(fq, micros1, status); 148 micros1.modMiddle->apply(nsb1, 0, 0, status); 149 assertSuccess("Spot 3", status); 150 151 NumberStringBuilder nsb2; 152 MicroProps micros2; 153 LocalPointer<ImmutablePatternModifier> immutable(mod.createImmutable(status)); 154 immutable->applyToMicros(micros2, fq); 155 micros2.modMiddle->apply(nsb2, 0, 0, status); 156 assertSuccess("Spot 4", status); 157 158 NumberStringBuilder nsb3; 159 MicroProps micros3; 160 mod.addToChain(µs3); 161 mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false); 162 mod.processQuantity(fq, micros3, status); 163 micros3.modMiddle->apply(nsb3, 0, 0, status); 164 assertSuccess("Spot 5", status); 165 166 assertTrue(nsb1.toUnicodeString() + " vs " + nsb2.toUnicodeString(), nsb1.contentEquals(nsb2)); 167 assertFalse(nsb1.toUnicodeString() + " vs " + nsb3.toUnicodeString(), nsb1.contentEquals(nsb3)); 168 } 169 170 UnicodeString PatternModifierTest::getPrefix(const MutablePatternModifier &mod, UErrorCode &status) { 171 NumberStringBuilder nsb; 172 mod.apply(nsb, 0, 0, status); 173 int32_t prefixLength = mod.getPrefixLength(); 174 return UnicodeString(nsb.toUnicodeString(), 0, prefixLength); 175 } 176 177 UnicodeString PatternModifierTest::getSuffix(const MutablePatternModifier &mod, UErrorCode &status) { 178 NumberStringBuilder nsb; 179 mod.apply(nsb, 0, 0, status); 180 int32_t prefixLength = mod.getPrefixLength(); 181 return UnicodeString(nsb.toUnicodeString(), prefixLength, nsb.length() - prefixLength); 182 } 183 184 #endif /* #if !UCONFIG_NO_FORMATTING */ 185