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 |