]>
Commit | Line | Data |
---|---|---|
2ca993e8 A |
1 | /******************************************************************** |
2 | * COPYRIGHT: | |
3 | * Copyright (c) 2015, International Business Machines Corporation and | |
4 | * others. All Rights Reserved. | |
5 | ********************************************************************/ | |
6 | ||
7 | #include "datadrivennumberformattestsuite.h" | |
8 | ||
9 | #if !UCONFIG_NO_FORMATTING | |
10 | ||
11 | #include "charstr.h" | |
12 | #include "ucbuf.h" | |
13 | #include "unicode/localpointer.h" | |
14 | #include "ustrfmt.h" | |
15 | ||
16 | static UBool isCROrLF(UChar c) { return c == 0xa || c == 0xd; } | |
17 | static UBool isSpace(UChar c) { return c == 9 || c == 0x20 || c == 0x3000; } | |
18 | ||
19 | void DataDrivenNumberFormatTestSuite::run(const char *fileName, UBool runAllTests) { | |
20 | fFileLineNumber = 0; | |
21 | fFormatTestNumber = 0; | |
22 | UErrorCode status = U_ZERO_ERROR; | |
23 | for (int32_t i = 0; i < UPRV_LENGTHOF(fPreviousFormatters); ++i) { | |
24 | delete fPreviousFormatters[i]; | |
25 | fPreviousFormatters[i] = newFormatter(status); | |
26 | } | |
27 | if (!assertSuccess("Can't create previous formatters", status)) { | |
28 | return; | |
29 | } | |
30 | CharString path(getSourceTestData(status), status); | |
31 | path.appendPathPart(fileName, status); | |
32 | const char *codePage = "UTF-8"; | |
33 | LocalUCHARBUFPointer f(ucbuf_open(path.data(), &codePage, TRUE, FALSE, &status)); | |
34 | if (!assertSuccess("Can't open data file", status)) { | |
35 | return; | |
36 | } | |
37 | UnicodeString columnValues[kNumberFormatTestTupleFieldCount]; | |
38 | ENumberFormatTestTupleField columnTypes[kNumberFormatTestTupleFieldCount]; | |
39 | int32_t columnCount; | |
40 | int32_t state = 0; | |
41 | while(U_SUCCESS(status)) { | |
42 | // Read a new line if necessary. | |
43 | if(fFileLine.isEmpty()) { | |
44 | if(!readLine(f.getAlias(), status)) { break; } | |
45 | if (fFileLine.isEmpty() && state == 2) { | |
46 | state = 0; | |
47 | } | |
48 | continue; | |
49 | } | |
50 | if (fFileLine.startsWith("//")) { | |
51 | fFileLine.remove(); | |
52 | continue; | |
53 | } | |
54 | // Initial setup of test. | |
55 | if (state == 0) { | |
56 | if (fFileLine.startsWith(UNICODE_STRING("test ", 5))) { | |
57 | fFileTestName = fFileLine; | |
58 | fTuple.clear(); | |
59 | } else if(fFileLine.startsWith(UNICODE_STRING("set ", 4))) { | |
60 | setTupleField(status); | |
61 | } else if(fFileLine.startsWith(UNICODE_STRING("begin", 5))) { | |
62 | state = 1; | |
63 | } else { | |
64 | showError("Unrecognized verb."); | |
65 | return; | |
66 | } | |
67 | // column specification | |
68 | } else if (state == 1) { | |
69 | columnCount = splitBy(columnValues, UPRV_LENGTHOF(columnValues), 0x9); | |
70 | for (int32_t i = 0; i < columnCount; ++i) { | |
71 | columnTypes[i] = NumberFormatTestTuple::getFieldByName( | |
72 | columnValues[i]); | |
73 | if (columnTypes[i] == kNumberFormatTestTupleFieldCount) { | |
74 | showError("Unrecognized field name."); | |
75 | return; | |
76 | } | |
77 | } | |
78 | state = 2; | |
79 | // run the tests | |
80 | } else { | |
81 | int32_t columnsInThisRow = splitBy(columnValues, columnCount, 0x9); | |
82 | for (int32_t i = 0; i < columnsInThisRow; ++i) { | |
83 | fTuple.setField( | |
84 | columnTypes[i], columnValues[i].unescape(), status); | |
85 | } | |
86 | for (int32_t i = columnsInThisRow; i < columnCount; ++i) { | |
87 | fTuple.clearField(columnTypes[i], status); | |
88 | } | |
89 | if (U_FAILURE(status)) { | |
90 | showError("Invalid column values"); | |
91 | return; | |
92 | } | |
93 | if (!breaksC() || runAllTests) { | |
94 | UnicodeString errorMessage; | |
95 | if (!isPass(fTuple, errorMessage, status)) { | |
96 | showFailure(errorMessage); | |
97 | } | |
98 | } | |
99 | } | |
100 | fFileLine.remove(); | |
101 | } | |
102 | } | |
103 | ||
104 | DataDrivenNumberFormatTestSuite::~DataDrivenNumberFormatTestSuite() { | |
105 | for (int32_t i = 0; i < UPRV_LENGTHOF(fPreviousFormatters); ++i) { | |
106 | delete fPreviousFormatters[i]; | |
107 | } | |
108 | } | |
109 | ||
110 | UBool DataDrivenNumberFormatTestSuite::breaksC() { | |
111 | return (NFTT_GET_FIELD(fTuple, breaks, "").toUpper().indexOf(0x43) != -1); | |
112 | } | |
113 | ||
114 | void DataDrivenNumberFormatTestSuite::setTupleField(UErrorCode &status) { | |
115 | if (U_FAILURE(status)) { | |
116 | return; | |
117 | } | |
118 | UnicodeString parts[3]; | |
119 | int32_t partCount = splitBy(parts, UPRV_LENGTHOF(parts), 0x20); | |
120 | if (partCount < 3) { | |
121 | showError("Set expects 2 parameters"); | |
122 | status = U_PARSE_ERROR; | |
123 | return; | |
124 | } | |
125 | if (!fTuple.setField( | |
126 | NumberFormatTestTuple::getFieldByName(parts[1]), | |
127 | parts[2].unescape(), | |
128 | status)) { | |
129 | showError("Invalid field value"); | |
130 | } | |
131 | } | |
132 | ||
133 | ||
134 | int32_t | |
135 | DataDrivenNumberFormatTestSuite::splitBy( | |
136 | UnicodeString *columnValues, | |
137 | int32_t columnValuesCount, | |
138 | UChar delimiter) { | |
139 | int32_t colIdx = 0; | |
140 | int32_t colStart = 0; | |
141 | int32_t len = fFileLine.length(); | |
142 | for (int32_t idx = 0; colIdx < columnValuesCount - 1 && idx < len; ++idx) { | |
143 | UChar ch = fFileLine.charAt(idx); | |
144 | if (ch == delimiter) { | |
145 | columnValues[colIdx++] = | |
146 | fFileLine.tempSubString(colStart, idx - colStart); | |
147 | colStart = idx + 1; | |
148 | } | |
149 | } | |
150 | columnValues[colIdx++] = | |
151 | fFileLine.tempSubString(colStart, len - colStart); | |
152 | return colIdx; | |
153 | } | |
154 | ||
155 | void DataDrivenNumberFormatTestSuite::showLineInfo() { | |
156 | UnicodeString indent(" "); | |
157 | infoln(indent + fFileTestName); | |
158 | infoln(indent + fFileLine); | |
159 | } | |
160 | ||
161 | void DataDrivenNumberFormatTestSuite::showError(const char *message) { | |
162 | errln("line %d: %s", (int) fFileLineNumber, message); | |
163 | showLineInfo(); | |
164 | } | |
165 | ||
166 | void DataDrivenNumberFormatTestSuite::showFailure(const UnicodeString &message) { | |
167 | UChar lineStr[20]; | |
168 | uprv_itou( | |
169 | lineStr, UPRV_LENGTHOF(lineStr), (uint32_t) fFileLineNumber, 10, 1); | |
170 | UnicodeString fullMessage("line "); | |
171 | dataerrln(fullMessage.append(lineStr).append(": ") | |
172 | .append(prettify(message))); | |
173 | showLineInfo(); | |
174 | } | |
175 | ||
176 | UBool DataDrivenNumberFormatTestSuite::readLine( | |
177 | UCHARBUF *f, UErrorCode &status) { | |
178 | int32_t lineLength; | |
179 | const UChar *line = ucbuf_readline(f, &lineLength, &status); | |
180 | if(line == NULL || U_FAILURE(status)) { | |
181 | if (U_FAILURE(status)) { | |
182 | errln("Error reading line from file."); | |
183 | } | |
184 | fFileLine.remove(); | |
185 | return FALSE; | |
186 | } | |
187 | ++fFileLineNumber; | |
188 | // Strip trailing CR/LF, comments, and spaces. | |
189 | while(lineLength > 0 && isCROrLF(line[lineLength - 1])) { --lineLength; } | |
190 | fFileLine.setTo(FALSE, line, lineLength); | |
191 | while(lineLength > 0 && isSpace(line[lineLength - 1])) { --lineLength; } | |
192 | if (lineLength == 0) { | |
193 | fFileLine.remove(); | |
194 | } | |
195 | return TRUE; | |
196 | } | |
197 | ||
198 | UBool DataDrivenNumberFormatTestSuite::isPass( | |
199 | const NumberFormatTestTuple &tuple, | |
200 | UnicodeString &appendErrorMessage, | |
201 | UErrorCode &status) { | |
202 | if (U_FAILURE(status)) { | |
203 | return FALSE; | |
204 | } | |
205 | UBool result = FALSE; | |
206 | if (tuple.formatFlag && tuple.outputFlag) { | |
207 | ++fFormatTestNumber; | |
208 | result = isFormatPass( | |
209 | tuple, | |
210 | fPreviousFormatters[ | |
211 | fFormatTestNumber % UPRV_LENGTHOF(fPreviousFormatters)], | |
212 | appendErrorMessage, | |
213 | status); | |
214 | } | |
215 | else if (tuple.toPatternFlag || tuple.toLocalizedPatternFlag) { | |
216 | result = isToPatternPass(tuple, appendErrorMessage, status); | |
217 | } else if (tuple.parseFlag && tuple.outputFlag && tuple.outputCurrencyFlag) { | |
218 | result = isParseCurrencyPass(tuple, appendErrorMessage, status); | |
219 | ||
220 | } else if (tuple.parseFlag && tuple.outputFlag) { | |
221 | result = isParsePass(tuple, appendErrorMessage, status); | |
222 | } else if (tuple.pluralFlag) { | |
223 | result = isSelectPass(tuple, appendErrorMessage, status); | |
224 | } else { | |
225 | appendErrorMessage.append("Unrecognized test type."); | |
226 | status = U_ILLEGAL_ARGUMENT_ERROR; | |
227 | } | |
228 | if (!result) { | |
229 | if (appendErrorMessage.length() > 0) { | |
230 | appendErrorMessage.append(": "); | |
231 | } | |
232 | if (U_FAILURE(status)) { | |
233 | appendErrorMessage.append(u_errorName(status)); | |
234 | appendErrorMessage.append(": "); | |
235 | } | |
236 | tuple.toString(appendErrorMessage); | |
237 | } | |
238 | return result; | |
239 | } | |
240 | ||
241 | UBool DataDrivenNumberFormatTestSuite::isFormatPass( | |
242 | const NumberFormatTestTuple & /* tuple */, | |
243 | UnicodeString & /*appendErrorMessage*/, | |
244 | UErrorCode &status) { | |
245 | if (U_FAILURE(status)) { | |
246 | return FALSE; | |
247 | } | |
248 | return TRUE; | |
249 | } | |
250 | ||
251 | UBool DataDrivenNumberFormatTestSuite::isFormatPass( | |
252 | const NumberFormatTestTuple &tuple, | |
253 | UObject * /* somePreviousFormatter */, | |
254 | UnicodeString &appendErrorMessage, | |
255 | UErrorCode &status) { | |
256 | return isFormatPass(tuple, appendErrorMessage, status); | |
257 | } | |
258 | ||
259 | UObject *DataDrivenNumberFormatTestSuite::newFormatter( | |
260 | UErrorCode & /*status*/) { | |
261 | return NULL; | |
262 | } | |
263 | ||
264 | UBool DataDrivenNumberFormatTestSuite::isToPatternPass( | |
265 | const NumberFormatTestTuple & /* tuple */, | |
266 | UnicodeString & /*appendErrorMessage*/, | |
267 | UErrorCode &status) { | |
268 | if (U_FAILURE(status)) { | |
269 | return FALSE; | |
270 | } | |
271 | return TRUE; | |
272 | } | |
273 | ||
274 | UBool DataDrivenNumberFormatTestSuite::isParsePass( | |
275 | const NumberFormatTestTuple & /* tuple */, | |
276 | UnicodeString & /*appendErrorMessage*/, | |
277 | UErrorCode &status) { | |
278 | if (U_FAILURE(status)) { | |
279 | return FALSE; | |
280 | } | |
281 | return TRUE; | |
282 | } | |
283 | ||
284 | UBool DataDrivenNumberFormatTestSuite::isParseCurrencyPass( | |
285 | const NumberFormatTestTuple & /* tuple */, | |
286 | UnicodeString & /*appendErrorMessage*/, | |
287 | UErrorCode &status) { | |
288 | if (U_FAILURE(status)) { | |
289 | return FALSE; | |
290 | } | |
291 | return TRUE; | |
292 | } | |
293 | ||
294 | UBool DataDrivenNumberFormatTestSuite::isSelectPass( | |
295 | const NumberFormatTestTuple & /* tuple */, | |
296 | UnicodeString & /*appendErrorMessage*/, | |
297 | UErrorCode &status) { | |
298 | if (U_FAILURE(status)) { | |
299 | return FALSE; | |
300 | } | |
301 | return TRUE; | |
302 | } | |
303 | #endif /* !UCONFIG_NO_FORMATTING */ |