Index: source/test/intltest/datadrivennumberformattestsuite.cpp |
diff --git a/source/test/intltest/datadrivennumberformattestsuite.cpp b/source/test/intltest/datadrivennumberformattestsuite.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..d3c650c24700d4000ebbac5f49c62614f0a4b796 |
--- /dev/null |
+++ b/source/test/intltest/datadrivennumberformattestsuite.cpp |
@@ -0,0 +1,303 @@ |
+/******************************************************************** |
+ * COPYRIGHT: |
+ * Copyright (c) 2015, International Business Machines Corporation and |
+ * others. All Rights Reserved. |
+ ********************************************************************/ |
+ |
+#include "datadrivennumberformattestsuite.h" |
+ |
+#if !UCONFIG_NO_FORMATTING |
+ |
+#include "charstr.h" |
+#include "ucbuf.h" |
+#include "unicode/localpointer.h" |
+#include "ustrfmt.h" |
+ |
+static UBool isCROrLF(UChar c) { return c == 0xa || c == 0xd; } |
+static UBool isSpace(UChar c) { return c == 9 || c == 0x20 || c == 0x3000; } |
+ |
+void DataDrivenNumberFormatTestSuite::run(const char *fileName, UBool runAllTests) { |
+ fFileLineNumber = 0; |
+ fFormatTestNumber = 0; |
+ UErrorCode status = U_ZERO_ERROR; |
+ for (int32_t i = 0; i < UPRV_LENGTHOF(fPreviousFormatters); ++i) { |
+ delete fPreviousFormatters[i]; |
+ fPreviousFormatters[i] = newFormatter(status); |
+ } |
+ if (!assertSuccess("Can't create previous formatters", status)) { |
+ return; |
+ } |
+ CharString path(getSourceTestData(status), status); |
+ path.appendPathPart(fileName, status); |
+ const char *codePage = "UTF-8"; |
+ LocalUCHARBUFPointer f(ucbuf_open(path.data(), &codePage, TRUE, FALSE, &status)); |
+ if (!assertSuccess("Can't open data file", status)) { |
+ return; |
+ } |
+ UnicodeString columnValues[kNumberFormatTestTupleFieldCount]; |
+ ENumberFormatTestTupleField columnTypes[kNumberFormatTestTupleFieldCount]; |
+ int32_t columnCount; |
+ int32_t state = 0; |
+ while(U_SUCCESS(status)) { |
+ // Read a new line if necessary. |
+ if(fFileLine.isEmpty()) { |
+ if(!readLine(f.getAlias(), status)) { break; } |
+ if (fFileLine.isEmpty() && state == 2) { |
+ state = 0; |
+ } |
+ continue; |
+ } |
+ if (fFileLine.startsWith("//")) { |
+ fFileLine.remove(); |
+ continue; |
+ } |
+ // Initial setup of test. |
+ if (state == 0) { |
+ if (fFileLine.startsWith(UNICODE_STRING("test ", 5))) { |
+ fFileTestName = fFileLine; |
+ fTuple.clear(); |
+ } else if(fFileLine.startsWith(UNICODE_STRING("set ", 4))) { |
+ setTupleField(status); |
+ } else if(fFileLine.startsWith(UNICODE_STRING("begin", 5))) { |
+ state = 1; |
+ } else { |
+ showError("Unrecognized verb."); |
+ return; |
+ } |
+ // column specification |
+ } else if (state == 1) { |
+ columnCount = splitBy(columnValues, UPRV_LENGTHOF(columnValues), 0x9); |
+ for (int32_t i = 0; i < columnCount; ++i) { |
+ columnTypes[i] = NumberFormatTestTuple::getFieldByName( |
+ columnValues[i]); |
+ if (columnTypes[i] == kNumberFormatTestTupleFieldCount) { |
+ showError("Unrecognized field name."); |
+ return; |
+ } |
+ } |
+ state = 2; |
+ // run the tests |
+ } else { |
+ int32_t columnsInThisRow = splitBy(columnValues, columnCount, 0x9); |
+ for (int32_t i = 0; i < columnsInThisRow; ++i) { |
+ fTuple.setField( |
+ columnTypes[i], columnValues[i].unescape(), status); |
+ } |
+ for (int32_t i = columnsInThisRow; i < columnCount; ++i) { |
+ fTuple.clearField(columnTypes[i], status); |
+ } |
+ if (U_FAILURE(status)) { |
+ showError("Invalid column values"); |
+ return; |
+ } |
+ if (!breaksC() || runAllTests) { |
+ UnicodeString errorMessage; |
+ if (!isPass(fTuple, errorMessage, status)) { |
+ showFailure(errorMessage); |
+ } |
+ } |
+ } |
+ fFileLine.remove(); |
+ } |
+} |
+ |
+DataDrivenNumberFormatTestSuite::~DataDrivenNumberFormatTestSuite() { |
+ for (int32_t i = 0; i < UPRV_LENGTHOF(fPreviousFormatters); ++i) { |
+ delete fPreviousFormatters[i]; |
+ } |
+} |
+ |
+UBool DataDrivenNumberFormatTestSuite::breaksC() { |
+ return (NFTT_GET_FIELD(fTuple, breaks, "").toUpper().indexOf(0x43) != -1); |
+} |
+ |
+void DataDrivenNumberFormatTestSuite::setTupleField(UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ UnicodeString parts[3]; |
+ int32_t partCount = splitBy(parts, UPRV_LENGTHOF(parts), 0x20); |
+ if (partCount < 3) { |
+ showError("Set expects 2 parameters"); |
+ status = U_PARSE_ERROR; |
+ return; |
+ } |
+ if (!fTuple.setField( |
+ NumberFormatTestTuple::getFieldByName(parts[1]), |
+ parts[2].unescape(), |
+ status)) { |
+ showError("Invalid field value"); |
+ } |
+} |
+ |
+ |
+int32_t |
+DataDrivenNumberFormatTestSuite::splitBy( |
+ UnicodeString *columnValues, |
+ int32_t columnValuesCount, |
+ UChar delimiter) { |
+ int32_t colIdx = 0; |
+ int32_t colStart = 0; |
+ int32_t len = fFileLine.length(); |
+ for (int32_t idx = 0; colIdx < columnValuesCount - 1 && idx < len; ++idx) { |
+ UChar ch = fFileLine.charAt(idx); |
+ if (ch == delimiter) { |
+ columnValues[colIdx++] = |
+ fFileLine.tempSubString(colStart, idx - colStart); |
+ colStart = idx + 1; |
+ } |
+ } |
+ columnValues[colIdx++] = |
+ fFileLine.tempSubString(colStart, len - colStart); |
+ return colIdx; |
+} |
+ |
+void DataDrivenNumberFormatTestSuite::showLineInfo() { |
+ UnicodeString indent(" "); |
+ infoln(indent + fFileTestName); |
+ infoln(indent + fFileLine); |
+} |
+ |
+void DataDrivenNumberFormatTestSuite::showError(const char *message) { |
+ errln("line %d: %s", (int) fFileLineNumber, message); |
+ showLineInfo(); |
+} |
+ |
+void DataDrivenNumberFormatTestSuite::showFailure(const UnicodeString &message) { |
+ UChar lineStr[20]; |
+ uprv_itou( |
+ lineStr, UPRV_LENGTHOF(lineStr), (uint32_t) fFileLineNumber, 10, 1); |
+ UnicodeString fullMessage("line "); |
+ dataerrln(fullMessage.append(lineStr).append(": ") |
+ .append(prettify(message))); |
+ showLineInfo(); |
+} |
+ |
+UBool DataDrivenNumberFormatTestSuite::readLine( |
+ UCHARBUF *f, UErrorCode &status) { |
+ int32_t lineLength; |
+ const UChar *line = ucbuf_readline(f, &lineLength, &status); |
+ if(line == NULL || U_FAILURE(status)) { |
+ if (U_FAILURE(status)) { |
+ errln("Error reading line from file."); |
+ } |
+ fFileLine.remove(); |
+ return FALSE; |
+ } |
+ ++fFileLineNumber; |
+ // Strip trailing CR/LF, comments, and spaces. |
+ while(lineLength > 0 && isCROrLF(line[lineLength - 1])) { --lineLength; } |
+ fFileLine.setTo(FALSE, line, lineLength); |
+ while(lineLength > 0 && isSpace(line[lineLength - 1])) { --lineLength; } |
+ if (lineLength == 0) { |
+ fFileLine.remove(); |
+ } |
+ return TRUE; |
+} |
+ |
+UBool DataDrivenNumberFormatTestSuite::isPass( |
+ const NumberFormatTestTuple &tuple, |
+ UnicodeString &appendErrorMessage, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ UBool result = FALSE; |
+ if (tuple.formatFlag && tuple.outputFlag) { |
+ ++fFormatTestNumber; |
+ result = isFormatPass( |
+ tuple, |
+ fPreviousFormatters[ |
+ fFormatTestNumber % UPRV_LENGTHOF(fPreviousFormatters)], |
+ appendErrorMessage, |
+ status); |
+ } |
+ else if (tuple.toPatternFlag || tuple.toLocalizedPatternFlag) { |
+ result = isToPatternPass(tuple, appendErrorMessage, status); |
+ } else if (tuple.parseFlag && tuple.outputFlag && tuple.outputCurrencyFlag) { |
+ result = isParseCurrencyPass(tuple, appendErrorMessage, status); |
+ |
+ } else if (tuple.parseFlag && tuple.outputFlag) { |
+ result = isParsePass(tuple, appendErrorMessage, status); |
+ } else if (tuple.pluralFlag) { |
+ result = isSelectPass(tuple, appendErrorMessage, status); |
+ } else { |
+ appendErrorMessage.append("Unrecognized test type."); |
+ status = U_ILLEGAL_ARGUMENT_ERROR; |
+ } |
+ if (!result) { |
+ if (appendErrorMessage.length() > 0) { |
+ appendErrorMessage.append(": "); |
+ } |
+ if (U_FAILURE(status)) { |
+ appendErrorMessage.append(u_errorName(status)); |
+ appendErrorMessage.append(": "); |
+ } |
+ tuple.toString(appendErrorMessage); |
+ } |
+ return result; |
+} |
+ |
+UBool DataDrivenNumberFormatTestSuite::isFormatPass( |
+ const NumberFormatTestTuple & /* tuple */, |
+ UnicodeString & /*appendErrorMessage*/, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ return TRUE; |
+} |
+ |
+UBool DataDrivenNumberFormatTestSuite::isFormatPass( |
+ const NumberFormatTestTuple &tuple, |
+ UObject * /* somePreviousFormatter */, |
+ UnicodeString &appendErrorMessage, |
+ UErrorCode &status) { |
+ return isFormatPass(tuple, appendErrorMessage, status); |
+} |
+ |
+UObject *DataDrivenNumberFormatTestSuite::newFormatter( |
+ UErrorCode & /*status*/) { |
+ return NULL; |
+} |
+ |
+UBool DataDrivenNumberFormatTestSuite::isToPatternPass( |
+ const NumberFormatTestTuple & /* tuple */, |
+ UnicodeString & /*appendErrorMessage*/, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ return TRUE; |
+} |
+ |
+UBool DataDrivenNumberFormatTestSuite::isParsePass( |
+ const NumberFormatTestTuple & /* tuple */, |
+ UnicodeString & /*appendErrorMessage*/, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ return TRUE; |
+} |
+ |
+UBool DataDrivenNumberFormatTestSuite::isParseCurrencyPass( |
+ const NumberFormatTestTuple & /* tuple */, |
+ UnicodeString & /*appendErrorMessage*/, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ return TRUE; |
+} |
+ |
+UBool DataDrivenNumberFormatTestSuite::isSelectPass( |
+ const NumberFormatTestTuple & /* tuple */, |
+ UnicodeString & /*appendErrorMessage*/, |
+ UErrorCode &status) { |
+ if (U_FAILURE(status)) { |
+ return FALSE; |
+ } |
+ return TRUE; |
+} |
+#endif /* !UCONFIG_NO_FORMATTING */ |