1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 /* 24 * @test 25 * @bug 8177552 26 * @summary Checks the functioning of compact number format 27 * @modules jdk.localedata 28 * @run testng/othervm TestCompactNumber 29 */ 30 import java.math.BigDecimal; 31 import java.math.BigInteger; 32 import java.text.FieldPosition; 33 import java.text.Format; 34 import java.text.NumberFormat; 35 import java.text.ParseException; 36 import java.text.ParsePosition; 37 import java.util.Locale; 38 import java.util.stream.Stream; 39 import static org.testng.Assert.*; 40 import org.testng.annotations.DataProvider; 41 import org.testng.annotations.Test; 42 43 public class TestCompactNumber { 44 45 private static final NumberFormat FORMAT_DZ_LONG = NumberFormat 46 .getCompactNumberInstance(new Locale("dz"), NumberFormat.Style.LONG); 47 48 private static final NumberFormat FORMAT_EN_US_SHORT = NumberFormat 49 .getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT); 50 51 private static final NumberFormat FORMAT_EN_LONG = NumberFormat 52 .getCompactNumberInstance(new Locale("en"), NumberFormat.Style.LONG); 53 54 private static final NumberFormat FORMAT_HI_IN_LONG = NumberFormat 55 .getCompactNumberInstance(new Locale("hi", "IN"), NumberFormat.Style.LONG); 56 57 private static final NumberFormat FORMAT_JA_JP_SHORT = NumberFormat 58 .getCompactNumberInstance(Locale.JAPAN, NumberFormat.Style.SHORT); 59 60 private static final NumberFormat FORMAT_IT_SHORT = NumberFormat 61 .getCompactNumberInstance(new Locale("it"), NumberFormat.Style.SHORT); 62 63 private static final NumberFormat FORMAT_CA_LONG = NumberFormat 64 .getCompactNumberInstance(new Locale("ca"), NumberFormat.Style.LONG); 65 66 private static final NumberFormat FORMAT_AS_LONG = NumberFormat 67 .getCompactNumberInstance(new Locale("as"), NumberFormat.Style.LONG); 68 69 private static final NumberFormat FORMAT_BRX_SHORT = NumberFormat 70 .getCompactNumberInstance(new Locale("brx"), NumberFormat.Style.SHORT); 71 72 private static final NumberFormat FORMAT_SW_LONG = NumberFormat 73 .getCompactNumberInstance(new Locale("sw"), NumberFormat.Style.LONG); 74 75 private static final NumberFormat FORMAT_SE_SHORT = NumberFormat 76 .getCompactNumberInstance(new Locale("se"), NumberFormat.Style.SHORT); 77 78 @DataProvider(name = "format") 79 Object[][] compactFormatData() { 80 return new Object[][]{ 81 // compact number format instance, number to format, formatted output 82 {FORMAT_DZ_LONG, 1000.09, "\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55" 83 + "\u0FB2\u0F42 \u0F21"}, 84 {FORMAT_DZ_LONG, -999.99, "-\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55" 85 + "\u0FB2\u0F42 \u0F21"}, 86 {FORMAT_DZ_LONG, -0.0, "-\u0F20"}, 87 {FORMAT_DZ_LONG, 3000L, "\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55" 88 + "\u0FB2\u0F42 \u0F23"}, 89 {FORMAT_DZ_LONG, new BigInteger("12345678901234567890"), "\u0F51" 90 + "\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B\u0F66" 91 + "\u0F0B\u0F61\u0F0B \u0F21\u0F22\u0F23\u0F24\u0F25\u0F27"}, 92 // negative 93 {FORMAT_DZ_LONG, new BigInteger("-12345678901234567890"), "-\u0F51" 94 + "\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B\u0F66" 95 + "\u0F0B\u0F61\u0F0B \u0F21\u0F22\u0F23\u0F24\u0F25\u0F27"}, 96 {FORMAT_DZ_LONG, new BigDecimal("12345678901234567890.89"), "\u0F51" 97 + "\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B\u0F66" 98 + "\u0F0B\u0F61\u0F0B \u0F21\u0F22\u0F23\u0F24\u0F25\u0F27"}, 99 {FORMAT_DZ_LONG, new BigDecimal("-12345678901234567890.89"), "-\u0F51" 100 + "\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62\u0F0B\u0F66" 101 + "\u0F0B\u0F61\u0F0B \u0F21\u0F22\u0F23\u0F24\u0F25\u0F27"}, 102 // Zeros 103 {FORMAT_EN_US_SHORT, 0, "0"}, 104 {FORMAT_EN_US_SHORT, 0.0, "0"}, 105 {FORMAT_EN_US_SHORT, -0.0, "-0"}, 106 // Less than 1000 no suffix 107 {FORMAT_EN_US_SHORT, 499, "499"}, 108 // Boundary number 109 {FORMAT_EN_US_SHORT, 1000.0, "1K"}, 110 // Long 111 {FORMAT_EN_US_SHORT, 3000L, "3K"}, 112 {FORMAT_EN_US_SHORT, 30000L, "30K"}, 113 {FORMAT_EN_US_SHORT, 300000L, "300K"}, 114 {FORMAT_EN_US_SHORT, 3000000L, "3M"}, 115 {FORMAT_EN_US_SHORT, 30000000L, "30M"}, 116 {FORMAT_EN_US_SHORT, 300000000L, "300M"}, 117 {FORMAT_EN_US_SHORT, 3000000000L, "3B"}, 118 {FORMAT_EN_US_SHORT, 30000000000L, "30B"}, 119 {FORMAT_EN_US_SHORT, 300000000000L, "300B"}, 120 {FORMAT_EN_US_SHORT, 3000000000000L, "3T"}, 121 {FORMAT_EN_US_SHORT, 30000000000000L, "30T"}, 122 {FORMAT_EN_US_SHORT, 300000000000000L, "300T"}, 123 {FORMAT_EN_US_SHORT, 3000000000000000L, "3000T"}, 124 // Negatives 125 {FORMAT_EN_US_SHORT, -3000L, "-3K"}, 126 {FORMAT_EN_US_SHORT, -30000L, "-30K"}, 127 {FORMAT_EN_US_SHORT, -300000L, "-300K"}, 128 {FORMAT_EN_US_SHORT, -3000000L, "-3M"}, 129 {FORMAT_EN_US_SHORT, -30000000L, "-30M"}, 130 {FORMAT_EN_US_SHORT, -300000000L, "-300M"}, 131 {FORMAT_EN_US_SHORT, -3000000000L, "-3B"}, 132 {FORMAT_EN_US_SHORT, -30000000000L, "-30B"}, 133 {FORMAT_EN_US_SHORT, -300000000000L, "-300B"}, 134 {FORMAT_EN_US_SHORT, -3000000000000L, "-3T"}, 135 {FORMAT_EN_US_SHORT, -30000000000000L, "-30T"}, 136 {FORMAT_EN_US_SHORT, -300000000000000L, "-300T"}, 137 {FORMAT_EN_US_SHORT, -3000000000000000L, "-3000T"}, 138 // Double 139 {FORMAT_EN_US_SHORT, 3000.0, "3K"}, 140 {FORMAT_EN_US_SHORT, 30000.0, "30K"}, 141 {FORMAT_EN_US_SHORT, 300000.0, "300K"}, 142 {FORMAT_EN_US_SHORT, 3000000.0, "3M"}, 143 {FORMAT_EN_US_SHORT, 30000000.0, "30M"}, 144 {FORMAT_EN_US_SHORT, 300000000.0, "300M"}, 145 {FORMAT_EN_US_SHORT, 3000000000.0, "3B"}, 146 {FORMAT_EN_US_SHORT, 30000000000.0, "30B"}, 147 {FORMAT_EN_US_SHORT, 300000000000.0, "300B"}, 148 {FORMAT_EN_US_SHORT, 3000000000000.0, "3T"}, 149 {FORMAT_EN_US_SHORT, 30000000000000.0, "30T"}, 150 {FORMAT_EN_US_SHORT, 300000000000000.0, "300T"}, 151 {FORMAT_EN_US_SHORT, 3000000000000000.0, "3000T"}, 152 // Negatives 153 {FORMAT_EN_US_SHORT, -3000.0, "-3K"}, 154 {FORMAT_EN_US_SHORT, -30000.0, "-30K"}, 155 {FORMAT_EN_US_SHORT, -300000.0, "-300K"}, 156 {FORMAT_EN_US_SHORT, -3000000.0, "-3M"}, 157 {FORMAT_EN_US_SHORT, -30000000.0, "-30M"}, 158 {FORMAT_EN_US_SHORT, -300000000.0, "-300M"}, 159 {FORMAT_EN_US_SHORT, -3000000000.0, "-3B"}, 160 {FORMAT_EN_US_SHORT, -30000000000.0, "-30B"}, 161 {FORMAT_EN_US_SHORT, -300000000000.0, "-300B"}, 162 {FORMAT_EN_US_SHORT, -3000000000000.0, "-3T"}, 163 {FORMAT_EN_US_SHORT, -30000000000000.0, "-30T"}, 164 {FORMAT_EN_US_SHORT, -300000000000000.0, "-300T"}, 165 {FORMAT_EN_US_SHORT, -3000000000000000.0, "-3000T"}, 166 // BigInteger 167 {FORMAT_EN_US_SHORT, new BigInteger("12345678901234567890"), 168 "12345679T"}, 169 {FORMAT_EN_US_SHORT, new BigInteger("-12345678901234567890"), 170 "-12345679T"}, 171 //BigDecimal 172 {FORMAT_EN_US_SHORT, new BigDecimal("12345678901234567890.89"), 173 "12345679T"}, 174 {FORMAT_EN_US_SHORT, new BigDecimal("-12345678901234567890.89"), 175 "-12345679T"}, 176 {FORMAT_EN_US_SHORT, new BigDecimal("12345678901234567890123466767.89"), 177 "12345678901234568T"}, 178 {FORMAT_EN_US_SHORT, new BigDecimal( 179 "12345678901234567890878732267863209.89"), 180 "12345678901234567890879T"}, 181 // number as exponent 182 {FORMAT_EN_US_SHORT, 9.78313E+3, "10K"}, 183 // Less than 1000 no suffix 184 {FORMAT_EN_LONG, 999, "999"}, 185 // Round the value and then format 186 {FORMAT_EN_LONG, 999.99, "1 thousand"}, 187 // 10 thousand 188 {FORMAT_EN_LONG, 99000, "99 thousand"}, 189 // Long path 190 {FORMAT_EN_LONG, 330000, "330 thousand"}, 191 // Double path 192 {FORMAT_EN_LONG, 3000.90, "3 thousand"}, 193 // BigInteger path 194 {FORMAT_EN_LONG, new BigInteger("12345678901234567890"), 195 "12345679 trillion"}, 196 //BigDecimal path 197 {FORMAT_EN_LONG, new BigDecimal("12345678901234567890.89"), 198 "12345679 trillion"}, 199 // Less than 1000 no suffix 200 {FORMAT_HI_IN_LONG, -999, "-999"}, 201 // Round the value with 0 fraction digits and format it 202 {FORMAT_HI_IN_LONG, -999.99, "-1 \u0939\u091C\u093C\u093E\u0930"}, 203 // 10 thousand 204 {FORMAT_HI_IN_LONG, 99000, "99 \u0939\u091C\u093C\u093E\u0930"}, 205 // Long path 206 {FORMAT_HI_IN_LONG, 330000, "3 \u0932\u093E\u0916"}, 207 // Double path 208 {FORMAT_HI_IN_LONG, 3000.90, "3 \u0939\u091C\u093C\u093E\u0930"}, 209 // BigInteger path 210 {FORMAT_HI_IN_LONG, new BigInteger("12345678901234567890"), 211 "123456789 \u0916\u0930\u092C"}, 212 // BigDecimal path 213 {FORMAT_HI_IN_LONG, new BigDecimal("12345678901234567890.89"), 214 "123456789 \u0916\u0930\u092C"}, 215 // 1000 does not have any suffix in "ja" locale 216 {FORMAT_JA_JP_SHORT, -999.99, "-1,000"}, 217 // 0-9999 does not have any suffix 218 {FORMAT_JA_JP_SHORT, 9999, "9,999"}, 219 // 99000/10000 => 9.9\u4E07 rounded to 10\u4E07 220 {FORMAT_JA_JP_SHORT, 99000, "10\u4E07"}, 221 // Negative 222 {FORMAT_JA_JP_SHORT, -99000, "-10\u4E07"}, 223 // Long path 224 {FORMAT_JA_JP_SHORT, 330000, "33\u4E07"}, 225 // Double path 226 {FORMAT_JA_JP_SHORT, 3000.90, "3,001"}, 227 // BigInteger path 228 {FORMAT_JA_JP_SHORT, new BigInteger("12345678901234567890"), 229 "12345679\u5146"}, 230 // BigDecimal path 231 {FORMAT_JA_JP_SHORT, new BigDecimal("12345678901234567890.89"), 232 "12345679\u5146"}, 233 // less than 1000 no suffix 234 {FORMAT_IT_SHORT, 499, "499"}, 235 // Boundary number 236 {FORMAT_IT_SHORT, 1000, "1.000"}, 237 // Long path 238 {FORMAT_IT_SHORT, 3000000L, "3\u00a0Mln"}, 239 // Double path 240 {FORMAT_IT_SHORT, 3000000.0, "3\u00a0Mln"}, 241 // BigInteger path 242 {FORMAT_IT_SHORT, new BigInteger("12345678901234567890"), 243 "12345679\u00a0Bln"}, 244 // BigDecimal path 245 {FORMAT_IT_SHORT, new BigDecimal("12345678901234567890.89"), 246 "12345679\u00a0Bln"}, 247 {FORMAT_CA_LONG, 999, "999"}, 248 {FORMAT_CA_LONG, 999.99, "1 miler"}, 249 {FORMAT_CA_LONG, 99000, "99 milers"}, 250 {FORMAT_CA_LONG, 330000, "330 milers"}, 251 {FORMAT_CA_LONG, 3000.90, "3 miler"}, 252 {FORMAT_CA_LONG, 1000000, "1 mili\u00f3"}, 253 {FORMAT_CA_LONG, new BigInteger("12345678901234567890"), 254 "12345679 bilions"}, 255 {FORMAT_CA_LONG, new BigDecimal("12345678901234567890.89"), 256 "12345679 bilions"}, 257 {FORMAT_AS_LONG, 5000.0, "\u09eb \u09b9\u09be\u099c\u09be\u09f0"}, 258 {FORMAT_AS_LONG, 50000.0, "\u09eb\u09e6 \u09b9\u09be\u099c\u09be\u09f0"}, 259 {FORMAT_AS_LONG, 500000.0, "\u09eb \u09b2\u09be\u0996"}, 260 {FORMAT_AS_LONG, 5000000.0, "\u09eb \u09a8\u09bf\u09af\u09c1\u09a4"}, 261 {FORMAT_AS_LONG, 50000000.0, "\u09eb\u09e6 \u09a8\u09bf\u09af\u09c1\u09a4"}, 262 {FORMAT_AS_LONG, 500000000.0, "\u09eb\u09e6\u09e6 \u09a8\u09bf\u09af\u09c1\u09a4"}, 263 {FORMAT_AS_LONG, 5000000000.0, "\u09eb \u09b6\u09a4 \u0995\u09cb\u099f\u09bf"}, 264 {FORMAT_AS_LONG, 50000000000.0, "\u09eb\u09e6 \u09b6\u09a4 \u0995\u09cb\u099f\u09bf"}, 265 {FORMAT_AS_LONG, 500000000000.0, "\u09eb\u09e6\u09e6 \u09b6\u09a4 \u0995\u09cb\u099f\u09bf"}, 266 {FORMAT_AS_LONG, 5000000000000.0, "\u09eb \u09b6\u09a4 \u09aa\u09f0\u09be\u09f0\u09cd\u09a6\u09cd\u09a7"}, 267 {FORMAT_AS_LONG, 50000000000000.0, "\u09eb\u09e6 \u09b6\u09a4 \u09aa\u09f0\u09be\u09f0\u09cd\u09a6\u09cd\u09a7"}, 268 {FORMAT_AS_LONG, 500000000000000.0, "\u09eb\u09e6\u09e6 \u09b6\u09a4 \u09aa\u09f0\u09be\u09f0\u09cd\u09a6\u09cd\u09a7"}, 269 {FORMAT_AS_LONG, 5000000000000000.0, "\u09eb\u09e6\u09e6\u09e6 \u09b6\u09a4 \u09aa\u09f0\u09be\u09f0\u09cd\u09a6\u09cd\u09a7"}, 270 {FORMAT_AS_LONG, new BigInteger("12345678901234567890"), 271 "\u09e7\u09e8\u09e9\u09ea\u09eb\u09ec\u09ed\u09ef \u09b6\u09a4 \u09aa\u09f0\u09be\u09f0\u09cd\u09a6\u09cd\u09a7"}, 272 {FORMAT_AS_LONG, new BigDecimal("12345678901234567890123466767.89"), 273 "\u09e7\u09e8\u09e9\u09ea\u09eb\u09ec\u09ed\u09ee\u09ef\u09e6\u09e7\u09e8\u09e9\u09ea\u09eb\u09ec\u09ee \u09b6\u09a4 \u09aa\u09f0\u09be\u09f0\u09cd\u09a6\u09cd\u09a7"}, 274 {FORMAT_BRX_SHORT, 999, "999"}, 275 {FORMAT_BRX_SHORT, 999.99, "1K"}, 276 {FORMAT_BRX_SHORT, 99000, "99K"}, 277 {FORMAT_BRX_SHORT, 330000, "330K"}, 278 {FORMAT_BRX_SHORT, 3000.90, "3K"}, 279 {FORMAT_BRX_SHORT, 1000000, "1M"}, 280 {FORMAT_BRX_SHORT, new BigInteger("12345678901234567890"), 281 "12345679T"}, 282 {FORMAT_BRX_SHORT, new BigDecimal("12345678901234567890.89"), 283 "12345679T"}, 284 // Less than 1000 no suffix 285 {FORMAT_SW_LONG, 499, "499"}, 286 // Boundary number 287 {FORMAT_SW_LONG, 1000, "elfu 1"}, 288 // Long path 289 {FORMAT_SW_LONG, 3000000L, "milioni 3"}, 290 // Long path, negative 291 {FORMAT_SW_LONG, -3000000L, "milioni -3"}, 292 // Double path 293 {FORMAT_SW_LONG, 3000000.0, "milioni 3"}, 294 // Double path, negative 295 {FORMAT_SW_LONG, -3000000.0, "milioni -3"}, 296 // BigInteger path 297 {FORMAT_SW_LONG, new BigInteger("12345678901234567890"), 298 "trilioni 12345679"}, 299 // BigDecimal path 300 {FORMAT_SW_LONG, new BigDecimal("12345678901234567890.89"), 301 "trilioni 12345679"}, 302 // Positives 303 // No compact form 304 {FORMAT_SE_SHORT, 999, "999"}, 305 // Long 306 {FORMAT_SE_SHORT, 8000000L, "8\u00a0mn"}, 307 // Double 308 {FORMAT_SE_SHORT, 8000.98, "8\u00a0dt"}, 309 // Big integer 310 {FORMAT_SE_SHORT, new BigInteger("12345678901234567890"), "12345679\u00a0bn"}, 311 // Big decimal 312 {FORMAT_SE_SHORT, new BigDecimal("12345678901234567890.98"), "12345679\u00a0bn"}, 313 // Negatives 314 // No compact form 315 {FORMAT_SE_SHORT, -999, "\u2212999"}, 316 // Long 317 {FORMAT_SE_SHORT, -8000000L, "\u22128\u00a0mn"}, 318 // Double 319 {FORMAT_SE_SHORT, -8000.98, "\u22128\u00a0dt"}, 320 // BigInteger 321 {FORMAT_SE_SHORT, new BigInteger("-12345678901234567890"), "\u221212345679\u00a0bn"}, 322 // BigDecimal 323 {FORMAT_SE_SHORT, new BigDecimal("-12345678901234567890.98"), "\u221212345679\u00a0bn"},}; 324 } 325 326 @DataProvider(name = "parse") 327 Object[][] compactParseData() { 328 return new Object[][]{ 329 // compact number format instance, string to parse, parsed number, return type 330 {FORMAT_DZ_LONG, "\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2" 331 + "\u0F42 \u0F21", 1000L, Long.class}, 332 {FORMAT_DZ_LONG, "-\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2" 333 + "\u0F42 \u0F23", -3000L, Long.class}, 334 {FORMAT_DZ_LONG, "\u0F51\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62" 335 + "\u0F0B\u0F66\u0F0B\u0F61\u0F0B \u0F21" 336 + "\u0F22\u0F23\u0F24\u0F25\u0F27", 1.23457E19, Double.class}, 337 {FORMAT_DZ_LONG, "-\u0F51\u0F74\u0F44\u0F0B\u0F55\u0FB1\u0F74\u0F62" 338 + "\u0F0B\u0F66\u0F0B\u0F61\u0F0B \u0F21" 339 + "\u0F22\u0F23\u0F24\u0F25\u0F27", -1.23457E19, Double.class}, 340 {FORMAT_EN_US_SHORT, "-0.0", -0.0, Double.class}, 341 {FORMAT_EN_US_SHORT, "-0", -0.0, Double.class}, 342 {FORMAT_EN_US_SHORT, "0", 0L, Long.class}, 343 {FORMAT_EN_US_SHORT, "499", 499L, Long.class}, 344 {FORMAT_EN_US_SHORT, "-499", -499L, Long.class}, 345 {FORMAT_EN_US_SHORT, "499.89", 499.89, Double.class}, 346 {FORMAT_EN_US_SHORT, "-499.89", -499.89, Double.class}, 347 {FORMAT_EN_US_SHORT, "1K", 1000L, Long.class}, 348 {FORMAT_EN_US_SHORT, "-1K", -1000L, Long.class}, 349 {FORMAT_EN_US_SHORT, "3K", 3000L, Long.class}, 350 {FORMAT_EN_US_SHORT, "17K", 17000L, Long.class}, 351 {FORMAT_EN_US_SHORT, "-17K", -17000L, Long.class}, 352 {FORMAT_EN_US_SHORT, "-3K", -3000L, Long.class}, 353 {FORMAT_EN_US_SHORT, "12345678901234567890", 1.2345678901234567E19, Double.class}, 354 {FORMAT_EN_US_SHORT, "12345679T", 1.2345679E19, Double.class}, 355 {FORMAT_EN_US_SHORT, "-12345679T", -1.2345679E19, Double.class}, 356 {FORMAT_EN_US_SHORT, "599.01K", 599010L, Long.class}, 357 {FORMAT_EN_US_SHORT, "-599.01K", -599010L, Long.class}, 358 {FORMAT_EN_US_SHORT, "599444444.90T", 5.994444449E20, Double.class}, 359 {FORMAT_EN_US_SHORT, "-599444444.90T", -5.994444449E20, Double.class}, 360 {FORMAT_EN_US_SHORT, "123456789012345.5678K", 123456789012345568L, Long.class}, 361 {FORMAT_EN_US_SHORT, "17.000K", 17000L, Long.class}, 362 {FORMAT_EN_US_SHORT, "123.56678K", 123566.78000, Double.class}, 363 {FORMAT_EN_US_SHORT, "-123.56678K", -123566.78000, Double.class}, 364 {FORMAT_EN_LONG, "999", 999L, Long.class}, 365 {FORMAT_EN_LONG, "1 thousand", 1000L, Long.class}, 366 {FORMAT_EN_LONG, "3 thousand", 3000L, Long.class}, 367 {FORMAT_EN_LONG, "12345679 trillion", 1.2345679E19, Double.class}, 368 {FORMAT_HI_IN_LONG, "999", 999L, Long.class}, 369 {FORMAT_HI_IN_LONG, "-999", -999L, Long.class}, 370 {FORMAT_HI_IN_LONG, "1 \u0939\u091C\u093C\u093E\u0930", 1000L, Long.class}, 371 {FORMAT_HI_IN_LONG, "-1 \u0939\u091C\u093C\u093E\u0930", -1000L, Long.class}, 372 {FORMAT_HI_IN_LONG, "3 \u0939\u091C\u093C\u093E\u0930", 3000L, Long.class}, 373 {FORMAT_HI_IN_LONG, "12345679 \u0916\u0930\u092C", 1234567900000000000L, Long.class}, 374 {FORMAT_HI_IN_LONG, "-12345679 \u0916\u0930\u092C", -1234567900000000000L, Long.class}, 375 {FORMAT_JA_JP_SHORT, "-99", -99L, Long.class}, 376 {FORMAT_JA_JP_SHORT, "1\u4E07", 10000L, Long.class}, 377 {FORMAT_JA_JP_SHORT, "30\u4E07", 300000L, Long.class}, 378 {FORMAT_JA_JP_SHORT, "-30\u4E07", -300000L, Long.class}, 379 {FORMAT_JA_JP_SHORT, "12345679\u5146", 1.2345679E19, Double.class}, 380 {FORMAT_JA_JP_SHORT, "-12345679\u5146", -1.2345679E19, Double.class}, 381 {FORMAT_IT_SHORT, "-99", -99L, Long.class}, 382 {FORMAT_IT_SHORT, "1\u00a0Mln", 1000000L, Long.class}, 383 {FORMAT_IT_SHORT, "30\u00a0Mln", 30000000L, Long.class}, 384 {FORMAT_IT_SHORT, "-30\u00a0Mln", -30000000L, Long.class}, 385 {FORMAT_IT_SHORT, "12345679\u00a0Bln", 1.2345679E19, Double.class}, 386 {FORMAT_IT_SHORT, "-12345679\u00a0Bln", -1.2345679E19, Double.class}, 387 {FORMAT_SW_LONG, "-0.0", -0.0, Double.class}, 388 {FORMAT_SW_LONG, "499", 499L, Long.class}, 389 {FORMAT_SW_LONG, "elfu 1", 1000L, Long.class}, 390 {FORMAT_SW_LONG, "elfu 3", 3000L, Long.class}, 391 {FORMAT_SW_LONG, "elfu 17", 17000L, Long.class}, 392 {FORMAT_SW_LONG, "elfu -3", -3000L, Long.class}, 393 {FORMAT_SW_LONG, "499", 499L, Long.class}, 394 {FORMAT_SW_LONG, "-499", -499L, Long.class}, 395 {FORMAT_SW_LONG, "elfu 1", 1000L, Long.class}, 396 {FORMAT_SW_LONG, "elfu 3", 3000L, Long.class}, 397 {FORMAT_SW_LONG, "elfu -3", -3000L, Long.class}, 398 {FORMAT_SW_LONG, "elfu 17", 17000L, Long.class}, 399 {FORMAT_SW_LONG, "trilioni 12345679", 1.2345679E19, Double.class}, 400 {FORMAT_SW_LONG, "trilioni -12345679", -1.2345679E19, Double.class}, 401 {FORMAT_SW_LONG, "elfu 599.01", 599010L, Long.class}, 402 {FORMAT_SW_LONG, "elfu -599.01", -599010L, Long.class}, 403 {FORMAT_SE_SHORT, "999", 999L, Long.class}, 404 {FORMAT_SE_SHORT, "8\u00a0mn", 8000000L, Long.class}, 405 {FORMAT_SE_SHORT, "8\u00a0dt", 8000L, Long.class}, 406 {FORMAT_SE_SHORT, "12345679\u00a0bn", 1.2345679E19, Double.class}, 407 {FORMAT_SE_SHORT, "12345679,89\u00a0bn", 1.2345679890000001E19, Double.class}, 408 {FORMAT_SE_SHORT, "\u2212999", -999L, Long.class}, 409 {FORMAT_SE_SHORT, "\u22128\u00a0mn", -8000000L, Long.class}, 410 {FORMAT_SE_SHORT, "\u22128\u00a0dt", -8000L, Long.class}, 411 {FORMAT_SE_SHORT, "\u221212345679\u00a0bn", -1.2345679E19, Double.class}, 412 {FORMAT_SE_SHORT, "\u221212345679,89\u00a0bn", -1.2345679890000001E19, Double.class},}; 413 } 414 415 @DataProvider(name = "exceptionParse") 416 Object[][] exceptionParseData() { 417 return new Object[][]{ 418 // compact number instance, string to parse, null (no o/p; must throws exception) 419 // no number 420 {FORMAT_DZ_LONG, "\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2" 421 + "\u0F42", null}, 422 // Invalid prefix 423 {FORMAT_DZ_LONG, "-\u0F66\u0F9F\u0F7C\u0F44,\u0F0B\u0F55\u0FB2" 424 + "\u0F42 \u0F23", null}, 425 // Invalid prefix for en_US 426 {FORMAT_EN_US_SHORT, "K12,347", null}, 427 // Invalid prefix for ja_JP 428 {FORMAT_JA_JP_SHORT, "\u4E071", null}, 429 // Localized minus sign should be used 430 {FORMAT_SE_SHORT, "-8\u00a0mn", null},}; 431 } 432 433 @DataProvider(name = "invalidParse") 434 Object[][] invalidParseData() { 435 return new Object[][]{ 436 // compact number instance, string to parse, parsed number 437 // Prefix and suffix do not match 438 {FORMAT_DZ_LONG, "\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2" 439 + "\u0F42 \u0F21 KM", 1000L}, 440 // Exponents are unparseable 441 {FORMAT_EN_US_SHORT, "-1.05E4K", -1.05}, 442 // Default instance does not allow grouping 443 {FORMAT_EN_US_SHORT, "12,347", 12L}, 444 // Take partial suffix "K" as 1000 for en_US_SHORT patterns 445 {FORMAT_EN_US_SHORT, "12KM", 12000L}, 446 // Invalid suffix 447 {FORMAT_HI_IN_LONG, "-1 \u00a0\u0915.", -1L},}; 448 } 449 450 @DataProvider(name = "fieldPosition") 451 Object[][] formatFieldPositionData() { 452 return new Object[][]{ 453 //compact number instance, number to format, field, start position, end position, formatted string 454 {FORMAT_DZ_LONG, -3500, NumberFormat.Field.SIGN, 0, 1, "-\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2\u0F42 \u0F24"}, 455 {FORMAT_DZ_LONG, 3500, NumberFormat.Field.INTEGER, 9, 10, "\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2\u0F42 \u0F24"}, 456 {FORMAT_DZ_LONG, -3500, NumberFormat.Field.INTEGER, 10, 11, "-\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2\u0F42 \u0F24"}, 457 {FORMAT_DZ_LONG, 999, NumberFormat.Field.INTEGER, 0, 3, "\u0F29\u0F29\u0F29"}, 458 {FORMAT_DZ_LONG, -999, NumberFormat.Field.INTEGER, 1, 4, "-\u0F29\u0F29\u0F29"}, 459 {FORMAT_DZ_LONG, 3500, NumberFormat.Field.PREFIX, 0, 9, "\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2\u0F42 \u0F24"}, 460 {FORMAT_DZ_LONG, -3500, NumberFormat.Field.PREFIX, 0, 10, "-\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2\u0F42 \u0F24"}, 461 {FORMAT_DZ_LONG, 999, NumberFormat.Field.PREFIX, 0, 0, "\u0F29\u0F29\u0F29"}, 462 {FORMAT_EN_US_SHORT, -3500, NumberFormat.Field.SIGN, 0, 1, "-4K"}, 463 {FORMAT_EN_US_SHORT, 3500, NumberFormat.Field.INTEGER, 0, 1, "4K"}, 464 {FORMAT_EN_US_SHORT, 14900000067L, NumberFormat.Field.INTEGER, 0, 2, "15B"}, 465 {FORMAT_EN_US_SHORT, -1000, NumberFormat.Field.PREFIX, 0, 1, "-1K"}, 466 {FORMAT_EN_US_SHORT, 3500, NumberFormat.Field.SUFFIX, 1, 2, "4K"}, 467 {FORMAT_EN_US_SHORT, 14900000067L, NumberFormat.Field.SUFFIX, 2, 3, "15B"}, 468 {FORMAT_EN_LONG, 3500, NumberFormat.Field.INTEGER, 0, 1, "4 thousand"}, 469 {FORMAT_EN_LONG, 14900000067L, NumberFormat.Field.INTEGER, 0, 2, "15 billion"}, 470 {FORMAT_EN_LONG, 3500, NumberFormat.Field.SUFFIX, 1, 10, "4 thousand"}, 471 {FORMAT_EN_LONG, 14900000067L, NumberFormat.Field.SUFFIX, 2, 10, "15 billion"}, 472 {FORMAT_JA_JP_SHORT, 14900000067L, NumberFormat.Field.INTEGER, 0, 3, "149\u5104"}, 473 {FORMAT_JA_JP_SHORT, -999.99, NumberFormat.Field.INTEGER, 1, 6, "-1,000"}, 474 {FORMAT_JA_JP_SHORT, 14900000067L, NumberFormat.Field.SUFFIX, 3, 4, "149\u5104"}, 475 {FORMAT_JA_JP_SHORT, -999.99, NumberFormat.Field.SUFFIX, 0, 0, "-1,000"}, 476 {FORMAT_JA_JP_SHORT, -999.99, NumberFormat.Field.SIGN, 0, 1, "-1,000"}, 477 {FORMAT_HI_IN_LONG, -14900000067L, NumberFormat.Field.SIGN, 0, 1, 478 "-15 \u0905\u0930\u092C"}, 479 {FORMAT_HI_IN_LONG, 3500, NumberFormat.Field.INTEGER, 0, 1, 480 "4 \u0939\u091C\u093C\u093E\u0930"}, 481 {FORMAT_HI_IN_LONG, 14900000067L, NumberFormat.Field.INTEGER, 0, 2, 482 "15 \u0905\u0930\u092C"}, 483 {FORMAT_HI_IN_LONG, 3500, NumberFormat.Field.SUFFIX, 1, 7, 484 "4 \u0939\u091C\u093C\u093E\u0930"}, 485 {FORMAT_HI_IN_LONG, 14900000067L, NumberFormat.Field.SUFFIX, 2, 6, 486 "15 \u0905\u0930\u092C"}, 487 {FORMAT_SE_SHORT, 8000000L, NumberFormat.Field.SUFFIX, 1, 4, "8\u00a0mn"}, 488 {FORMAT_SE_SHORT, 8000.98, NumberFormat.Field.SUFFIX, 1, 4, "8\u00a0dt"}, 489 {FORMAT_SE_SHORT, new BigInteger("12345678901234567890"), NumberFormat.Field.SUFFIX, 8, 11, "12345679\u00a0bn"}, 490 {FORMAT_SE_SHORT, new BigDecimal("12345678901234567890.98"), NumberFormat.Field.SUFFIX, 8, 11, "12345679\u00a0bn"}, 491 {FORMAT_SE_SHORT, -8000000L, NumberFormat.Field.INTEGER, 1, 2, "\u22128\u00a0mn"}, 492 {FORMAT_SE_SHORT, -8000.98, NumberFormat.Field.SIGN, 0, 1, "\u22128\u00a0dt"}, 493 {FORMAT_SE_SHORT, new BigDecimal("-48982865901234567890.98"), NumberFormat.Field.INTEGER, 1, 9, "\u221248982866\u00a0bn"},}; 494 } 495 496 @DataProvider(name = "varParsePosition") 497 Object[][] varParsePosition() { 498 return new Object[][]{ 499 // compact number instance, parse string, parsed number, 500 // start position, end position, error index 501 {FORMAT_DZ_LONG, "\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2" 502 + "\u0F42 \u0F21 KM", 1000L, 0, 10, -1}, 503 // Invalid prefix returns null 504 {FORMAT_DZ_LONG, "Number is: -\u0F66\u0F9F\u0F7C\u0F44,\u0F0B\u0F55\u0FB2" 505 + "\u0F42 \u0F23", null, 11, 11, 11}, 506 // Returns null 507 {FORMAT_DZ_LONG, "\u0F66\u0F9F\u0F7C\u0F44\u0F0B\u0F55\u0FB2" 508 + "\u0F42", null, 0, 0, 0}, 509 {FORMAT_EN_US_SHORT, "Exponent: -1.05E4K", -1.05, 10, 15, -1}, 510 // Default instance does not allow grouping 511 {FORMAT_EN_US_SHORT, "12,347", 12L, 0, 2, -1}, 512 // Invalid suffix "KM" for en_US_SHORT patterns 513 {FORMAT_EN_US_SHORT, "12KM", 12000L, 0, 3, -1}, 514 // Invalid suffix 515 {FORMAT_HI_IN_LONG, "-1 \u00a0\u0915.", -1L, 0, 2, -1}, 516 {FORMAT_EN_LONG, "Number is: 12345679 trillion", 517 1.2345679E19, 11, 28, -1}, 518 {FORMAT_EN_LONG, "Number is: -12345679 trillion", 519 -1.2345679E19, 11, 29, -1}, 520 {FORMAT_EN_LONG, "parse 12 thousand and four", 12000L, 6, 17, -1},}; 521 } 522 523 @Test 524 public void testInstanceCreation() { 525 Stream.of(NumberFormat.getAvailableLocales()).forEach(l -> NumberFormat 526 .getCompactNumberInstance(l, NumberFormat.Style.SHORT).format(10000)); 527 Stream.of(NumberFormat.getAvailableLocales()).forEach(l -> NumberFormat 528 .getCompactNumberInstance(l, NumberFormat.Style.LONG).format(10000)); 529 } 530 531 @Test(dataProvider = "format") 532 public void testFormat(NumberFormat cnf, Object number, 533 String expected) { 534 CompactFormatAndParseHelper.testFormat(cnf, number, expected); 535 } 536 537 @Test(dataProvider = "parse") 538 public void testParse(NumberFormat cnf, String parseString, 539 Number expected, Class<? extends Number> returnType) throws ParseException { 540 CompactFormatAndParseHelper.testParse(cnf, parseString, expected, null, returnType); 541 } 542 543 @Test(dataProvider = "parse") 544 public void testParsePosition(NumberFormat cnf, String parseString, 545 Number expected, Class<? extends Number> returnType) throws ParseException { 546 ParsePosition pos = new ParsePosition(0); 547 CompactFormatAndParseHelper.testParse(cnf, parseString, expected, pos, returnType); 548 assertEquals(pos.getIndex(), parseString.length()); 549 assertEquals(pos.getErrorIndex(), -1); 550 } 551 552 @Test(dataProvider = "varParsePosition") 553 public void testVarParsePosition(NumberFormat cnf, String parseString, 554 Number expected, int startPosition, int indexPosition, 555 int errPosition) throws ParseException { 556 ParsePosition pos = new ParsePosition(startPosition); 557 CompactFormatAndParseHelper.testParse(cnf, parseString, expected, pos, null); 558 assertEquals(pos.getIndex(), indexPosition); 559 assertEquals(pos.getErrorIndex(), errPosition); 560 } 561 562 @Test(dataProvider = "exceptionParse", expectedExceptions = ParseException.class) 563 public void throwsParseException(NumberFormat cnf, String parseString, 564 Number expected) throws ParseException { 565 CompactFormatAndParseHelper.testParse(cnf, parseString, expected, null, null); 566 } 567 568 @Test(dataProvider = "invalidParse") 569 public void testInvalidParse(NumberFormat cnf, String parseString, 570 Number expected) throws ParseException { 571 CompactFormatAndParseHelper.testParse(cnf, parseString, expected, null, null); 572 } 573 574 @Test(dataProvider = "fieldPosition") 575 public void testFormatWithFieldPosition(NumberFormat nf, 576 Object number, Format.Field field, int posStartExpected, 577 int posEndExpected, String expected) { 578 FieldPosition pos = new FieldPosition(field); 579 StringBuffer buf = new StringBuffer(); 580 StringBuffer result = nf.format(number, buf, pos); 581 assertEquals(result.toString(), expected, "Incorrect formatting of the number '" 582 + number + "'"); 583 assertEquals(pos.getBeginIndex(), posStartExpected, "Incorrect start position" 584 + " while formatting the number '" + number + "', for the field " + field); 585 assertEquals(pos.getEndIndex(), posEndExpected, "Incorrect end position" 586 + " while formatting the number '" + number + "', for the field " + field); 587 } 588 589 }