OLD | NEW |
| (Empty) |
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 runAllTest
s) { | |
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, &stat
us)); | |
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 */ | |
OLD | NEW |