Also adds expectError to IcuTestErrorCode.
// Note: in ICU4J Currency.getInstance(), we check string length for 3, but in ICU4C we allow a
// non-NUL-terminated string to be passed as an argument, so it is not possible to check length.
// However, we allow a NUL-terminated empty string, which should have the same behavior as nullptr.
+ // Consider NUL-terminated strings of length 1 or 2 as invalid.
const char16_t* isoCodeToUse;
if (U_FAILURE(ec) || _isoCode == nullptr || _isoCode[0] == 0) {
isoCodeToUse = kDefaultCurrency;
+ } else if (_isoCode[1] == 0 || _isoCode[2] == 0) {
+ isoCodeToUse = kDefaultCurrency;
+ ec = U_ILLEGAL_ARGUMENT_ERROR;
} else if (!uprv_isInvariantUString(_isoCode, 3)) {
// TODO: Perform a more strict ASCII check like in ICU4J isAlpha3Code?
isoCodeToUse = kDefaultCurrency;
helper.test = this;
// Test destructor message
- helper.expectedErrln = u"AAA failure: U_ILLEGAL_PAD_POSITION";
+ helper.expectedErrln = u"AAA destructor: expected success but got error: U_ILLEGAL_PAD_POSITION";
helper.expectedDataErr = FALSE;
helper.seenError = FALSE;
{
assertTrue("Should have seen an error", helper.seenError);
// Test destructor message with scope
- helper.expectedErrln = u"BBB failure: U_ILLEGAL_PAD_POSITION scope: foo";
+ helper.expectedErrln = u"BBB destructor: expected success but got error: U_ILLEGAL_PAD_POSITION scope: foo";
helper.expectedDataErr = FALSE;
helper.seenError = FALSE;
{
assertTrue("Should have seen an error", helper.seenError);
// Check errIfFailure message with scope
- helper.expectedErrln = u"CCC failure: U_ILLEGAL_PAD_POSITION scope: foo";
+ helper.expectedErrln = u"CCC expected success but got error: U_ILLEGAL_PAD_POSITION scope: foo";
helper.expectedDataErr = FALSE;
helper.seenError = FALSE;
{
testStatus.errIfFailureAndReset();
assertTrue("Should have seen an error", helper.seenError);
helper.seenError = FALSE;
- helper.expectedErrln = u"CCC failure: U_ILLEGAL_CHAR_FOUND scope: foo - 5.4300";
+ helper.expectedErrln = u"CCC expected success but got error: U_ILLEGAL_CHAR_FOUND scope: foo - 5.4300";
testStatus.set(U_ILLEGAL_CHAR_FOUND);
testStatus.errIfFailureAndReset("%6.4f", 5.43);
assertTrue("Should have seen an error", helper.seenError);
}
// Check errDataIfFailure message without scope
- helper.expectedErrln = u"DDD failure: U_ILLEGAL_PAD_POSITION";
+ helper.expectedErrln = u"DDD data: expected success but got error: U_ILLEGAL_PAD_POSITION";
helper.expectedDataErr = TRUE;
helper.seenError = FALSE;
{
testStatus.errDataIfFailureAndReset();
assertTrue("Should have seen an error", helper.seenError);
helper.seenError = FALSE;
- helper.expectedErrln = u"DDD failure: U_ILLEGAL_CHAR_FOUND - 5.4300";
+ helper.expectedErrln = u"DDD data: expected success but got error: U_ILLEGAL_CHAR_FOUND - 5.4300";
testStatus.set(U_ILLEGAL_CHAR_FOUND);
testStatus.errDataIfFailureAndReset("%6.4f", 5.43);
assertTrue("Should have seen an error", helper.seenError);
}
+
+ // Check expectFailure
+ helper.expectedErrln = u"EEE expected: U_ILLEGAL_CHAR_FOUND but got error: U_ILLEGAL_PAD_POSITION";
+ helper.expectedDataErr = FALSE;
+ helper.seenError = FALSE;
+ {
+ IcuTestErrorCode testStatus(helper, "EEE");
+ testStatus.set(U_ILLEGAL_PAD_POSITION);
+ testStatus.expectErrorAndReset(U_ILLEGAL_PAD_POSITION);
+ assertFalse("Should NOT have seen an error", helper.seenError);
+ testStatus.set(U_ILLEGAL_PAD_POSITION);
+ testStatus.expectErrorAndReset(U_ILLEGAL_CHAR_FOUND);
+ assertTrue("Should have seen an error", helper.seenError);
+ helper.seenError = FALSE;
+ helper.expectedErrln = u"EEE expected: U_ILLEGAL_CHAR_FOUND but got error: U_ZERO_ERROR scope: scopety scope - 5.4300";
+ testStatus.setScope("scopety scope");
+ testStatus.set(U_ILLEGAL_PAD_POSITION);
+ testStatus.expectErrorAndReset(U_ILLEGAL_PAD_POSITION, "%6.4f", 5.43);
+ assertFalse("Should NOT have seen an error", helper.seenError);
+ testStatus.expectErrorAndReset(U_ILLEGAL_CHAR_FOUND, "%6.4f", 5.43);
+ assertTrue("Should have seen an error", helper.seenError);
+ }
}
}
void MeasureFormatTest::TestCurrencies() {
- UChar USD[4];
+ UChar USD[4] = {};
u_uastrcpy(USD, "USD");
UErrorCode status = U_ZERO_ERROR;
+ CurrencyUnit USD_unit(USD, status);
+ assertEquals("Currency Unit", USD, USD_unit.getISOCurrency());
+ if (!assertSuccess("Error creating CurrencyUnit", status)) {
+ return;
+ }
CurrencyAmount USD_1(1.0, USD, status);
assertEquals("Currency Code", USD, USD_1.getISOCurrency());
CurrencyAmount USD_2(2.0, USD, status);
void NumberFormatTest::Test13850_EmptyStringCurrency() {
IcuTestErrorCode status(*this, "Test13840_EmptyStringCurrency");
- LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
- if (status.errIfFailureAndReset()) { return; }
- UnicodeString actual;
- nf->format(1, actual, status);
- assertEquals("Should format with US currency", u"$1.00", actual);
- nf->setCurrency(u"", status);
- nf->format(1, actual.remove(), status);
- assertEquals("Should unset the currency on empty string", u"XXX\u00A01.00", actual);
-
- // Try with nullptr
- nf.adoptInstead(NumberFormat::createCurrencyInstance("en-US", status));
- nf->format(1, actual.remove(), status);
- assertEquals("Should format with US currency", u"$1.00", actual);
- nf->setCurrency(nullptr, status);
- nf->format(1, actual.remove(), status);
- assertEquals("Should unset the currency on nullptr", u"XXX\u00A01.00", actual);
+ struct TestCase {
+ const char16_t* currencyArg;
+ UErrorCode expectedError;
+ } cases[] = {
+ {u"", U_ZERO_ERROR},
+ {u"U", U_ILLEGAL_ARGUMENT_ERROR},
+ {u"Us", U_ILLEGAL_ARGUMENT_ERROR},
+ {nullptr, U_ZERO_ERROR},
+ {u"U$D", U_INVARIANT_CONVERSION_ERROR},
+ {u"Xxx", U_ZERO_ERROR}
+ };
+ for (const auto& cas : cases) {
+ UnicodeString message(u"with currency arg: ");
+ if (cas.currencyArg == nullptr) {
+ message += u"nullptr";
+ } else {
+ message += UnicodeString(cas.currencyArg);
+ }
+ status.setScope(message);
+ LocalPointer<NumberFormat> nf(NumberFormat::createCurrencyInstance("en-US", status), status);
+ if (status.errIfFailureAndReset()) { return; }
+ UnicodeString actual;
+ nf->format(1, actual, status);
+ status.errIfFailureAndReset();
+ assertEquals(u"Should format with US currency " + message, u"$1.00", actual);
+ nf->setCurrency(cas.currencyArg, status);
+ if (status.expectErrorAndReset(cas.expectedError)) {
+ // If an error occurred, do not check formatting.
+ continue;
+ }
+ nf->format(1, actual.remove(), status);
+ assertEquals(u"Should unset the currency " + message, u"XXX\u00A01.00", actual);
+ status.errIfFailureAndReset();
+ }
}
#endif /* #if !UCONFIG_NO_FORMATTING */
IcuTestErrorCode::~IcuTestErrorCode() {
// Safe because our errlog() does not throw exceptions.
if(isFailure()) {
- errlog(FALSE, nullptr);
+ errlog(FALSE, u"destructor: expected success", nullptr);
}
}
UBool IcuTestErrorCode::errIfFailureAndReset() {
if(isFailure()) {
- errlog(FALSE, nullptr);
+ errlog(FALSE, u"expected success", nullptr);
reset();
return TRUE;
} else {
va_start(ap, fmt);
vsprintf(buffer, fmt, ap);
va_end(ap);
- errlog(FALSE, buffer);
+ errlog(FALSE, u"expected success", buffer);
reset();
return TRUE;
} else {
UBool IcuTestErrorCode::errDataIfFailureAndReset() {
if(isFailure()) {
- errlog(TRUE, nullptr);
+ errlog(TRUE, u"data: expected success", nullptr);
reset();
return TRUE;
} else {
va_start(ap, fmt);
vsprintf(buffer, fmt, ap);
va_end(ap);
- errlog(TRUE, buffer);
+ errlog(TRUE, u"data: expected success", buffer);
reset();
return TRUE;
} else {
}
}
+UBool IcuTestErrorCode::expectErrorAndReset(UErrorCode expectedError) {
+ if(get() != expectedError) {
+ errlog(FALSE, UnicodeString(u"expected: ") + u_errorName(expectedError), nullptr);
+ }
+ UBool retval = isFailure();
+ reset();
+ return retval;
+}
+
+UBool IcuTestErrorCode::expectErrorAndReset(UErrorCode expectedError, const char *fmt, ...) {
+ if(get() != expectedError) {
+ char buffer[4000];
+ va_list ap;
+ va_start(ap, fmt);
+ vsprintf(buffer, fmt, ap);
+ va_end(ap);
+ errlog(FALSE, UnicodeString(u"expected: ") + u_errorName(expectedError), buffer);
+ }
+ UBool retval = isFailure();
+ reset();
+ return retval;
+}
+
void IcuTestErrorCode::setScope(const char* message) {
scopeMessage.remove().append({ message, -1, US_INV });
}
}
void IcuTestErrorCode::handleFailure() const {
- errlog(FALSE, nullptr);
+ errlog(FALSE, u"(handleFailure)", nullptr);
}
-void IcuTestErrorCode::errlog(UBool dataErr, const char* extraMessage) const {
+void IcuTestErrorCode::errlog(UBool dataErr, const UnicodeString& mainMessage, const char* extraMessage) const {
UnicodeString msg(testName, -1, US_INV);
- msg.append(u" failure: ").append(UnicodeString(errorName(), -1, US_INV));
+ msg.append(u' ').append(mainMessage);
+ msg.append(u" but got error: ").append(UnicodeString(errorName(), -1, US_INV));
if (!scopeMessage.isEmpty()) {
msg.append(u" scope: ").append(scopeMessage);
UBool errIfFailureAndReset(const char *fmt, ...);
UBool errDataIfFailureAndReset();
UBool errDataIfFailureAndReset(const char *fmt, ...);
+ UBool expectErrorAndReset(UErrorCode expectedError);
+ UBool expectErrorAndReset(UErrorCode expectedError, const char *fmt, ...);
/** Sets an additional message string to be appended to failure output. */
void setScope(const char* message);
const char *const testName;
UnicodeString scopeMessage;
- void errlog(UBool dataErr, const char* extraMessage) const;
+ void errlog(UBool dataErr, const UnicodeString& mainMessage, const char* extraMessage) const;
};
#endif