|
|
// © 2018 and later: Unicode, Inc. and others.
|
|
|
// License & terms of use: http://www.unicode.org/copyright.html
|
|
|
|
|
|
#include "unicode/utypes.h"
|
|
|
|
|
|
#if !UCONFIG_NO_FORMATTING
|
|
|
|
|
|
// Allow implicit conversion from char16_t* to UnicodeString for this file:
|
|
|
// Helpful in toString methods and elsewhere.
|
|
|
#define UNISTR_FROM_STRING_EXPLICIT
|
|
|
|
|
|
#include <stdio.h>
|
|
|
#include "unicode/unumberformatter.h"
|
|
|
#include "unicode/unumberrangeformatter.h"
|
|
|
#include "unicode/umisc.h"
|
|
|
#include "unicode/unum.h"
|
|
|
#include "unicode/ustring.h"
|
|
|
#include "cformtst.h"
|
|
|
#include "cintltst.h"
|
|
|
#include "cmemory.h"
|
|
|
|
|
|
static void TestExampleCode(void);
|
|
|
|
|
|
static void TestFormattedValue(void);
|
|
|
|
|
|
static void TestSkeletonParseError(void);
|
|
|
|
|
|
static void TestGetDecimalNumbers(void);
|
|
|
|
|
|
void addUNumberRangeFormatterTest(TestNode** root);
|
|
|
|
|
|
#define TESTCASE(x) addTest(root, &x, "tsformat/unumberrangeformatter/" #x)
|
|
|
|
|
|
void addUNumberRangeFormatterTest(TestNode** root) {
|
|
|
TESTCASE(TestExampleCode);
|
|
|
TESTCASE(TestFormattedValue);
|
|
|
TESTCASE(TestSkeletonParseError);
|
|
|
TESTCASE(TestGetDecimalNumbers);
|
|
|
}
|
|
|
|
|
|
|
|
|
#define CAPACITY 30
|
|
|
|
|
|
|
|
|
static void TestExampleCode() {
|
|
|
// This is the example code given in unumberrangeformatter.h.
|
|
|
|
|
|
// Setup:
|
|
|
UErrorCode ec = U_ZERO_ERROR;
|
|
|
UNumberRangeFormatter* uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
|
|
|
u"currency/USD precision-integer",
|
|
|
-1,
|
|
|
UNUM_RANGE_COLLAPSE_AUTO,
|
|
|
UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
|
|
|
"en-US",
|
|
|
NULL,
|
|
|
&ec);
|
|
|
UFormattedNumberRange* uresult = unumrf_openResult(&ec);
|
|
|
assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE);
|
|
|
|
|
|
// Format a double range:
|
|
|
unumrf_formatDoubleRange(uformatter, 3.0, 5.0, uresult, &ec);
|
|
|
assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE);
|
|
|
|
|
|
// Get the result string:
|
|
|
int32_t len;
|
|
|
const UChar* str = ufmtval_getString(unumrf_resultAsValue(uresult, &ec), &len, &ec);
|
|
|
assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE);
|
|
|
assertUEquals("Should produce expected string result", u"$3 – $5", str);
|
|
|
int32_t resultLength = str != NULL ? u_strlen(str) : 0;
|
|
|
assertIntEquals("Length should be as expected", resultLength, len);
|
|
|
|
|
|
// Cleanup:
|
|
|
unumrf_close(uformatter);
|
|
|
unumrf_closeResult(uresult);
|
|
|
}
|
|
|
|
|
|
|
|
|
static void TestFormattedValue() {
|
|
|
UErrorCode ec = U_ZERO_ERROR;
|
|
|
UNumberRangeFormatter* uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
|
|
|
u"K",
|
|
|
-1,
|
|
|
UNUM_RANGE_COLLAPSE_AUTO,
|
|
|
UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
|
|
|
"en-US",
|
|
|
NULL,
|
|
|
&ec);
|
|
|
assertSuccessCheck("Should create without error", &ec, TRUE);
|
|
|
UFormattedNumberRange* uresult = unumrf_openResult(&ec);
|
|
|
assertSuccess("Should create result without error", &ec);
|
|
|
|
|
|
// Test the decimal number code path, too
|
|
|
unumrf_formatDecimalRange(uformatter, "5.5e4", -1, "1.5e5", -1, uresult, &ec);
|
|
|
|
|
|
if (assertSuccessCheck("Should format without error", &ec, TRUE)) {
|
|
|
const UFormattedValue* fv = unumrf_resultAsValue(uresult, &ec);
|
|
|
assertSuccess("Should convert without error", &ec);
|
|
|
static const UFieldPosition expectedFieldPositions[] = {
|
|
|
// field, begin index, end index
|
|
|
{UNUM_INTEGER_FIELD, 0, 2},
|
|
|
{UNUM_COMPACT_FIELD, 2, 3},
|
|
|
{UNUM_INTEGER_FIELD, 6, 9},
|
|
|
{UNUM_COMPACT_FIELD, 9, 10}};
|
|
|
checkFormattedValue(
|
|
|
"FormattedNumber as FormattedValue",
|
|
|
fv,
|
|
|
u"55K – 150K",
|
|
|
UFIELD_CATEGORY_NUMBER,
|
|
|
expectedFieldPositions,
|
|
|
UPRV_LENGTHOF(expectedFieldPositions));
|
|
|
}
|
|
|
|
|
|
assertIntEquals("Identity result should match",
|
|
|
UNUM_IDENTITY_RESULT_NOT_EQUAL,
|
|
|
unumrf_resultGetIdentityResult(uresult, &ec));
|
|
|
|
|
|
// cleanup:
|
|
|
unumrf_closeResult(uresult);
|
|
|
unumrf_close(uformatter);
|
|
|
}
|
|
|
|
|
|
|
|
|
static void TestSkeletonParseError() {
|
|
|
UErrorCode ec = U_ZERO_ERROR;
|
|
|
UNumberRangeFormatter* uformatter;
|
|
|
UParseError perror;
|
|
|
|
|
|
// The UParseError can be null. The following should not segfault.
|
|
|
uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
|
|
|
u".00 measure-unit/typo",
|
|
|
-1,
|
|
|
UNUM_RANGE_COLLAPSE_AUTO,
|
|
|
UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
|
|
|
"en",
|
|
|
NULL,
|
|
|
&ec);
|
|
|
unumrf_close(uformatter);
|
|
|
|
|
|
// Now test the behavior.
|
|
|
ec = U_ZERO_ERROR;
|
|
|
uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
|
|
|
u".00 measure-unit/typo",
|
|
|
-1,
|
|
|
UNUM_RANGE_COLLAPSE_AUTO,
|
|
|
UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
|
|
|
"en",
|
|
|
&perror,
|
|
|
&ec);
|
|
|
|
|
|
assertIntEquals("Should have set error code", U_NUMBER_SKELETON_SYNTAX_ERROR, ec);
|
|
|
assertIntEquals("Should have correct skeleton error offset", 17, perror.offset);
|
|
|
assertUEquals("Should have correct pre context", u"0 measure-unit/", perror.preContext);
|
|
|
assertUEquals("Should have correct post context", u"typo", perror.postContext);
|
|
|
|
|
|
// cleanup:
|
|
|
unumrf_close(uformatter);
|
|
|
}
|
|
|
|
|
|
|
|
|
static void TestGetDecimalNumbers() {
|
|
|
UErrorCode ec = U_ZERO_ERROR;
|
|
|
UNumberRangeFormatter* uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
|
|
|
u"currency/USD",
|
|
|
-1,
|
|
|
UNUM_RANGE_COLLAPSE_AUTO,
|
|
|
UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
|
|
|
"en-US",
|
|
|
NULL,
|
|
|
&ec);
|
|
|
assertSuccessCheck("Should create without error", &ec, TRUE);
|
|
|
UFormattedNumberRange* uresult = unumrf_openResult(&ec);
|
|
|
assertSuccess("Should create result without error", &ec);
|
|
|
|
|
|
unumrf_formatDoubleRange(uformatter, 3.0, 5.0, uresult, &ec);
|
|
|
const UChar* str = ufmtval_getString(unumrf_resultAsValue(uresult, &ec), NULL, &ec);
|
|
|
assertSuccessCheck("Formatting should succeed", &ec, TRUE);
|
|
|
assertUEquals("Should produce expected string result", u"$3.00 \u2013 $5.00", str);
|
|
|
|
|
|
char buffer[CAPACITY];
|
|
|
|
|
|
int32_t len = unumrf_resultGetFirstDecimalNumber(uresult, buffer, CAPACITY, &ec);
|
|
|
assertIntEquals("First len should be as expected", strlen(buffer), len);
|
|
|
assertEquals("First decimal should be as expected", "3", buffer);
|
|
|
|
|
|
len = unumrf_resultGetSecondDecimalNumber(uresult, buffer, CAPACITY, &ec);
|
|
|
assertIntEquals("Second len should be as expected", strlen(buffer), len);
|
|
|
assertEquals("Second decimal should be as expected", "5", buffer);
|
|
|
|
|
|
// cleanup:
|
|
|
unumrf_closeResult(uresult);
|
|
|
unumrf_close(uformatter);
|
|
|
}
|
|
|
|
|
|
#endif /* #if !UCONFIG_NO_FORMATTING */
|