]>
Commit | Line | Data |
---|---|---|
340931cb A |
1 | // © 2019 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 <fstream> | |
9 | #include <iostream> | |
10 | #include <vector> | |
11 | ||
12 | #include "numbertest.h" | |
13 | #include "ucbuf.h" | |
14 | #include "unicode/numberformatter.h" | |
15 | ||
16 | void NumberPermutationTest::runIndexedTest(int32_t index, UBool exec, const char*& name, char*) { | |
17 | if (exec) { | |
18 | logln("TestSuite NumberPermutationTest: "); | |
19 | } | |
20 | TESTCASE_AUTO_BEGIN; | |
21 | TESTCASE_AUTO(testPermutations); | |
22 | TESTCASE_AUTO_END; | |
23 | } | |
24 | ||
25 | static const char16_t* kSkeletonParts[] = { | |
26 | // Notation | |
27 | u"compact-short", | |
28 | u"scientific/+ee/sign-always", | |
29 | nullptr, | |
30 | // Unit | |
31 | u"percent", | |
32 | u"currency/EUR", | |
33 | u"measure-unit/length-furlong", | |
34 | nullptr, | |
35 | // Unit Width | |
36 | u"unit-width-narrow", | |
37 | u"unit-width-full-name", | |
38 | nullptr, | |
39 | // Precision | |
40 | u"precision-integer", | |
41 | u".000", | |
42 | u".##/@@@+", | |
43 | u"@@", | |
44 | nullptr, | |
45 | // Rounding Mode | |
46 | u"rounding-mode-floor", | |
47 | nullptr, | |
48 | // Integer Width | |
49 | u"integer-width/##00", | |
50 | nullptr, | |
51 | // Scale | |
52 | u"scale/0.5", | |
53 | nullptr, | |
54 | // Grouping | |
55 | u"group-on-aligned", | |
56 | nullptr, | |
57 | // Symbols | |
58 | u"latin", | |
59 | nullptr, | |
60 | // Sign Display | |
61 | u"sign-accounting-except-zero", | |
62 | nullptr, | |
63 | // Decimal Separator Display | |
64 | u"decimal-always", | |
65 | nullptr, | |
66 | }; | |
67 | ||
68 | static const double kNumbersToTest[]{0, 91827.3645, -0.22222}; | |
69 | ||
70 | /** | |
71 | * Test permutations of 3 orthogonal skeleton parts from the list above. | |
72 | * Compare the results against the golden data file: | |
73 | * numberpermutationtest.txt | |
74 | * To regenerate that file, run intltest with the -G option. | |
75 | */ | |
76 | void NumberPermutationTest::testPermutations() { | |
77 | IcuTestErrorCode status(*this, "testPermutations"); | |
78 | ||
79 | const struct LocaleData { | |
80 | Locale locale; | |
81 | const char16_t* ustring; | |
82 | } localesToTest[] = { | |
83 | {"es-MX", u"es-MX"}, | |
84 | {"zh-TW", u"zh-TW"}, | |
85 | {"bn-BD", u"bn-BD"}, | |
86 | }; | |
87 | ||
88 | // Convert kSkeletonParts to a more convenient data structure | |
89 | auto skeletonParts = std::vector<std::vector<const char16_t*>>(); | |
90 | auto currentSection = std::vector<const char16_t*>(); | |
91 | for (int32_t i = 0; i < UPRV_LENGTHOF(kSkeletonParts); i++) { | |
92 | const char16_t* skeletonPart = kSkeletonParts[i]; | |
93 | if (skeletonPart == nullptr) { | |
94 | skeletonParts.push_back(currentSection); | |
95 | currentSection.clear(); | |
96 | } else { | |
97 | currentSection.push_back(skeletonPart); | |
98 | } | |
99 | } | |
100 | ||
101 | // Build up the golden data string as we evaluate all permutations | |
102 | std::vector<UnicodeString> resultLines; | |
103 | resultLines.push_back(u"# © 2019 and later: Unicode, Inc. and others."); | |
104 | resultLines.push_back(u"# License & terms of use: http://www.unicode.org/copyright.html"); | |
105 | resultLines.push_back(UnicodeString()); | |
106 | ||
107 | // Take combinations of 3 orthogonal options | |
108 | for (size_t i = 0; i < skeletonParts.size() - 2; i++) { | |
109 | const auto& skeletons1 = skeletonParts[i]; | |
110 | for (size_t j = i + 1; j < skeletonParts.size() - 1; j++) { | |
111 | const auto& skeletons2 = skeletonParts[j]; | |
112 | for (size_t k = j + 1; k < skeletonParts.size(); k++) { | |
113 | const auto& skeletons3 = skeletonParts[k]; | |
114 | ||
115 | // Evaluate all combinations of skeletons for these options | |
116 | for (const auto& skel1 : skeletons1) { | |
117 | for (const auto& skel2 : skeletons2) { | |
118 | for (const auto& skel3 : skeletons3) { | |
119 | // Compute the skeleton | |
120 | UnicodeString skeleton; | |
121 | skeleton | |
122 | .append(skel1) // | |
123 | .append(u' ') // | |
124 | .append(skel2) // | |
125 | .append(u' ') // | |
126 | .append(skel3); | |
127 | resultLines.push_back(skeleton); | |
128 | ||
129 | // Check several locales and several numbers in each locale | |
130 | for (const auto& locData : localesToTest) { | |
131 | auto lnf = NumberFormatter::forSkeleton(skeleton, status) | |
132 | .locale(locData.locale); | |
133 | resultLines.push_back(UnicodeString(u" ").append(locData.ustring)); | |
134 | for (const auto& input : kNumbersToTest) { | |
135 | resultLines.push_back(UnicodeString(u" ").append( | |
136 | lnf.formatDouble(input, status).toTempString(status))); | |
137 | } | |
138 | } | |
139 | ||
140 | resultLines.push_back(UnicodeString()); | |
141 | } | |
142 | } | |
143 | } | |
144 | } | |
145 | ||
146 | // Quick mode: test all fields at least once but stop early. | |
147 | if (quick) { | |
148 | infoln(u"Quick mode: stopped after " + Int64ToUnicodeString(resultLines.size()) + | |
149 | u" lines"); | |
150 | goto outerEnd; | |
151 | } | |
152 | } | |
153 | } | |
154 | outerEnd: | |
155 | void(); | |
156 | ||
157 | CharString goldenFilePath(getSourceTestData(status), status); | |
158 | goldenFilePath.appendPathPart("numberpermutationtest.txt", status); | |
159 | ||
160 | // Compare it to the golden file | |
161 | const char* codePage = "UTF-8"; | |
162 | LocalUCHARBUFPointer f(ucbuf_open(goldenFilePath.data(), &codePage, TRUE, FALSE, status)); | |
163 | if (!assertSuccess("Can't open data file", status)) { | |
164 | return; | |
165 | } | |
166 | ||
167 | int32_t lineNumber = 1; | |
168 | int32_t lineLength; | |
169 | for (const auto& actualLine : resultLines) { | |
170 | const UChar* lineBuf = ucbuf_readline(f.getAlias(), &lineLength, status); | |
171 | if (lineBuf == nullptr) { | |
172 | errln("More lines generated than are in the data file!"); | |
173 | break; | |
174 | } | |
175 | UnicodeString expectedLine(lineBuf, lineLength - 1); | |
176 | assertEquals(u"Line #" + Int64ToUnicodeString(lineNumber) + u" differs", // | |
177 | expectedLine, actualLine); | |
178 | lineNumber++; | |
179 | } | |
180 | // Quick mode: test all fields at least once but stop early. | |
181 | if (!quick && ucbuf_readline(f.getAlias(), &lineLength, status) != nullptr) { | |
182 | errln("Fewer lines generated than are in the data file!"); | |
183 | } | |
184 | ||
185 | // Overwrite the golden data if requested | |
186 | if (write_golden_data) { | |
187 | std::ofstream outFile; | |
188 | outFile.open(goldenFilePath.data()); | |
189 | for (const auto& uniLine : resultLines) { | |
190 | std::string byteLine; | |
191 | uniLine.toUTF8String(byteLine); | |
192 | outFile << byteLine << std::endl; | |
193 | } | |
194 | outFile.close(); | |
195 | } | |
196 | } | |
197 | ||
198 | #endif /* #if !UCONFIG_NO_FORMATTING */ |