| 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 |