1 /********************************************************************
3 * Copyright (c) 2015, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
7 #include "datadrivennumberformattestsuite.h"
9 #if !UCONFIG_NO_FORMATTING
13 #include "unicode/localpointer.h"
16 static UBool
isCROrLF(UChar c
) { return c
== 0xa || c
== 0xd; }
17 static UBool
isSpace(UChar c
) { return c
== 9 || c
== 0x20 || c
== 0x3000; }
19 void DataDrivenNumberFormatTestSuite::run(const char *fileName
, UBool runAllTests
) {
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
);
27 if (!assertSuccess("Can't create previous formatters", status
)) {
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
)) {
37 UnicodeString columnValues
[kNumberFormatTestTupleFieldCount
];
38 ENumberFormatTestTupleField columnTypes
[kNumberFormatTestTupleFieldCount
];
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) {
50 if (fFileLine
.startsWith("//")) {
54 // Initial setup of test.
56 if (fFileLine
.startsWith(UNICODE_STRING("test ", 5))) {
57 fFileTestName
= fFileLine
;
59 } else if(fFileLine
.startsWith(UNICODE_STRING("set ", 4))) {
60 setTupleField(status
);
61 } else if(fFileLine
.startsWith(UNICODE_STRING("begin", 5))) {
64 showError("Unrecognized verb.");
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(
73 if (columnTypes
[i
] == kNumberFormatTestTupleFieldCount
) {
74 showError("Unrecognized field name.");
81 int32_t columnsInThisRow
= splitBy(columnValues
, columnCount
, 0x9);
82 for (int32_t i
= 0; i
< columnsInThisRow
; ++i
) {
84 columnTypes
[i
], columnValues
[i
].unescape(), status
);
86 for (int32_t i
= columnsInThisRow
; i
< columnCount
; ++i
) {
87 fTuple
.clearField(columnTypes
[i
], status
);
89 if (U_FAILURE(status
)) {
90 showError("Invalid column values");
93 if (!breaksC() || runAllTests
) {
94 UnicodeString errorMessage
;
95 if (!isPass(fTuple
, errorMessage
, status
)) {
96 showFailure(errorMessage
);
104 DataDrivenNumberFormatTestSuite::~DataDrivenNumberFormatTestSuite() {
105 for (int32_t i
= 0; i
< UPRV_LENGTHOF(fPreviousFormatters
); ++i
) {
106 delete fPreviousFormatters
[i
];
110 UBool
DataDrivenNumberFormatTestSuite::breaksC() {
111 return (NFTT_GET_FIELD(fTuple
, breaks
, "").toUpper().indexOf(0x43) != -1);
114 void DataDrivenNumberFormatTestSuite::setTupleField(UErrorCode
&status
) {
115 if (U_FAILURE(status
)) {
118 UnicodeString parts
[3];
119 int32_t partCount
= splitBy(parts
, UPRV_LENGTHOF(parts
), 0x20);
121 showError("Set expects 2 parameters");
122 status
= U_PARSE_ERROR
;
125 if (!fTuple
.setField(
126 NumberFormatTestTuple::getFieldByName(parts
[1]),
129 showError("Invalid field value");
135 DataDrivenNumberFormatTestSuite::splitBy(
136 UnicodeString
*columnValues
,
137 int32_t columnValuesCount
,
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
);
150 columnValues
[colIdx
++] =
151 fFileLine
.tempSubString(colStart
, len
- colStart
);
155 void DataDrivenNumberFormatTestSuite::showLineInfo() {
156 UnicodeString
indent(" ");
157 infoln(indent
+ fFileTestName
);
158 infoln(indent
+ fFileLine
);
161 void DataDrivenNumberFormatTestSuite::showError(const char *message
) {
162 errln("line %d: %s", (int) fFileLineNumber
, message
);
166 void DataDrivenNumberFormatTestSuite::showFailure(const UnicodeString
&message
) {
169 lineStr
, UPRV_LENGTHOF(lineStr
), (uint32_t) fFileLineNumber
, 10, 1);
170 UnicodeString
fullMessage("line ");
171 dataerrln(fullMessage
.append(lineStr
).append(": ")
172 .append(prettify(message
)));
176 UBool
DataDrivenNumberFormatTestSuite::readLine(
177 UCHARBUF
*f
, UErrorCode
&status
) {
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.");
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) {
198 UBool
DataDrivenNumberFormatTestSuite::isPass(
199 const NumberFormatTestTuple
&tuple
,
200 UnicodeString
&appendErrorMessage
,
201 UErrorCode
&status
) {
202 if (U_FAILURE(status
)) {
205 UBool result
= FALSE
;
206 if (tuple
.formatFlag
&& tuple
.outputFlag
) {
208 result
= isFormatPass(
211 fFormatTestNumber
% UPRV_LENGTHOF(fPreviousFormatters
)],
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
);
220 } else if (tuple
.parseFlag
&& tuple
.outputFlag
) {
221 result
= isParsePass(tuple
, appendErrorMessage
, status
);
222 } else if (tuple
.pluralFlag
) {
223 result
= isSelectPass(tuple
, appendErrorMessage
, status
);
225 appendErrorMessage
.append("Unrecognized test type.");
226 status
= U_ILLEGAL_ARGUMENT_ERROR
;
229 if (appendErrorMessage
.length() > 0) {
230 appendErrorMessage
.append(": ");
232 if (U_FAILURE(status
)) {
233 appendErrorMessage
.append(u_errorName(status
));
234 appendErrorMessage
.append(": ");
236 tuple
.toString(appendErrorMessage
);
241 UBool
DataDrivenNumberFormatTestSuite::isFormatPass(
242 const NumberFormatTestTuple
& /* tuple */,
243 UnicodeString
& /*appendErrorMessage*/,
244 UErrorCode
&status
) {
245 if (U_FAILURE(status
)) {
251 UBool
DataDrivenNumberFormatTestSuite::isFormatPass(
252 const NumberFormatTestTuple
&tuple
,
253 UObject
* /* somePreviousFormatter */,
254 UnicodeString
&appendErrorMessage
,
255 UErrorCode
&status
) {
256 return isFormatPass(tuple
, appendErrorMessage
, status
);
259 UObject
*DataDrivenNumberFormatTestSuite::newFormatter(
260 UErrorCode
& /*status*/) {
264 UBool
DataDrivenNumberFormatTestSuite::isToPatternPass(
265 const NumberFormatTestTuple
& /* tuple */,
266 UnicodeString
& /*appendErrorMessage*/,
267 UErrorCode
&status
) {
268 if (U_FAILURE(status
)) {
274 UBool
DataDrivenNumberFormatTestSuite::isParsePass(
275 const NumberFormatTestTuple
& /* tuple */,
276 UnicodeString
& /*appendErrorMessage*/,
277 UErrorCode
&status
) {
278 if (U_FAILURE(status
)) {
284 UBool
DataDrivenNumberFormatTestSuite::isParseCurrencyPass(
285 const NumberFormatTestTuple
& /* tuple */,
286 UnicodeString
& /*appendErrorMessage*/,
287 UErrorCode
&status
) {
288 if (U_FAILURE(status
)) {
294 UBool
DataDrivenNumberFormatTestSuite::isSelectPass(
295 const NumberFormatTestTuple
& /* tuple */,
296 UnicodeString
& /*appendErrorMessage*/,
297 UErrorCode
&status
) {
298 if (U_FAILURE(status
)) {
303 #endif /* !UCONFIG_NO_FORMATTING */