• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2020 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html#License
3 
4 #include "unicode/utypes.h"
5 
6 #if !UCONFIG_NO_FORMATTING
7 
8 #include "measunit_impl.h"
9 #include "units_data.h"
10 
11 #include "intltest.h"
12 
13 using namespace ::icu::units;
14 
15 // These test are no in ICU4J. TODO: consider porting them to Java?
16 class UnitsDataTest : public IntlTest {
17   public:
UnitsDataTest()18     UnitsDataTest() {}
19 
20     void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = NULL);
21 
22     void testGetUnitCategory();
23     void testGetAllConversionRates();
24     void testGetPreferencesFor();
25 };
26 
createUnitsDataTest()27 extern IntlTest *createUnitsDataTest() { return new UnitsDataTest(); }
28 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)29 void UnitsDataTest::runIndexedTest(int32_t index, UBool exec, const char *&name, char * /*par*/) {
30     if (exec) { logln("TestSuite UnitsDataTest: "); }
31     TESTCASE_AUTO_BEGIN;
32     TESTCASE_AUTO(testGetUnitCategory);
33     TESTCASE_AUTO(testGetAllConversionRates);
34     TESTCASE_AUTO(testGetPreferencesFor);
35     TESTCASE_AUTO_END;
36 }
37 
testGetUnitCategory()38 void UnitsDataTest::testGetUnitCategory() {
39     struct TestCase {
40         const char *unit;
41         const char *expectedCategory;
42     } testCases[]{
43         {"kilogram-per-cubic-meter", "mass-density"},
44         {"cubic-meter-per-kilogram", "specific-volume"},
45         {"meter-per-second", "speed"},
46         // TODO(icu-units#130): inverse-speed
47         // {"second-per-meter", "speed"},
48         // Consumption specifically supports inverse units (mile-per-galon,
49         // liter-per-100-kilometer):
50         {"cubic-meter-per-meter", "consumption"},
51         {"meter-per-cubic-meter", "consumption"},
52     };
53 
54     IcuTestErrorCode status(*this, "testGetUnitCategory");
55     for (const auto &t : testCases) {
56         CharString category = getUnitQuantity(t.unit, status);
57         if (!status.errIfFailureAndReset("getUnitCategory(%s)", t.unit)) {
58             assertEquals("category", t.expectedCategory, category.data());
59         }
60     }
61 }
62 
testGetAllConversionRates()63 void UnitsDataTest::testGetAllConversionRates() {
64     IcuTestErrorCode status(*this, "testGetAllConversionRates");
65     MaybeStackVector<ConversionRateInfo> conversionInfo;
66     getAllConversionRates(conversionInfo, status);
67 
68     // Convenience output for debugging
69     for (int i = 0; i < conversionInfo.length(); i++) {
70         ConversionRateInfo *cri = conversionInfo[i];
71         logln("* conversionInfo %d: source=\"%s\", baseUnit=\"%s\", factor=\"%s\", offset=\"%s\"", i,
72               cri->sourceUnit.data(), cri->baseUnit.data(), cri->factor.data(), cri->offset.data());
73         assertTrue("sourceUnit", cri->sourceUnit.length() > 0);
74         assertTrue("baseUnit", cri->baseUnit.length() > 0);
75         assertTrue("factor", cri->factor.length() > 0);
76     }
77 }
78 
79 class UnitPreferencesOpenedUp : public UnitPreferences {
80   public:
UnitPreferencesOpenedUp(UErrorCode & status)81     UnitPreferencesOpenedUp(UErrorCode &status) : UnitPreferences(status) {}
getInternalMetadata() const82     const MaybeStackVector<UnitPreferenceMetadata> *getInternalMetadata() const { return &metadata_; }
getInternalUnitPrefs() const83     const MaybeStackVector<UnitPreference> *getInternalUnitPrefs() const { return &unitPrefs_; }
84 };
85 
86 /**
87  * This test is dependent upon CLDR Data: when the preferences change, the test
88  * may fail: see the constants for expected Max/Min unit identifiers, for US and
89  * World, and for Roads and default lengths.
90  */
testGetPreferencesFor()91 void UnitsDataTest::testGetPreferencesFor() {
92     const char* USRoadMax = "mile";
93     const char* USRoadMin = "foot";
94     const char* USLenMax = "mile";
95     const char* USLenMin = "inch";
96     const char* WorldRoadMax = "kilometer";
97     const char* WorldRoadMin = "meter";
98     const char* WorldLenMax = "kilometer";
99     const char* WorldLenMin = "centimeter";
100     struct TestCase {
101         const char *name;
102         const char *category;
103         const char *usage;
104         const char *region;
105         const char *expectedBiggest;
106         const char *expectedSmallest;
107     } testCases[]{
108         {"US road", "length", "road", "US", USRoadMax, USRoadMin},
109         {"001 road", "length", "road", "001", WorldRoadMax, WorldRoadMin},
110         {"US lengths", "length", "default", "US", USLenMax, USLenMin},
111         {"001 lengths", "length", "default", "001", WorldLenMax, WorldLenMin},
112         {"XX road falls back to 001", "length", "road", "XX", WorldRoadMax, WorldRoadMin},
113         {"XX default falls back to 001", "length", "default", "XX", WorldLenMax, WorldLenMin},
114         {"Unknown usage US", "length", "foobar", "US", USLenMax, USLenMin},
115         {"Unknown usage 001", "length", "foobar", "XX", WorldLenMax, WorldLenMin},
116         {"Fallback", "length", "person-height-xyzzy", "DE", "centimeter", "centimeter"},
117         {"Fallback twice", "length", "person-height-xyzzy-foo", "DE", "centimeter",
118          "centimeter"},
119         // Confirming results for some unitPreferencesTest.txt test cases
120         {"001 area", "area", "default", "001", "square-kilometer", "square-centimeter"},
121         {"GB area", "area", "default", "GB", "square-mile", "square-inch"},
122         {"001 area geograph", "area", "geograph", "001", "square-kilometer", "square-kilometer"},
123         {"GB area geograph", "area", "geograph", "GB", "square-mile", "square-mile"},
124         {"CA person-height", "length", "person-height", "CA", "foot-and-inch", "inch"},
125         {"AT person-height", "length", "person-height", "AT", "meter-and-centimeter",
126          "meter-and-centimeter"},
127     };
128     IcuTestErrorCode status(*this, "testGetPreferencesFor");
129     UnitPreferencesOpenedUp preferences(status);
130     auto *metadata = preferences.getInternalMetadata();
131     auto *unitPrefs = preferences.getInternalUnitPrefs();
132     assertTrue(UnicodeString("Metadata count: ") + metadata->length() + " > 200",
133                metadata->length() > 200);
134     assertTrue(UnicodeString("Preferences count: ") + unitPrefs->length() + " > 250",
135                unitPrefs->length() > 250);
136 
137     for (const auto &t : testCases) {
138         logln(t.name);
139         const UnitPreference *const *prefs;
140         int32_t prefsCount;
141         preferences.getPreferencesFor(t.category, t.usage, t.region, prefs, prefsCount, status);
142         if (status.errIfFailureAndReset("getPreferencesFor(\"%s\", \"%s\", \"%s\", ...", t.category,
143                                         t.usage, t.region)) {
144             continue;
145         }
146         if (prefsCount > 0) {
147             assertEquals(UnicodeString(t.name) + " - max unit", t.expectedBiggest,
148                          prefs[0]->unit.data());
149             assertEquals(UnicodeString(t.name) + " - min unit", t.expectedSmallest,
150                          prefs[prefsCount - 1]->unit.data());
151         } else {
152             errln(UnicodeString(t.name) + ": failed to find preferences");
153         }
154         status.errIfFailureAndReset("testCase '%s'", t.name);
155     }
156 }
157 
158 #endif /* #if !UCONFIG_NO_FORMATTING */
159