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 rounding of formatted number in compact number formatting
  27  * @run testng/othervm CNFRoundingTest
  28  */
  29 
  30 import java.math.RoundingMode;
  31 import java.text.NumberFormat;
  32 import java.util.Locale;
  33 import static org.testng.Assert.*;
  34 import org.testng.annotations.DataProvider;
  35 import org.testng.annotations.Test;
  36 
  37 public class CNFRoundingTest {
  38 
  39     @DataProvider(name = "roundingData")
  40     Object[][] roundingData() {
  41         return new Object[][]{
  42             {5500, "6K", "6K", "5K", "6K", "5K", "6K", "5K"},
  43             {2500, "2K", "3K", "2K", "3K", "2K", "3K", "2K"},
  44             {1600, "2K", "2K", "2K", "2K", "1K", "2K", "1K"},
  45             {1100, "1K", "1K", "1K", "2K", "1K", "2K", "1K"},
  46             {1000, "1K", "1K", "1K", "1K", "1K", "1K", "1K"},
  47             {-1000, "-1K", "-1K", "-1K", "-1K", "-1K", "-1K", "-1K"},
  48             {-1100, "-1K", "-1K", "-1K", "-2K", "-1K", "-1K", "-2K"},
  49             {-1600, "-2K", "-2K", "-2K", "-2K", "-1K", "-1K", "-2K"},
  50             {-2500, "-2K", "-3K", "-2K", "-3K", "-2K", "-2K", "-3K"},
  51             {-5500, "-6K", "-6K", "-5K", "-6K", "-5K", "-5K", "-6K"},
  52             {5501, "6K", "6K", "6K", "6K", "5K", "6K", "5K"},
  53             {-5501, "-6K", "-6K", "-6K", "-6K", "-5K", "-5K", "-6K"},
  54             {1001, "1K", "1K", "1K", "2K", "1K", "2K", "1K"},
  55             {-1001, "-1K", "-1K", "-1K", "-2K", "-1K", "-1K", "-2K"},
  56             {4501, "5K", "5K", "5K", "5K", "4K", "5K", "4K"},
  57             {-4501, "-5K", "-5K", "-5K", "-5K", "-4K", "-4K", "-5K"},
  58             {4500, "4K", "5K", "4K", "5K", "4K", "5K", "4K"},
  59             {-4500, "-4K", "-5K", "-4K", "-5K", "-4K", "-4K", "-5K"},};
  60     }
  61 
  62     @DataProvider(name = "roundingFract")
  63     Object[][] roundingFract() {
  64         return new Object[][]{
  65             {5550, "5.5K", "5.5K", "5.5K", "5.6K", "5.5K", "5.6K", "5.5K"},
  66             {2550, "2.5K", "2.5K", "2.5K", "2.6K", "2.5K", "2.6K", "2.5K"},
  67             {1660, "1.7K", "1.7K", "1.7K", "1.7K", "1.6K", "1.7K", "1.6K"},
  68             {1110, "1.1K", "1.1K", "1.1K", "1.2K", "1.1K", "1.2K", "1.1K"},
  69             {1000, "1.0K", "1.0K", "1.0K", "1.0K", "1.0K", "1.0K", "1.0K"},
  70             {-1000, "-1.0K", "-1.0K", "-1.0K", "-1.0K", "-1.0K", "-1.0K", "-1.0K"},
  71             {-1110, "-1.1K", "-1.1K", "-1.1K", "-1.2K", "-1.1K", "-1.1K", "-1.2K"},
  72             {-1660, "-1.7K", "-1.7K", "-1.7K", "-1.7K", "-1.6K", "-1.6K", "-1.7K"},
  73             {-2550, "-2.5K", "-2.5K", "-2.5K", "-2.6K", "-2.5K", "-2.5K", "-2.6K"},
  74             {-5550, "-5.5K", "-5.5K", "-5.5K", "-5.6K", "-5.5K", "-5.5K", "-5.6K"},
  75             {5551, "5.6K", "5.6K", "5.6K", "5.6K", "5.5K", "5.6K", "5.5K"},
  76             {-5551, "-5.6K", "-5.6K", "-5.6K", "-5.6K", "-5.5K", "-5.5K", "-5.6K"},
  77             {1001, "1.0K", "1.0K", "1.0K", "1.1K", "1.0K", "1.1K", "1.0K"},
  78             {-1001, "-1.0K", "-1.0K", "-1.0K", "-1.1K", "-1.0K", "-1.0K", "-1.1K"},
  79             {4551, "4.6K", "4.6K", "4.6K", "4.6K", "4.5K", "4.6K", "4.5K"},
  80             {-4551, "-4.6K", "-4.6K", "-4.6K", "-4.6K", "-4.5K", "-4.5K", "-4.6K"},
  81             {4500, "4.5K", "4.5K", "4.5K", "4.5K", "4.5K", "4.5K", "4.5K"},
  82             {-4500, "-4.5K", "-4.5K", "-4.5K", "-4.5K", "-4.5K", "-4.5K", "-4.5K"},};
  83     }
  84 
  85     @DataProvider(name = "rounding2Fract")
  86     Object[][] rounding2Fract() {
  87         return new Object[][]{
  88             {1115, "1.11K", "1.11K", "1.11K"},
  89             {1125, "1.12K", "1.13K", "1.12K"},
  90             {1135, "1.14K", "1.14K", "1.14K"},
  91             {3115, "3.12K", "3.12K", "3.12K"},
  92             {3125, "3.12K", "3.13K", "3.12K"},
  93             {3135, "3.13K", "3.13K", "3.13K"},
  94             {6865, "6.87K", "6.87K", "6.87K"},
  95             {6875, "6.88K", "6.88K", "6.87K"},
  96             {6885, "6.88K", "6.88K", "6.88K"},
  97             {3124, "3.12K", "3.12K", "3.12K"},
  98             {3126, "3.13K", "3.13K", "3.13K"},
  99             {3128, "3.13K", "3.13K", "3.13K"},
 100             {6864, "6.86K", "6.86K", "6.86K"},
 101             {6865, "6.87K", "6.87K", "6.87K"},
 102             {6868, "6.87K", "6.87K", "6.87K"},
 103             {4685, "4.68K", "4.68K", "4.68K"},
 104             {4687, "4.69K", "4.69K", "4.69K"},
 105             {4686, "4.69K", "4.69K", "4.69K"},};
 106     }
 107 
 108     @Test(expectedExceptions = NullPointerException.class)
 109     public void testNullMode() {
 110         NumberFormat fmt = NumberFormat
 111                 .getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
 112         fmt.setRoundingMode(null);
 113     }
 114 
 115     @Test(dataProvider = "roundingData")
 116     public void testRounding(Object number, String halfEven, String halfUp,
 117             String halfDown, String up, String down, String ceiling, String floor) {
 118         testHalfEven(number, halfEven, 0);
 119         testHalfUp(number, halfUp, 0);
 120         testHalfDown(number, halfDown, 0);
 121         testUp(number, up, 0);
 122         testDown(number, down, 0);
 123         testCeiling(number, ceiling, 0);
 124         testFloor(number, floor, 0);
 125     }
 126 
 127     @Test(dataProvider = "roundingFract")
 128     public void testRoundingFract(Object number, String halfEven, String halfUp,
 129             String halfDown, String up, String down, String ceiling, String floor) {
 130         testHalfEven(number, halfEven, 1);
 131         testHalfUp(number, halfUp, 1);
 132         testHalfDown(number, halfDown, 1);
 133         testUp(number, up, 1);
 134         testDown(number, down, 1);
 135         testCeiling(number, ceiling, 1);
 136         testFloor(number, floor, 1);
 137     }
 138 
 139     @Test(dataProvider = "rounding2Fract")
 140     public void testRounding2Fract(Object number, String halfEven, String halfUp,
 141             String halfDown) {
 142         testHalfEven(number, halfEven, 2);
 143         testHalfUp(number, halfUp, 2);
 144         testHalfDown(number, halfDown, 2);
 145     }
 146 
 147     private void testHalfEven(Object number, String halfEven, int fraction) {
 148         NumberFormat fmtHalfEven = NumberFormat
 149                 .getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
 150 
 151         if (fmtHalfEven.getRoundingMode() != RoundingMode.HALF_EVEN) {
 152             throw new RuntimeException("[FAILED: Default rounding should be"
 153                     + " HALF_EVEN]");
 154         }
 155         fmtHalfEven.setMinimumFractionDigits(fraction);
 156         String result = fmtHalfEven.format(number);
 157         if (!result.equals(halfEven)) {
 158             assertEquals(result, halfEven, "FAILED: Incorrect formatting"
 159                     + " of number " + number + " using rounding mode: "
 160                     + RoundingMode.HALF_EVEN);
 161         }
 162     }
 163 
 164     private void testHalfUp(Object number, String halfUp, int fraction) {
 165         NumberFormat fmtHalfUp = NumberFormat
 166                 .getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
 167         fmtHalfUp.setRoundingMode(RoundingMode.HALF_UP);
 168         if (fmtHalfUp.getRoundingMode() != RoundingMode.HALF_UP) {
 169             throw new RuntimeException("[FAILED: RoundingMode set is not"
 170                     + " returned by getRoundingMode]");
 171         }
 172         fmtHalfUp.setMinimumFractionDigits(fraction);
 173         String result = fmtHalfUp.format(number);
 174         if (!result.equals(halfUp)) {
 175             assertEquals(result, halfUp, "FAILED: Incorrect formatting"
 176                     + " of number " + number + " using rounding mode: "
 177                     + RoundingMode.HALF_UP);
 178         }
 179     }
 180 
 181     private void testHalfDown(Object number, String halfDown, int fraction) {
 182         NumberFormat fmtHalfDown = NumberFormat
 183                 .getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
 184 
 185         fmtHalfDown.setRoundingMode(RoundingMode.HALF_DOWN);
 186         if (fmtHalfDown.getRoundingMode() != RoundingMode.HALF_DOWN) {
 187             throw new RuntimeException("[FAILED: RoundingMode set is not"
 188                     + " returned by getRoundingMode]");
 189         }
 190         fmtHalfDown.setMinimumFractionDigits(fraction);
 191         String result = fmtHalfDown.format(number);
 192         if (!result.equals(halfDown)) {
 193             assertEquals(result, halfDown, "FAILED: Incorrect formatting"
 194                     + " of number " + number + " using rounding mode: "
 195                     + RoundingMode.HALF_DOWN);
 196         }
 197     }
 198 
 199     private void testUp(Object number, String up, int fraction) {
 200         NumberFormat fmtUp = NumberFormat
 201                 .getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
 202         fmtUp.setRoundingMode(RoundingMode.UP);
 203         if (fmtUp.getRoundingMode() != RoundingMode.UP) {
 204             throw new RuntimeException("[FAILED: RoundingMode set is not"
 205                     + " returned by getRoundingMode]");
 206         }
 207         fmtUp.setMinimumFractionDigits(fraction);
 208         String result = fmtUp.format(number);
 209         if (!result.equals(up)) {
 210             assertEquals(result, up, "FAILED: Incorrect formatting"
 211                     + " of number " + number + " using rounding mode: "
 212                     + RoundingMode.UP);
 213         }
 214     }
 215 
 216     private void testDown(Object number, String down, int fraction) {
 217         NumberFormat fmtDown = NumberFormat
 218                 .getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
 219 
 220         fmtDown.setRoundingMode(RoundingMode.DOWN);
 221         if (fmtDown.getRoundingMode() != RoundingMode.DOWN) {
 222             throw new RuntimeException("[FAILED: RoundingMode set is not"
 223                     + " returned by getRoundingMode]");
 224         }
 225         fmtDown.setMinimumFractionDigits(fraction);
 226         String result = fmtDown.format(number);
 227         if (!result.equals(down)) {
 228             assertEquals(result, down, "FAILED: Incorrect formatting"
 229                     + " of number " + number + " using rounding mode: "
 230                     + RoundingMode.DOWN);
 231         }
 232     }
 233 
 234     private void testCeiling(Object number, String ceiling, int fraction) {
 235         NumberFormat fmtCeiling = NumberFormat
 236                 .getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
 237         fmtCeiling.setRoundingMode(RoundingMode.CEILING);
 238         if (fmtCeiling.getRoundingMode() != RoundingMode.CEILING) {
 239             throw new RuntimeException("[FAILED: RoundingMode set is not"
 240                     + " returned by getRoundingMode]");
 241         }
 242 
 243         fmtCeiling.setMinimumFractionDigits(fraction);
 244         String result = fmtCeiling.format(number);
 245         if (!result.equals(ceiling)) {
 246             assertEquals(result, ceiling, "FAILED: Incorrect formatting"
 247                     + " of number " + number + " using rounding mode: "
 248                     + RoundingMode.CEILING);
 249         }
 250     }
 251 
 252     private void testFloor(Object number, String floor, int fraction) {
 253         NumberFormat fmtFloor = NumberFormat
 254                 .getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
 255         fmtFloor.setRoundingMode(RoundingMode.FLOOR);
 256         if (fmtFloor.getRoundingMode() != RoundingMode.FLOOR) {
 257             throw new RuntimeException("[FAILED: RoundingMode set is not"
 258                     + " returned by getRoundingMode]");
 259         }
 260         fmtFloor.setMinimumFractionDigits(fraction);
 261         String result = fmtFloor.format(number);
 262         if (!result.equals(floor)) {
 263             assertEquals(result, floor, "FAILED: Incorrect formatting"
 264                     + " of number " + number + " using rounding mode: "
 265                     + RoundingMode.FLOOR);
 266         }
 267     }
 268 
 269 }