TestNumberFormat.cpp (8299B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 #include "gtest/gtest.h" 5 6 #include "mozilla/intl/NumberFormat.h" 7 #include "TestBuffer.h" 8 9 #include <string_view> 10 11 namespace mozilla { 12 namespace intl { 13 14 TEST(IntlNumberFormat, Basic) 15 { 16 NumberFormatOptions options; 17 UniquePtr<NumberFormat> nf = 18 NumberFormat::TryCreate("en-US", options).unwrap(); 19 TestBuffer<char> buf8; 20 ASSERT_TRUE(nf->format(1234.56, buf8).isOk()); 21 ASSERT_EQ(buf8.get_string_view(), "1,234.56"); 22 TestBuffer<char16_t> buf16; 23 ASSERT_TRUE(nf->format(1234.56, buf16).isOk()); 24 ASSERT_EQ(buf16.get_string_view(), u"1,234.56"); 25 const char16_t* res16 = nf->format(1234.56).unwrap().data(); 26 ASSERT_TRUE(res16 != nullptr); 27 ASSERT_EQ(std::u16string_view(res16), u"1,234.56"); 28 29 UniquePtr<NumberFormat> nfAr = 30 NumberFormat::TryCreate("ar-EG", options).unwrap(); 31 ASSERT_TRUE(nfAr->format(1234.56, buf8).isOk()); 32 ASSERT_EQ(buf8.get_string_view(), "١٬٢٣٤٫٥٦"); 33 ASSERT_TRUE(nfAr->format(1234.56, buf16).isOk()); 34 ASSERT_EQ(buf16.get_string_view(), u"١٬٢٣٤٫٥٦"); 35 res16 = nfAr->format(1234.56).unwrap().data(); 36 ASSERT_TRUE(res16 != nullptr); 37 ASSERT_EQ(std::u16string_view(res16), u"١٬٢٣٤٫٥٦"); 38 } 39 40 TEST(IntlNumberFormat, Numbers) 41 { 42 NumberFormatOptions options; 43 UniquePtr<NumberFormat> nf = 44 NumberFormat::TryCreate("es-ES", options).unwrap(); 45 TestBuffer<char> buf8; 46 ASSERT_TRUE(nf->format(123456.789, buf8).isOk()); 47 ASSERT_EQ(buf8.get_string_view(), "123.456,789"); 48 TestBuffer<char16_t> buf16; 49 ASSERT_TRUE(nf->format(123456.789, buf16).isOk()); 50 ASSERT_EQ(buf16.get_string_view(), u"123.456,789"); 51 52 const char16_t* res = nf->format(123456.789).unwrap().data(); 53 ASSERT_TRUE(res != nullptr); 54 ASSERT_EQ(std::u16string_view(res), u"123.456,789"); 55 } 56 57 TEST(IntlNumberFormat, SignificantDigits) 58 { 59 NumberFormatOptions options; 60 options.mSignificantDigits = Some(std::make_pair(3, 5)); 61 UniquePtr<NumberFormat> nf = 62 NumberFormat::TryCreate("es-ES", options).unwrap(); 63 TestBuffer<char> buf8; 64 ASSERT_TRUE(nf->format(123456.789, buf8).isOk()); 65 ASSERT_EQ(buf8.get_string_view(), "123.460"); 66 ASSERT_TRUE(nf->format(0.7, buf8).isOk()); 67 ASSERT_EQ(buf8.get_string_view(), "0,700"); 68 } 69 70 TEST(IntlNumberFormat, Currency) 71 { 72 NumberFormatOptions options; 73 options.mCurrency = 74 Some(std::make_pair("MXN", NumberFormatOptions::CurrencyDisplay::Symbol)); 75 UniquePtr<NumberFormat> nf = 76 NumberFormat::TryCreate("es-MX", options).unwrap(); 77 TestBuffer<char> buf8; 78 ASSERT_TRUE(nf->format(123456.789, buf8).isOk()); 79 ASSERT_EQ(buf8.get_string_view(), "$123,456.79"); 80 TestBuffer<char16_t> buf16; 81 ASSERT_TRUE(nf->format(123456.789, buf16).isOk()); 82 ASSERT_EQ(buf16.get_string_view(), u"$123,456.79"); 83 const char16_t* res = nf->format(123456.789).unwrap().data(); 84 ASSERT_TRUE(res != nullptr); 85 ASSERT_EQ(std::u16string_view(res), u"$123,456.79"); 86 } 87 88 TEST(IntlNumberFormat, Unit) 89 { 90 NumberFormatOptions options; 91 options.mUnit = Some(std::make_pair("meter-per-second", 92 NumberFormatOptions::UnitDisplay::Long)); 93 UniquePtr<NumberFormat> nf = 94 NumberFormat::TryCreate("es-MX", options).unwrap(); 95 TestBuffer<char> buf8; 96 ASSERT_TRUE(nf->format(12.34, buf8).isOk()); 97 ASSERT_EQ(buf8.get_string_view(), "12.34 metros por segundo"); 98 TestBuffer<char16_t> buf16; 99 ASSERT_TRUE(nf->format(12.34, buf16).isOk()); 100 ASSERT_EQ(buf16.get_string_view(), u"12.34 metros por segundo"); 101 const char16_t* res = nf->format(12.34).unwrap().data(); 102 ASSERT_TRUE(res != nullptr); 103 ASSERT_EQ(std::u16string_view(res), u"12.34 metros por segundo"); 104 105 // Create a string view into a longer string and make sure everything works 106 // correctly. 107 const char* unit = "meter-per-second-with-some-trailing-garbage"; 108 options.mUnit = Some(std::make_pair(std::string_view(unit, 5), 109 NumberFormatOptions::UnitDisplay::Long)); 110 UniquePtr<NumberFormat> nf2 = 111 NumberFormat::TryCreate("es-MX", options).unwrap(); 112 res = nf2->format(12.34).unwrap().data(); 113 ASSERT_TRUE(res != nullptr); 114 ASSERT_EQ(std::u16string_view(res), u"12.34 metros"); 115 116 options.mUnit = Some(std::make_pair(std::string_view(unit, 16), 117 NumberFormatOptions::UnitDisplay::Long)); 118 UniquePtr<NumberFormat> nf3 = 119 NumberFormat::TryCreate("es-MX", options).unwrap(); 120 res = nf3->format(12.34).unwrap().data(); 121 ASSERT_TRUE(res != nullptr); 122 ASSERT_EQ(std::u16string_view(res), u"12.34 metros por segundo"); 123 } 124 125 TEST(IntlNumberFormat, RoundingMode) 126 { 127 NumberFormatOptions options; 128 options.mFractionDigits = Some(std::make_pair(0, 2)); 129 options.mStripTrailingZero = true; 130 options.mRoundingIncrement = 5; 131 options.mRoundingMode = NumberFormatOptions::RoundingMode::Ceil; 132 133 UniquePtr<NumberFormat> nf = NumberFormat::TryCreate("en", options).unwrap(); 134 135 const char16_t* res16 = nf->format(1.92).unwrap().data(); 136 ASSERT_TRUE(res16 != nullptr); 137 ASSERT_EQ(std::u16string_view(res16), u"1.95"); 138 139 res16 = nf->format(1.96).unwrap().data(); 140 ASSERT_TRUE(res16 != nullptr); 141 ASSERT_EQ(std::u16string_view(res16), u"2"); 142 } 143 144 TEST(IntlNumberFormat, Grouping) 145 { 146 NumberFormatOptions options; 147 options.mGrouping = NumberFormatOptions::Grouping::Min2; 148 149 UniquePtr<NumberFormat> nf = NumberFormat::TryCreate("en", options).unwrap(); 150 151 const char16_t* res16 = nf->format(1'000.0).unwrap().data(); 152 ASSERT_TRUE(res16 != nullptr); 153 ASSERT_EQ(std::u16string_view(res16), u"1000"); 154 155 res16 = nf->format(10'000.0).unwrap().data(); 156 ASSERT_TRUE(res16 != nullptr); 157 ASSERT_EQ(std::u16string_view(res16), u"10,000"); 158 } 159 160 TEST(IntlNumberFormat, RoundingPriority) 161 { 162 NumberFormatOptions options; 163 options.mFractionDigits = Some(std::make_pair(2, 2)); 164 options.mSignificantDigits = Some(std::make_pair(1, 2)); 165 options.mRoundingPriority = 166 NumberFormatOptions::RoundingPriority::LessPrecision; 167 168 UniquePtr<NumberFormat> nf1 = NumberFormat::TryCreate("en", options).unwrap(); 169 170 const char16_t* res16 = nf1->format(4.321).unwrap().data(); 171 ASSERT_TRUE(res16 != nullptr); 172 ASSERT_EQ(std::u16string_view(res16), u"4.3"); 173 174 options.mRoundingPriority = 175 NumberFormatOptions::RoundingPriority::MorePrecision; 176 177 UniquePtr<NumberFormat> nf2 = NumberFormat::TryCreate("en", options).unwrap(); 178 179 res16 = nf2->format(4.321).unwrap().data(); 180 ASSERT_TRUE(res16 != nullptr); 181 ASSERT_EQ(std::u16string_view(res16), u"4.32"); 182 } 183 184 TEST(IntlNumberFormat, FormatToParts) 185 { 186 NumberFormatOptions options; 187 UniquePtr<NumberFormat> nf = 188 NumberFormat::TryCreate("es-ES", options).unwrap(); 189 NumberPartVector parts; 190 const char16_t* res = nf->formatToParts(123456.789, parts).unwrap().data(); 191 ASSERT_TRUE(res != nullptr); 192 ASSERT_EQ(std::u16string_view(res), u"123.456,789"); 193 ASSERT_EQ(parts.length(), 5U); 194 195 // NumberFormat only ever produces number parts with NumberPartSource::Shared. 196 197 ASSERT_EQ(parts[0], 198 (NumberPart{NumberPartType::Integer, NumberPartSource::Shared, 3})); 199 ASSERT_EQ(parts[1], 200 (NumberPart{NumberPartType::Group, NumberPartSource::Shared, 4})); 201 ASSERT_EQ(parts[2], 202 (NumberPart{NumberPartType::Integer, NumberPartSource::Shared, 7})); 203 ASSERT_EQ(parts[3], 204 (NumberPart{NumberPartType::Decimal, NumberPartSource::Shared, 8})); 205 ASSERT_EQ(parts[4], (NumberPart{NumberPartType::Fraction, 206 NumberPartSource::Shared, 11})); 207 } 208 209 TEST(IntlNumberFormat, GetAvailableLocales) 210 { 211 using namespace std::literals; 212 213 int32_t english = 0; 214 int32_t german = 0; 215 int32_t chinese = 0; 216 217 // Since this list is dependent on ICU, and may change between upgrades, only 218 // test a subset of the available locales. 219 for (const char* locale : NumberFormat::GetAvailableLocales()) { 220 if (locale == "en"sv) { 221 english++; 222 } else if (locale == "de"sv) { 223 german++; 224 } else if (locale == "zh"sv) { 225 chinese++; 226 } 227 } 228 229 // Each locale should be found exactly once. 230 ASSERT_EQ(english, 1); 231 ASSERT_EQ(german, 1); 232 ASSERT_EQ(chinese, 1); 233 } 234 235 } // namespace intl 236 } // namespace mozilla