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
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)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
testBasic()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, kUndefinedField);
30 mod.setPatternAttributes(UNUM_SIGN_AUTO, false, false);
31 DecimalFormatSymbols symbols(Locale::getEnglish(), status);
32 mod.setSymbols(&symbols, {u"USD", status}, UNUM_UNIT_WIDTH_SHORT, nullptr, status);
33 if (!assertSuccess("Spot 2", status, true)) {
34 return;
35 }
36
37 mod.setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
38 assertEquals("Pattern a0b", u"a", getPrefix(mod, status));
39 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
40 mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false, false);
41 assertEquals("Pattern a0b", u"+a", getPrefix(mod, status));
42 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
43 mod.setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT);
44 assertEquals("Pattern a0b", u"-a", getPrefix(mod, status));
45 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
46 mod.setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT);
47 assertEquals("Pattern a0b", u"+a", getPrefix(mod, status));
48 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
49 mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false, false);
50 assertEquals("Pattern a0b", u"a", getPrefix(mod, status));
51 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
52 mod.setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT);
53 assertEquals("Pattern a0b", u"-a", getPrefix(mod, status));
54 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
55 mod.setPatternAttributes(UNUM_SIGN_NEVER, false, false);
56 assertEquals("Pattern a0b", u"a", getPrefix(mod, status));
57 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
58 assertSuccess("Spot 3", status);
59
60 mod.setPatternAttributes(UNUM_SIGN_AUTO, false, true);
61 mod.setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
62 assertEquals("Pattern a0b", u"~a", getPrefix(mod, status));
63 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
64 mod.setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT);
65 assertEquals("Pattern a0b", u"~-a", getPrefix(mod, status));
66 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
67 mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false, true);
68 mod.setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
69 assertEquals("Pattern a0b", u"~+a", getPrefix(mod, status));
70 assertEquals("Pattern a0b", u"b", getSuffix(mod, status));
71 assertSuccess("Spot 3.5", status);
72
73 ParsedPatternInfo patternInfo2;
74 PatternParser::parseToPatternInfo(u"a0b;c-0d", patternInfo2, status);
75 assertSuccess("Spot 4", status);
76 mod.setPatternInfo(&patternInfo2, kUndefinedField);
77 mod.setPatternAttributes(UNUM_SIGN_AUTO, false, false);
78 mod.setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
79 assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status));
80 assertEquals("Pattern a0b;c-0d", u"b", getSuffix(mod, status));
81 mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false, false);
82 assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status));
83 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
84 mod.setNumberProperties(SIGNUM_NEG_ZERO, StandardPlural::Form::COUNT);
85 assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
86 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
87 mod.setNumberProperties(SIGNUM_POS_ZERO, StandardPlural::Form::COUNT);
88 assertEquals("Pattern a0b;c-0d", u"c+", getPrefix(mod, status));
89 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
90 mod.setPatternAttributes(UNUM_SIGN_EXCEPT_ZERO, false, false);
91 assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status));
92 assertEquals("Pattern a0b;c-0d", u"b", getSuffix(mod, status));
93 mod.setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT);
94 assertEquals("Pattern a0b;c-0d", u"c-", getPrefix(mod, status));
95 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
96 mod.setPatternAttributes(UNUM_SIGN_NEVER, false, false);
97 assertEquals("Pattern a0b;c-0d", u"a", getPrefix(mod, status));
98 assertEquals("Pattern a0b;c-0d", u"b", getSuffix(mod, status));
99 assertSuccess("Spot 5", status);
100
101 mod.setPatternAttributes(UNUM_SIGN_AUTO, false, true);
102 mod.setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
103 assertEquals("Pattern a0b;c-0d", u"c~", getPrefix(mod, status));
104 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
105 mod.setNumberProperties(SIGNUM_NEG, StandardPlural::Form::COUNT);
106 assertEquals("Pattern a0b;c-0d", u"c~-", getPrefix(mod, status));
107 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
108 mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false, true);
109 mod.setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
110 assertEquals("Pattern a0b;c-0d", u"c~+", getPrefix(mod, status));
111 assertEquals("Pattern a0b;c-0d", u"d", getSuffix(mod, status));
112 assertSuccess("Spot 5.5", status);
113 }
114
testPatternWithNoPlaceholder()115 void PatternModifierTest::testPatternWithNoPlaceholder() {
116 UErrorCode status = U_ZERO_ERROR;
117 MutablePatternModifier mod(false);
118 ParsedPatternInfo patternInfo;
119 PatternParser::parseToPatternInfo(u"abc", patternInfo, status);
120 assertSuccess("Spot 1", status);
121 mod.setPatternInfo(&patternInfo, kUndefinedField);
122 mod.setPatternAttributes(UNUM_SIGN_AUTO, false, false);
123 DecimalFormatSymbols symbols(Locale::getEnglish(), status);
124 mod.setSymbols(&symbols, {u"USD", status}, UNUM_UNIT_WIDTH_SHORT, nullptr, status);
125 if (!assertSuccess("Spot 2", status, true)) {
126 return;
127 }
128 mod.setNumberProperties(SIGNUM_POS, StandardPlural::Form::COUNT);
129
130 // Unsafe Code Path
131 FormattedStringBuilder nsb;
132 nsb.append(u"x123y", kUndefinedField, status);
133 assertSuccess("Spot 3", status);
134 mod.apply(nsb, 1, 4, status);
135 assertSuccess("Spot 4", status);
136 assertEquals("Unsafe Path", u"xabcy", nsb.toUnicodeString());
137
138 // Safe Code Path
139 nsb.clear();
140 nsb.append(u"x123y", kUndefinedField, status);
141 assertSuccess("Spot 5", status);
142 MicroProps micros;
143 LocalPointer<ImmutablePatternModifier> imod(mod.createImmutable(status), status);
144 if (U_FAILURE(status)) {
145 dataerrln("%s %d Error in ImmutablePatternModifier creation",
146 __FILE__, __LINE__);
147 assertSuccess("Spot 6", status);
148 return;
149 }
150 DecimalQuantity quantity;
151 imod->applyToMicros(micros, quantity, status);
152 micros.modMiddle->apply(nsb, 1, 4, status);
153 assertSuccess("Spot 7", status);
154 assertEquals("Safe Path", u"xabcy", nsb.toUnicodeString());
155 }
156
testMutableEqualsImmutable()157 void PatternModifierTest::testMutableEqualsImmutable() {
158 UErrorCode status = U_ZERO_ERROR;
159 MutablePatternModifier mod(false);
160 ParsedPatternInfo patternInfo;
161 PatternParser::parseToPatternInfo("a0b;c-0d", patternInfo, status);
162 assertSuccess("Spot 1", status);
163 mod.setPatternInfo(&patternInfo, kUndefinedField);
164 mod.setPatternAttributes(UNUM_SIGN_AUTO, false, false);
165 DecimalFormatSymbols symbols(Locale::getEnglish(), status);
166 mod.setSymbols(&symbols, {u"USD", status}, UNUM_UNIT_WIDTH_SHORT, nullptr, status);
167 assertSuccess("Spot 2", status);
168 if (U_FAILURE(status)) { return; }
169 DecimalQuantity fq;
170 fq.setToInt(1);
171
172 FormattedStringBuilder nsb1;
173 MicroProps micros1;
174 mod.addToChain(µs1);
175 mod.processQuantity(fq, micros1, status);
176 micros1.modMiddle->apply(nsb1, 0, 0, status);
177 assertSuccess("Spot 3", status);
178
179 FormattedStringBuilder nsb2;
180 MicroProps micros2;
181 LocalPointer<ImmutablePatternModifier> immutable(mod.createImmutable(status));
182 immutable->applyToMicros(micros2, fq, status);
183 micros2.modMiddle->apply(nsb2, 0, 0, status);
184 assertSuccess("Spot 4", status);
185
186 FormattedStringBuilder nsb3;
187 MicroProps micros3;
188 mod.addToChain(µs3);
189 mod.setPatternAttributes(UNUM_SIGN_ALWAYS, false, false);
190 mod.processQuantity(fq, micros3, status);
191 micros3.modMiddle->apply(nsb3, 0, 0, status);
192 assertSuccess("Spot 5", status);
193
194 assertTrue(nsb1.toUnicodeString() + " vs " + nsb2.toUnicodeString(), nsb1.contentEquals(nsb2));
195 assertFalse(nsb1.toUnicodeString() + " vs " + nsb3.toUnicodeString(), nsb1.contentEquals(nsb3));
196 }
197
getPrefix(const MutablePatternModifier & mod,UErrorCode & status)198 UnicodeString PatternModifierTest::getPrefix(const MutablePatternModifier &mod, UErrorCode &status) {
199 FormattedStringBuilder nsb;
200 mod.apply(nsb, 0, 0, status);
201 int32_t prefixLength = mod.getPrefixLength();
202 return UnicodeString(nsb.toUnicodeString(), 0, prefixLength);
203 }
204
getSuffix(const MutablePatternModifier & mod,UErrorCode & status)205 UnicodeString PatternModifierTest::getSuffix(const MutablePatternModifier &mod, UErrorCode &status) {
206 FormattedStringBuilder nsb;
207 mod.apply(nsb, 0, 0, status);
208 int32_t prefixLength = mod.getPrefixLength();
209 return UnicodeString(nsb.toUnicodeString(), prefixLength, nsb.length() - prefixLength);
210 }
211
212 #endif /* #if !UCONFIG_NO_FORMATTING */
213