mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-07 06:25:30 +00:00
ICU-13267 Refactoring field position testing logic into helper function.
Makes future field position logic easier to test.
This commit is contained in:
parent
ba21ff79c4
commit
11a559f319
3 changed files with 154 additions and 95 deletions
|
@ -70,7 +70,7 @@ class NumberFormatterApiTest : public IntlTest {
|
|||
void scale();
|
||||
void locale();
|
||||
void formatTypes();
|
||||
void fieldPosition();
|
||||
void fieldPositionLogic();
|
||||
void toFormat();
|
||||
void errors();
|
||||
void validRanges();
|
||||
|
@ -111,11 +111,15 @@ class NumberFormatterApiTest : public IntlTest {
|
|||
void assertFormatDescendingBig(const char16_t* message, const char16_t* skeleton,
|
||||
const UnlocalizedNumberFormatter& f, Locale locale, ...);
|
||||
|
||||
void assertFormatSingle(const char16_t* message, const char16_t* skeleton,
|
||||
const UnlocalizedNumberFormatter& f, Locale locale, double input,
|
||||
const UnicodeString& expected);
|
||||
FormattedNumber
|
||||
assertFormatSingle(const char16_t* message, const char16_t* skeleton,
|
||||
const UnlocalizedNumberFormatter& f, Locale locale, double input,
|
||||
const UnicodeString& expected);
|
||||
|
||||
void assertUndefinedSkeleton(const UnlocalizedNumberFormatter& f);
|
||||
|
||||
void assertFieldPositions(const char16_t* message, const FormattedNumber& formattedNumber,
|
||||
const UFieldPosition* expectedFieldPositions, int32_t length);
|
||||
};
|
||||
|
||||
class DecimalQuantityTest : public IntlTest {
|
||||
|
|
|
@ -84,7 +84,7 @@ void NumberFormatterApiTest::runIndexedTest(int32_t index, UBool exec, const cha
|
|||
TESTCASE_AUTO(scale);
|
||||
TESTCASE_AUTO(locale);
|
||||
TESTCASE_AUTO(formatTypes);
|
||||
TESTCASE_AUTO(fieldPosition);
|
||||
TESTCASE_AUTO(fieldPositionLogic);
|
||||
TESTCASE_AUTO(toFormat);
|
||||
TESTCASE_AUTO(errors);
|
||||
TESTCASE_AUTO(validRanges);
|
||||
|
@ -2164,10 +2164,18 @@ void NumberFormatterApiTest::formatTypes() {
|
|||
assertEquals("Format decNumber to 40 digits", str, actual);
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::fieldPosition() {
|
||||
IcuTestErrorCode status(*this, "fieldPosition");
|
||||
FormattedNumber fmtd = NumberFormatter::withLocale("en").formatDouble(-9876543210.12, status);
|
||||
assertEquals("Should have expected format output", u"-9,876,543,210.12", fmtd.toString(status));
|
||||
void NumberFormatterApiTest::fieldPositionLogic() {
|
||||
IcuTestErrorCode status(*this, "fieldPositionLogic");
|
||||
|
||||
const char16_t* message = u"Field position logic test";
|
||||
|
||||
FormattedNumber fmtd = assertFormatSingle(
|
||||
message,
|
||||
u"",
|
||||
NumberFormatter::with(),
|
||||
Locale::getEnglish(),
|
||||
-9876543210.12,
|
||||
u"-9,876,543,210.12");
|
||||
|
||||
static const UFieldPosition expectedFieldPositions[] = {
|
||||
// field, begin index, end index
|
||||
|
@ -2179,56 +2187,15 @@ void NumberFormatterApiTest::fieldPosition() {
|
|||
{UNUM_DECIMAL_SEPARATOR_FIELD, 14, 15},
|
||||
{UNUM_FRACTION_FIELD, 15, 17}};
|
||||
|
||||
FieldPositionIterator fpi;
|
||||
fmtd.getAllFieldPositions(fpi, status);
|
||||
int32_t i = 0;
|
||||
FieldPosition actual;
|
||||
while (fpi.next(actual)) {
|
||||
UFieldPosition expected = expectedFieldPositions[i++];
|
||||
assertEquals(
|
||||
UnicodeString(u"Field, case #") + Int64ToUnicodeString(i),
|
||||
expected.field,
|
||||
actual.getField());
|
||||
assertEquals(
|
||||
UnicodeString(u"Iterator, begin index, case #") + Int64ToUnicodeString(i),
|
||||
expected.beginIndex,
|
||||
actual.getBeginIndex());
|
||||
assertEquals(
|
||||
UnicodeString(u"Iterator, end index, case #") + Int64ToUnicodeString(i),
|
||||
expected.endIndex,
|
||||
actual.getEndIndex());
|
||||
|
||||
// Check for the first location of the field
|
||||
if (expected.field != UNUM_GROUPING_SEPARATOR_FIELD) {
|
||||
FieldPosition actual2(expected.field);
|
||||
UBool found = fmtd.nextFieldPosition(actual2, status);
|
||||
assertEquals(
|
||||
UnicodeString(u"Next, found first time, case #") + Int64ToUnicodeString(i),
|
||||
(UBool) TRUE,
|
||||
found);
|
||||
assertEquals(
|
||||
UnicodeString(u"Next, begin index, case #") + Int64ToUnicodeString(i),
|
||||
expected.beginIndex,
|
||||
actual2.getBeginIndex());
|
||||
assertEquals(
|
||||
UnicodeString(u"Next, end index, case #") + Int64ToUnicodeString(i),
|
||||
expected.endIndex,
|
||||
actual2.getEndIndex());
|
||||
found = fmtd.nextFieldPosition(actual2, status);
|
||||
assertEquals(
|
||||
UnicodeString(u"Next, found second time, case #") + Int64ToUnicodeString(i),
|
||||
(UBool) FALSE,
|
||||
found);
|
||||
}
|
||||
}
|
||||
assertEquals(
|
||||
"Should have seen every field position",
|
||||
sizeof(expectedFieldPositions) / sizeof(*expectedFieldPositions),
|
||||
i);
|
||||
assertFieldPositions(
|
||||
message,
|
||||
fmtd,
|
||||
expectedFieldPositions,
|
||||
sizeof(expectedFieldPositions)/sizeof(*expectedFieldPositions));
|
||||
|
||||
// Test the iteration functionality of nextFieldPosition
|
||||
actual = {UNUM_GROUPING_SEPARATOR_FIELD};
|
||||
i = 1;
|
||||
FieldPosition actual = {UNUM_GROUPING_SEPARATOR_FIELD};
|
||||
int32_t i = 1;
|
||||
while (fmtd.nextFieldPosition(actual, status)) {
|
||||
UFieldPosition expected = expectedFieldPositions[i++];
|
||||
assertEquals(
|
||||
|
@ -2614,15 +2581,17 @@ void NumberFormatterApiTest::assertFormatDescendingBig(const char16_t* umessage,
|
|||
}
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::assertFormatSingle(const char16_t* umessage, const char16_t* uskeleton,
|
||||
const UnlocalizedNumberFormatter& f, Locale locale,
|
||||
double input, const UnicodeString& expected) {
|
||||
FormattedNumber
|
||||
NumberFormatterApiTest::assertFormatSingle(const char16_t* umessage, const char16_t* uskeleton,
|
||||
const UnlocalizedNumberFormatter& f, Locale locale,
|
||||
double input, const UnicodeString& expected) {
|
||||
UnicodeString message(TRUE, umessage, -1);
|
||||
const LocalizedNumberFormatter l1 = f.threshold(0).locale(locale); // no self-regulation
|
||||
const LocalizedNumberFormatter l2 = f.threshold(1).locale(locale); // all self-regulation
|
||||
IcuTestErrorCode status(*this, "assertFormatSingle");
|
||||
status.setScope(message);
|
||||
UnicodeString actual1 = l1.formatDouble(input, status).toString();
|
||||
FormattedNumber result1 = l1.formatDouble(input, status);
|
||||
UnicodeString actual1 = result1.toString();
|
||||
assertSuccess(message + u": Unsafe Path", status);
|
||||
assertEquals(message + u": Unsafe Path", expected, actual1);
|
||||
UnicodeString actual2 = l2.formatDouble(input, status).toString();
|
||||
|
@ -2640,6 +2609,7 @@ void NumberFormatterApiTest::assertFormatSingle(const char16_t* umessage, const
|
|||
} else {
|
||||
assertUndefinedSkeleton(f);
|
||||
}
|
||||
return result1;
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::assertUndefinedSkeleton(const UnlocalizedNumberFormatter& f) {
|
||||
|
@ -2651,4 +2621,67 @@ void NumberFormatterApiTest::assertUndefinedSkeleton(const UnlocalizedNumberForm
|
|||
status);
|
||||
}
|
||||
|
||||
void NumberFormatterApiTest::assertFieldPositions(
|
||||
const char16_t* message, const FormattedNumber& formattedNumber,
|
||||
const UFieldPosition* expectedFieldPositions, int32_t length) {
|
||||
IcuTestErrorCode status(*this, "assertFieldPositions");
|
||||
UnicodeString baseMessage = UnicodeString(message) + u": " + formattedNumber.toString(status) + u": ";
|
||||
FieldPositionIterator fpi;
|
||||
formattedNumber.getAllFieldPositions(fpi, status);
|
||||
int32_t i = 0;
|
||||
FieldPosition actual;
|
||||
while (fpi.next(actual)) {
|
||||
UFieldPosition expected = expectedFieldPositions[i++];
|
||||
assertEquals(
|
||||
baseMessage + UnicodeString(u"Field, case #") + Int64ToUnicodeString(i),
|
||||
expected.field,
|
||||
actual.getField());
|
||||
assertEquals(
|
||||
baseMessage + UnicodeString(u"Iterator, begin, case #") + Int64ToUnicodeString(i),
|
||||
expected.beginIndex,
|
||||
actual.getBeginIndex());
|
||||
assertEquals(
|
||||
baseMessage + UnicodeString(u"Iterator, end, case #") + Int64ToUnicodeString(i),
|
||||
expected.endIndex,
|
||||
actual.getEndIndex());
|
||||
|
||||
// Check for the first location of the field
|
||||
FieldPosition actual2(expected.field);
|
||||
// Fast-forward the field to skip previous occurrences of the field:
|
||||
actual2.setBeginIndex(expected.beginIndex);
|
||||
actual2.setEndIndex(expected.beginIndex);
|
||||
UBool found = formattedNumber.nextFieldPosition(actual2, status);
|
||||
assertEquals(
|
||||
baseMessage + UnicodeString(u"Next, found first, case #") + Int64ToUnicodeString(i),
|
||||
(UBool) TRUE,
|
||||
found);
|
||||
assertEquals(
|
||||
baseMessage + UnicodeString(u"Next, begin, case #") + Int64ToUnicodeString(i),
|
||||
expected.beginIndex,
|
||||
actual2.getBeginIndex());
|
||||
assertEquals(
|
||||
baseMessage + UnicodeString(u"Next, end, case #") + Int64ToUnicodeString(i),
|
||||
expected.endIndex,
|
||||
actual2.getEndIndex());
|
||||
|
||||
// The next position should be empty unless the field occurs again
|
||||
UBool occursAgain = false;
|
||||
for (int32_t j=i; j<length; j++) {
|
||||
if (expectedFieldPositions[j].field == expected.field) {
|
||||
occursAgain = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!occursAgain) {
|
||||
found = formattedNumber.nextFieldPosition(actual2, status);
|
||||
assertEquals(
|
||||
baseMessage + UnicodeString(u"Next, found second, case #") + Int64ToUnicodeString(i),
|
||||
(UBool) FALSE,
|
||||
found);
|
||||
}
|
||||
}
|
||||
assertEquals(baseMessage + u"Should have seen every field position", length, i);
|
||||
}
|
||||
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -2144,9 +2144,16 @@ public class NumberFormatterApiTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void fieldPosition() {
|
||||
FormattedNumber fmtd = NumberFormatter.withLocale(ULocale.ENGLISH).format(-9876543210.12);
|
||||
assertEquals("Should have expected format output", "-9,876,543,210.12", fmtd.toString());
|
||||
public void fieldPositionLogic() {
|
||||
String message = "Field position logic test";
|
||||
|
||||
FormattedNumber fmtd = assertFormatSingle(
|
||||
message,
|
||||
"",
|
||||
NumberFormatter.with(),
|
||||
ULocale.ENGLISH,
|
||||
-9876543210.12,
|
||||
"-9,876,543,210.12");
|
||||
|
||||
Object[][] expectedFieldPositions = new Object[][]{
|
||||
{NumberFormat.Field.SIGN, 0, 1},
|
||||
|
@ -2157,38 +2164,11 @@ public class NumberFormatterApiTest {
|
|||
{NumberFormat.Field.DECIMAL_SEPARATOR, 14, 15},
|
||||
{NumberFormat.Field.FRACTION, 15, 17}};
|
||||
|
||||
AttributedCharacterIterator fpi = fmtd.getFieldIterator();
|
||||
Set<AttributedCharacterIterator.Attribute> allAttributes = fpi.getAllAttributeKeys();
|
||||
assertEquals("All known fields should be in the iterator", 5, allAttributes.size());
|
||||
assertEquals("Iterator should have length of string output", 17, fpi.getEndIndex());
|
||||
int i = 0;
|
||||
for (char c = fpi.first(); c != AttributedCharacterIterator.DONE; c = fpi.next(), i++) {
|
||||
Set<AttributedCharacterIterator.Attribute> currentAttributes = fpi.getAttributes().keySet();
|
||||
int attributesRemaining = currentAttributes.size();
|
||||
for (Object[] cas : expectedFieldPositions) {
|
||||
NumberFormat.Field expectedField = (NumberFormat.Field) cas[0];
|
||||
int expectedBeginIndex = (Integer) cas[1];
|
||||
int expectedEndIndex = (Integer) cas[2];
|
||||
if (expectedBeginIndex > i || expectedEndIndex <= i) {
|
||||
// Field position does not overlap with the current character
|
||||
continue;
|
||||
}
|
||||
|
||||
assertTrue("Current character should have expected field", currentAttributes.contains(expectedField));
|
||||
assertTrue("Field should be a known attribute", allAttributes.contains(expectedField));
|
||||
int actualBeginIndex = fpi.getRunStart(expectedField);
|
||||
int actualEndIndex = fpi.getRunLimit(expectedField);
|
||||
assertEquals(expectedField + " begin index @" + i, expectedBeginIndex, actualBeginIndex);
|
||||
assertEquals(expectedField + " end index @" + i, expectedEndIndex, actualEndIndex);
|
||||
attributesRemaining--;
|
||||
}
|
||||
assertEquals("Should have looked at every field", 0, attributesRemaining);
|
||||
}
|
||||
assertEquals("Should have looked at every character", 17, i);
|
||||
assertFieldPositions(message, fmtd, expectedFieldPositions);
|
||||
|
||||
// Test the iteration functionality of nextFieldPosition
|
||||
FieldPosition actual = new FieldPosition(NumberFormat.Field.GROUPING_SEPARATOR);
|
||||
i = 1;
|
||||
int i = 1;
|
||||
while (fmtd.nextFieldPosition(actual)) {
|
||||
Object[] cas = expectedFieldPositions[i++];
|
||||
NumberFormat.Field expectedField = (NumberFormat.Field) cas[0];
|
||||
|
@ -2444,7 +2424,7 @@ public class NumberFormatterApiTest {
|
|||
}
|
||||
}
|
||||
|
||||
static void assertFormatSingle(
|
||||
static FormattedNumber assertFormatSingle(
|
||||
String message,
|
||||
String skeleton,
|
||||
UnlocalizedNumberFormatter f,
|
||||
|
@ -2453,7 +2433,8 @@ public class NumberFormatterApiTest {
|
|||
String expected) {
|
||||
LocalizedNumberFormatter l1 = f.threshold(0L).locale(locale); // no self-regulation
|
||||
LocalizedNumberFormatter l2 = f.threshold(1L).locale(locale); // all self-regulation
|
||||
String actual1 = l1.format(input).toString();
|
||||
FormattedNumber result1 = l1.format(input);
|
||||
String actual1 = result1.toString();
|
||||
assertEquals(message + ": Unsafe Path: " + input, expected, actual1);
|
||||
String actual2 = l2.format(input).toString();
|
||||
assertEquals(message + ": Safe Path: " + input, expected, actual2);
|
||||
|
@ -2468,6 +2449,7 @@ public class NumberFormatterApiTest {
|
|||
} else {
|
||||
assertUndefinedSkeleton(f);
|
||||
}
|
||||
return result1;
|
||||
}
|
||||
|
||||
static void assertFormatSingleMeasure(
|
||||
|
@ -2502,4 +2484,44 @@ public class NumberFormatterApiTest {
|
|||
fail("Expected toSkeleton to fail, but it passed, producing: " + skeleton);
|
||||
} catch (UnsupportedOperationException expected) {}
|
||||
}
|
||||
|
||||
static void assertFieldPositions(String message, FormattedNumber formattedNumber, Object[][] expectedFieldPositions) {
|
||||
// Calculate some initial expected values
|
||||
int stringLength = formattedNumber.toString().length();
|
||||
HashSet<Format.Field> uniqueFields = new HashSet<>();
|
||||
for (int i=0; i<expectedFieldPositions.length; i++) {
|
||||
uniqueFields.add((Format.Field) expectedFieldPositions[i][0]);
|
||||
}
|
||||
String baseMessage = message + ": " + formattedNumber.toString() + ": ";
|
||||
|
||||
// Check the AttributedCharacterIterator
|
||||
AttributedCharacterIterator fpi = formattedNumber.getFieldIterator();
|
||||
Set<AttributedCharacterIterator.Attribute> allAttributes = fpi.getAllAttributeKeys();
|
||||
assertEquals(baseMessage + "All known fields should be in the iterator", uniqueFields.size(), allAttributes.size());
|
||||
assertEquals(baseMessage + "Iterator should have length of string output", stringLength, fpi.getEndIndex());
|
||||
int i = 0;
|
||||
for (char c = fpi.first(); c != AttributedCharacterIterator.DONE; c = fpi.next(), i++) {
|
||||
Set<AttributedCharacterIterator.Attribute> currentAttributes = fpi.getAttributes().keySet();
|
||||
int attributesRemaining = currentAttributes.size();
|
||||
for (Object[] cas : expectedFieldPositions) {
|
||||
NumberFormat.Field expectedField = (NumberFormat.Field) cas[0];
|
||||
int expectedBeginIndex = (Integer) cas[1];
|
||||
int expectedEndIndex = (Integer) cas[2];
|
||||
if (expectedBeginIndex > i || expectedEndIndex <= i) {
|
||||
// Field position does not overlap with the current character
|
||||
continue;
|
||||
}
|
||||
|
||||
assertTrue(baseMessage + "Current character should have expected field", currentAttributes.contains(expectedField));
|
||||
assertTrue(baseMessage + "Field should be a known attribute", allAttributes.contains(expectedField));
|
||||
int actualBeginIndex = fpi.getRunStart(expectedField);
|
||||
int actualEndIndex = fpi.getRunLimit(expectedField);
|
||||
assertEquals(baseMessage + expectedField + " begin @" + i, expectedBeginIndex, actualBeginIndex);
|
||||
assertEquals(baseMessage + expectedField + " end @" + i, expectedEndIndex, actualEndIndex);
|
||||
attributesRemaining--;
|
||||
}
|
||||
assertEquals(baseMessage + "Should have looked at every field", 0, attributesRemaining);
|
||||
}
|
||||
assertEquals(baseMessage + "Should have looked at every character", stringLength, i);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue