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 CompactNumberTest
  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 CompactNumberTest {
  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             // big integer
 321             {FORMAT_SE_SHORT, new BigInteger("-12345678901234567890"), "\u221212345679\u00a0bn"},
 322             // big decimal
 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 retunrs 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         CompactFormatAndParse.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         CompactFormatAndParse.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         CompactFormatAndParse.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         CompactFormatAndParse.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         CompactFormatAndParse.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         CompactFormatAndParse.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 }