• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2018 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 
4 #include "unicode/utypes.h"
5 
6 #if !UCONFIG_NO_FORMATTING
7 
8 // Allow implicit conversion from char16_t* to UnicodeString for this file:
9 // Helpful in toString methods and elsewhere.
10 #define UNISTR_FROM_STRING_EXPLICIT
11 
12 #include <stdio.h>
13 #include "unicode/unumberformatter.h"
14 #include "unicode/unumberrangeformatter.h"
15 #include "unicode/umisc.h"
16 #include "unicode/unum.h"
17 #include "unicode/ustring.h"
18 #include "cformtst.h"
19 #include "cintltst.h"
20 #include "cmemory.h"
21 
22 static void TestExampleCode(void);
23 
24 static void TestFormattedValue(void);
25 
26 static void TestSkeletonParseError(void);
27 
28 static void TestGetDecimalNumbers(void);
29 
30 void addUNumberRangeFormatterTest(TestNode** root);
31 
32 #define TESTCASE(x) addTest(root, &x, "tsformat/unumberrangeformatter/" #x)
33 
addUNumberRangeFormatterTest(TestNode ** root)34 void addUNumberRangeFormatterTest(TestNode** root) {
35     TESTCASE(TestExampleCode);
36     TESTCASE(TestFormattedValue);
37     TESTCASE(TestSkeletonParseError);
38     TESTCASE(TestGetDecimalNumbers);
39 }
40 
41 
42 #define CAPACITY 30
43 
44 
TestExampleCode()45 static void TestExampleCode() {
46     // This is the example code given in unumberrangeformatter.h.
47 
48     // Setup:
49     UErrorCode ec = U_ZERO_ERROR;
50     UNumberRangeFormatter* uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
51         u"currency/USD precision-integer",
52         -1,
53         UNUM_RANGE_COLLAPSE_AUTO,
54         UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
55         "en-US",
56         NULL,
57         &ec);
58     UFormattedNumberRange* uresult = unumrf_openResult(&ec);
59     assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE);
60 
61     // Format a double range:
62     unumrf_formatDoubleRange(uformatter, 3.0, 5.0, uresult, &ec);
63     assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE);
64 
65     // Get the result string:
66     int32_t len;
67     const UChar* str = ufmtval_getString(unumrf_resultAsValue(uresult, &ec), &len, &ec);
68     assertSuccessCheck("There should not be a failure in the example code", &ec, TRUE);
69     assertUEquals("Should produce expected string result", u"$3 – $5", str);
70     int32_t resultLength = str != NULL ? u_strlen(str) : 0;
71     assertIntEquals("Length should be as expected", resultLength, len);
72 
73     // Cleanup:
74     unumrf_close(uformatter);
75     unumrf_closeResult(uresult);
76 }
77 
78 
TestFormattedValue()79 static void TestFormattedValue() {
80     UErrorCode ec = U_ZERO_ERROR;
81     UNumberRangeFormatter* uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
82         u"K",
83         -1,
84         UNUM_RANGE_COLLAPSE_AUTO,
85         UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
86         "en-US",
87         NULL,
88         &ec);
89     assertSuccessCheck("Should create without error", &ec, TRUE);
90     UFormattedNumberRange* uresult = unumrf_openResult(&ec);
91     assertSuccess("Should create result without error", &ec);
92 
93     // Test the decimal number code path, too
94     unumrf_formatDecimalRange(uformatter, "5.5e4", -1, "1.5e5", -1, uresult, &ec);
95 
96     if (assertSuccessCheck("Should format without error", &ec, TRUE)) {
97         const UFormattedValue* fv = unumrf_resultAsValue(uresult, &ec);
98         assertSuccess("Should convert without error", &ec);
99         static const UFieldPosition expectedFieldPositions[] = {
100             // field, begin index, end index
101             {UNUM_INTEGER_FIELD, 0, 2},
102             {UNUM_COMPACT_FIELD, 2, 3},
103             {UNUM_INTEGER_FIELD, 6, 9},
104             {UNUM_COMPACT_FIELD, 9, 10}};
105         checkFormattedValue(
106             "FormattedNumber as FormattedValue",
107             fv,
108             u"55K – 150K",
109             UFIELD_CATEGORY_NUMBER,
110             expectedFieldPositions,
111             UPRV_LENGTHOF(expectedFieldPositions));
112     }
113 
114     assertIntEquals("Identity result should match",
115         UNUM_IDENTITY_RESULT_NOT_EQUAL,
116         unumrf_resultGetIdentityResult(uresult, &ec));
117 
118     // cleanup:
119     unumrf_closeResult(uresult);
120     unumrf_close(uformatter);
121 }
122 
123 
TestSkeletonParseError()124 static void TestSkeletonParseError() {
125     UErrorCode ec = U_ZERO_ERROR;
126     UNumberRangeFormatter* uformatter;
127     UParseError perror;
128 
129     // The UParseError can be null. The following should not segfault.
130     uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
131         u".00 measure-unit/typo",
132         -1,
133         UNUM_RANGE_COLLAPSE_AUTO,
134         UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
135         "en",
136         NULL,
137         &ec);
138     unumrf_close(uformatter);
139 
140     // Now test the behavior.
141     ec = U_ZERO_ERROR;
142     uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
143         u".00 measure-unit/typo",
144         -1,
145         UNUM_RANGE_COLLAPSE_AUTO,
146         UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
147         "en",
148         &perror,
149         &ec);
150 
151     assertIntEquals("Should have set error code", U_NUMBER_SKELETON_SYNTAX_ERROR, ec);
152     assertIntEquals("Should have correct skeleton error offset", 17, perror.offset);
153     assertUEquals("Should have correct pre context", u"0 measure-unit/", perror.preContext);
154     assertUEquals("Should have correct post context", u"typo", perror.postContext);
155 
156     // cleanup:
157     unumrf_close(uformatter);
158 }
159 
160 
TestGetDecimalNumbers()161 static void TestGetDecimalNumbers() {
162     UErrorCode ec = U_ZERO_ERROR;
163     UNumberRangeFormatter* uformatter = unumrf_openForSkeletonWithCollapseAndIdentityFallback(
164         u"currency/USD",
165         -1,
166         UNUM_RANGE_COLLAPSE_AUTO,
167         UNUM_IDENTITY_FALLBACK_APPROXIMATELY,
168         "en-US",
169         NULL,
170         &ec);
171     assertSuccessCheck("Should create without error", &ec, TRUE);
172     UFormattedNumberRange* uresult = unumrf_openResult(&ec);
173     assertSuccess("Should create result without error", &ec);
174 
175     unumrf_formatDoubleRange(uformatter, 3.0, 5.0, uresult, &ec);
176     const UChar* str = ufmtval_getString(unumrf_resultAsValue(uresult, &ec), NULL, &ec);
177     assertSuccessCheck("Formatting should succeed", &ec, TRUE);
178     assertUEquals("Should produce expected string result", u"$3.00 \u2013 $5.00", str);
179 
180     char buffer[CAPACITY];
181 
182     int32_t len = unumrf_resultGetFirstDecimalNumber(uresult, buffer, CAPACITY, &ec);
183     assertIntEquals("First len should be as expected", strlen(buffer), len);
184     assertEquals("First decimal should be as expected", "3", buffer);
185 
186     len = unumrf_resultGetSecondDecimalNumber(uresult, buffer, CAPACITY, &ec);
187     assertIntEquals("Second len should be as expected", strlen(buffer), len);
188     assertEquals("Second decimal should be as expected", "5", buffer);
189 
190     // cleanup:
191     unumrf_closeResult(uresult);
192     unumrf_close(uformatter);
193 }
194 
195 #endif /* #if !UCONFIG_NO_FORMATTING */
196