From c8d1960895728daa00bf93bb75a857f6cd410a38 Mon Sep 17 00:00:00 2001 From: Hugo van der Merwe <17109322+hugovdm@users.noreply.github.com> Date: Thu, 12 Mar 2020 18:36:27 +0100 Subject: [PATCH] Clone parsePreferencesTests from u_parseDelimitedFile (w/ minor mods) --- icu4c/source/test/intltest/unitstest.cpp | 114 +++++++++++++++++++++-- 1 file changed, 105 insertions(+), 9 deletions(-) diff --git a/icu4c/source/test/intltest/unitstest.cpp b/icu4c/source/test/intltest/unitstest.cpp index c8cdfdc6ed4..962f8251b7b 100644 --- a/icu4c/source/test/intltest/unitstest.cpp +++ b/icu4c/source/test/intltest/unitstest.cpp @@ -6,6 +6,7 @@ #if !UCONFIG_NO_FORMATTING #include "charstr.h" +#include "filestrm.h" #include "intltest.h" #include "number_decimalquantity.h" #include "unicode/ctest.h" @@ -217,8 +218,7 @@ void unitsTestDataLineFn(void *context, char *fields[][2], int32_t fieldCount, U // Possible after merging in younies/tryingdouble: // UnitConverter converter(sourceUnit, targetUnit, *pErrorCode); // double got = converter.convert(1000, *pErrorCode); - // ((UnitsTest*)context)->assertEqualsNear(quantity.data(), expected, got, - // 0.0001); + // ((UnitsTest*)context)->assertEqualsNear(quantity.data(), expected, got, 0.0001); // // In the meantime, printing to stderr. fprintf(stderr, @@ -299,8 +299,7 @@ void unitPreferencesTestDataLineFn(void *context, char *fields[][2], int32_t fie // Possible after merging in younies/tryingdouble: // UnitConverter converter(sourceUnit, targetUnit, *pErrorCode); // double got = converter.convert(1000, *pErrorCode); - // ((UnitsTest*)context)->assertEqualsNear(quantity.data(), expected, got, - // 0.0001); + // ((UnitsTest*)context)->assertEqualsNear(quantity.data(), expected, got, 0.0001); // // In the meantime, printing to stderr. fprintf(stderr, @@ -312,6 +311,106 @@ void unitPreferencesTestDataLineFn(void *context, char *fields[][2], int32_t fie outputUnit.data(), outputR.length(), outputR.data(), expectedOutput); } +// WIP(hugovdm): we need to replace u_parseDelimitedFile with something +// custom, because not all lines in unitPreferencesTest.txt have the same +// number of fields. +void parsePreferencesTests(const char *filename, char delimiter, char *fields[][2], int32_t fieldCount, + UParseLineFn *lineFn, void *context, UErrorCode *pErrorCode) { + FileStream *file; + char line[10000]; + char *start, *limit; + int32_t i, length; + + if (U_FAILURE(*pErrorCode)) { return; } + + if (fields == NULL || lineFn == NULL || fieldCount <= 0) { + *pErrorCode = U_ILLEGAL_ARGUMENT_ERROR; + return; + } + + if (filename == NULL || *filename == 0 || (*filename == '-' && filename[1] == 0)) { + filename = NULL; + file = T_FileStream_stdin(); + } else { + file = T_FileStream_open(filename, "r"); + } + if (file == NULL) { + *pErrorCode = U_FILE_ACCESS_ERROR; + return; + } + + while (T_FileStream_readLine(file, line, sizeof(line)) != NULL) { + /* remove trailing newline characters */ + length = (int32_t)(u_rtrim(line) - line); + + // FYI: uparse.cpp had this code, which we're skipping here: + // /* + // * detect a line with # @missing: + // * start parsing after that, or else from the beginning of the line + // * set the default warning for @missing lines + // */ + // start = (char *)getMissingLimit(line); + // if (start == line) { + // *pErrorCode = U_ZERO_ERROR; + // } else { + // *pErrorCode = U_USING_DEFAULT_WARNING; + // } + start = line; + *pErrorCode = U_ZERO_ERROR; + + /* skip this line if it is empty or a comment */ + if (*start == 0 || *start == '#') { continue; } + + /* remove in-line comments */ + limit = uprv_strchr(start, '#'); + if (limit != NULL) { + /* get white space before the pound sign */ + while (limit > start && U_IS_INV_WHITESPACE(*(limit - 1))) { + --limit; + } + + /* truncate the line */ + *limit = 0; + } + + /* skip lines with only whitespace */ + if (u_skipWhitespace(start)[0] == 0) { continue; } + + /* for each field, call the corresponding field function */ + for (i = 0; i < fieldCount; ++i) { + /* set the limit pointer of this field */ + limit = start; + while (*limit != delimiter && *limit != 0) { + ++limit; + } + + /* set the field start and limit in the fields array */ + fields[i][0] = start; + fields[i][1] = limit; + + /* set start to the beginning of the next field, if any */ + start = limit; + if (*start != 0) { + ++start; + } else if (i + 1 < fieldCount) { + *pErrorCode = U_PARSE_ERROR; + limit = line + length; + i = fieldCount; + break; + } + } + + /* too few fields? */ + if (U_FAILURE(*pErrorCode)) { break; } + + /* call the field function */ + lineFn(context, fields, fieldCount, pErrorCode); + if (U_FAILURE(*pErrorCode)) { break; } + } + + if (filename != NULL) { T_FileStream_close(file); } +} + /** * Runs data-driven unit tests for unit preferences. */ @@ -331,11 +430,8 @@ void UnitsTest::testPreferences() { path.appendPathPart("units", errorCode); path.appendPathPart(filename, errorCode); - // WIP(hugovdm): we need to replace u_parseDelimitedFile with something - // custom, because not all lines in unitPreferencesTest.txt have the same - // number of fields. - u_parseDelimitedFile(path.data(), ';', fields, kNumFields, unitPreferencesTestDataLineFn, this, - errorCode); + parsePreferencesTests(path.data(), ';', fields, kNumFields, unitPreferencesTestDataLineFn, this, + errorCode); if (errorCode.errIfFailureAndReset("error parsing %s: %s\n", path.data(), u_errorName(errorCode))) { return; } -- 2.40.0