1 /*
   2  * Copyright (c) 2018, 2019, 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 import org.testng.Assert;
  25 import org.testng.annotations.DataProvider;
  26 import org.testng.annotations.Test;
  27 
  28 import java.io.IOException;
  29 import java.util.FormatFlagsConversionMismatchException;
  30 import java.util.Formattable;
  31 import java.util.Formatter;
  32 import java.util.IllegalFormatCodePointException;
  33 import java.util.IllegalFormatConversionException;
  34 import java.util.IllegalFormatPrecisionException;
  35 import java.util.Locale;
  36 import java.util.UnknownFormatConversionException;
  37 
  38 /**
  39  * @test
  40  * @bug 8211062
  41  * @summary Various additional tests for javac formatter intrinsics
  42  * @run testng JavacIntrinsicsTest
  43  */
  44 public class JavacIntrinsicsTest {
  45 
  46     @DataProvider(name = "locales")
  47     public Object[][] getLocales() {
  48         return new Object[][]{
  49                 { Locale.US, "123" },
  50                 { new Locale("ar","SA"), "١٢٣"},
  51                 { Locale.forLanguageTag("th-TH-u-nu-thai"), "๑๒๓" }
  52         };
  53     }
  54 
  55     private static final Locale[] locales = { Locale.US, new Locale("ar","SA"), Locale.forLanguageTag("th-TH-u-nu-thai") };
  56 
  57     String format(Formatter formatter, String fmt, Object... args) {
  58         formatter.format(fmt, args);
  59         return formatter.toString();
  60     }
  61 
  62 
  63     String formatIntrinsic(Formatter formatter, String fmt, Object... args) {
  64         JavacIntrinsicsSupport.formatterFormat(formatter, fmt, args);
  65         return formatter.toString();
  66     }
  67 
  68     String stringFormat(String fmt, Object... args) {
  69         return String.format(fmt, args);
  70     }
  71 
  72 
  73     String stringFormatIntrinsic(String fmt, Object... args) {
  74         return JavacIntrinsicsSupport.stringFormat(fmt, args);
  75     }
  76 
  77     @Test
  78     public void illegalFormatStringTest() {
  79         try {
  80             formatIntrinsic(new Formatter(), "%c", Integer.MAX_VALUE);
  81             Assert.fail("expected IllegalFormatCodePointException");
  82         } catch (Exception x) {
  83             Assert.assertEquals(x.getClass(), IllegalFormatCodePointException.class);
  84         }
  85         try {
  86             formatIntrinsic(new Formatter(), "%c", Boolean.TRUE);
  87             Assert.fail("expected IllegalFormatConversionException");
  88         } catch (Exception x) {
  89             Assert.assertEquals(x.getClass(), IllegalFormatConversionException.class);
  90         }
  91         try {
  92             formatIntrinsic(new Formatter(), "%#c");
  93             Assert.fail("expected FormatFlagsConversionMismatchException");
  94         } catch (Exception x) {
  95             Assert.assertEquals(x.getClass(), FormatFlagsConversionMismatchException.class);
  96         }
  97         try {
  98             formatIntrinsic(new Formatter(), "%,c");
  99             Assert.fail("expected FormatFlagsConversionMismatchException");
 100         } catch (Exception x) {
 101             Assert.assertEquals(x.getClass(), FormatFlagsConversionMismatchException.class);
 102         }
 103         try {
 104             formatIntrinsic(new Formatter(), "%(c");
 105             Assert.fail("expected FormatFlagsConversionMismatchException");
 106         } catch (Exception x) {
 107             Assert.assertEquals(x.getClass(), FormatFlagsConversionMismatchException.class);
 108         }
 109         try {
 110             formatIntrinsic(new Formatter(), "%$c");
 111             Assert.fail("expected UnknownFormatConversionException");
 112         } catch (Exception x) {
 113             Assert.assertEquals(x.getClass(), UnknownFormatConversionException.class);
 114         }
 115         try {
 116             formatIntrinsic(new Formatter(), "%.2c");
 117             Assert.fail("expected IllegalFormatPrecisionException");
 118         } catch (Exception x) {
 119             Assert.assertEquals(x.getClass(), IllegalFormatPrecisionException.class);
 120         }
 121         try {
 122             formatIntrinsic(new Formatter(), "%#s", -3);
 123             Assert.fail("expected FormatFlagsConversionMismatchException");
 124         } catch (Exception x) {
 125             Assert.assertEquals(x.getClass(), FormatFlagsConversionMismatchException.class);
 126         }
 127         try {
 128             formatIntrinsic(new Formatter(), "%#d", -3);
 129             Assert.fail("expected FormatFlagsConversionMismatchException");
 130         } catch (Exception x) {
 131             Assert.assertEquals(x.getClass(), FormatFlagsConversionMismatchException.class);
 132         }
 133         try {
 134             formatIntrinsic(new Formatter(), "%#s", (byte) -3);
 135             Assert.fail("expected FormatFlagsConversionMismatchException");
 136         } catch (Exception x) {
 137             Assert.assertEquals(x.getClass(), FormatFlagsConversionMismatchException.class);
 138         }
 139         try {
 140             formatIntrinsic(new Formatter(), "%#d", (byte) -3);
 141             Assert.fail("expected FormatFlagsConversionMismatchException");
 142         } catch (Exception x) {
 143             Assert.assertEquals(x.getClass(), FormatFlagsConversionMismatchException.class);
 144         }
 145     }
 146 
 147     @Test
 148     public void paramTypesTest() {
 149 
 150         Assert.assertEquals(format(new Formatter(), "%s", -3), "-3");
 151         Assert.assertEquals(formatIntrinsic(new Formatter(), "%s", -3), "-3");
 152         Assert.assertEquals(stringFormat("%s", -3), "-3");
 153         Assert.assertEquals(stringFormatIntrinsic("%s", -3), "-3");
 154 
 155         Assert.assertEquals(format(new Formatter(), "%s", (byte) -3), "-3");
 156         Assert.assertEquals(formatIntrinsic(new Formatter(), "%s", (byte) -3), "-3");
 157         Assert.assertEquals(stringFormat("%s", (byte) -3), "-3");
 158         Assert.assertEquals(stringFormatIntrinsic("%s", (byte) -3), "-3");
 159 
 160         Assert.assertEquals(format(new Formatter(), "%s", (short) -3), "-3");
 161         Assert.assertEquals(formatIntrinsic(new Formatter(), "%s", (short) -3), "-3");
 162         Assert.assertEquals(stringFormat("%s", (short) -3), "-3");
 163         Assert.assertEquals(stringFormatIntrinsic("%s", (short) -3), "-3");
 164 
 165         Assert.assertEquals(format(new Formatter(), "%S", -3), "-3");
 166         Assert.assertEquals(formatIntrinsic(new Formatter(), "%S", -3), "-3");
 167         Assert.assertEquals(stringFormat("%S", -3), "-3");
 168         Assert.assertEquals(stringFormatIntrinsic("%S", -3), "-3");
 169 
 170         Assert.assertEquals(format(new Formatter(), "%S", (byte) -3), "-3");
 171         Assert.assertEquals(formatIntrinsic(new Formatter(), "%S", (byte) -3), "-3");
 172         Assert.assertEquals(stringFormat("%S", (byte) -3), "-3");
 173         Assert.assertEquals(stringFormatIntrinsic("%S", (byte) -3), "-3");
 174 
 175         Assert.assertEquals(format(new Formatter(), "%S", (short) -3), "-3");
 176         Assert.assertEquals(formatIntrinsic(new Formatter(), "%S", (short) -3), "-3");
 177         Assert.assertEquals(stringFormat("%S", (short) -3), "-3");
 178         Assert.assertEquals(stringFormatIntrinsic("%S", (short) -3), "-3");
 179 
 180         Assert.assertEquals(format(new Formatter(), "%d", -3), "-3");
 181         Assert.assertEquals(formatIntrinsic(new Formatter(), "%d", -3), "-3");
 182         Assert.assertEquals(stringFormat("%d", -3), "-3");
 183         Assert.assertEquals(stringFormatIntrinsic("%d", -3), "-3");
 184 
 185         Assert.assertEquals(format(new Formatter(), "%d", (byte) -3), "-3");
 186         Assert.assertEquals(formatIntrinsic(new Formatter(), "%d", (byte) -3), "-3");
 187         Assert.assertEquals(stringFormat("%d", (byte) -3), "-3");
 188         Assert.assertEquals(stringFormatIntrinsic("%d", (byte) -3), "-3");
 189 
 190         Assert.assertEquals(format(new Formatter(), "%d", (short) -3), "-3");
 191         Assert.assertEquals(formatIntrinsic(new Formatter(), "%d", (short) -3), "-3");
 192         Assert.assertEquals(stringFormat("%d", (short) -3), "-3");
 193         Assert.assertEquals(stringFormatIntrinsic("%d", (short) -3), "-3");
 194 
 195         Assert.assertEquals(format(new Formatter(), "%x", -3), "fffffffd");
 196         Assert.assertEquals(formatIntrinsic(new Formatter(), "%x", -3), "fffffffd");
 197         Assert.assertEquals(stringFormat("%x", -3), "fffffffd");
 198         Assert.assertEquals(stringFormatIntrinsic("%x", -3), "fffffffd");
 199 
 200         Assert.assertEquals(format(new Formatter(), "%x", (byte) -3), "fd");
 201         Assert.assertEquals(formatIntrinsic(new Formatter(), "%x", (byte) -3), "fd");
 202         Assert.assertEquals(stringFormat("%x", (byte) -3), "fd");
 203         Assert.assertEquals(stringFormatIntrinsic("%x", (byte) -3), "fd");
 204 
 205         Assert.assertEquals(format(new Formatter(), "%x", (short) -3), "fffd");
 206         Assert.assertEquals(formatIntrinsic(new Formatter(), "%x", (short) -3), "fffd");
 207         Assert.assertEquals(stringFormat("%x", (short) -3), "fffd");
 208         Assert.assertEquals(stringFormatIntrinsic("%x", (short) -3), "fffd");
 209 
 210         Assert.assertEquals(format(new Formatter(), "%X", -3), "FFFFFFFD");
 211         Assert.assertEquals(formatIntrinsic(new Formatter(), "%X", -3), "FFFFFFFD");
 212         Assert.assertEquals(stringFormat("%X", -3), "FFFFFFFD");
 213         Assert.assertEquals(stringFormatIntrinsic("%X", -3), "FFFFFFFD");
 214 
 215         Assert.assertEquals(format(new Formatter(), "%X", (byte) -3), "FD");
 216         Assert.assertEquals(formatIntrinsic(new Formatter(), "%X", (byte) -3), "FD");
 217         Assert.assertEquals(stringFormat("%X", (byte) -3), "FD");
 218         Assert.assertEquals(stringFormatIntrinsic("%X", (byte) -3), "FD");
 219 
 220         Assert.assertEquals(format(new Formatter(), "%X", (short) -3), "FFFD");
 221         Assert.assertEquals(formatIntrinsic(new Formatter(), "%X", (short) -3), "FFFD");
 222         Assert.assertEquals(stringFormat("%X", (short) -3), "FFFD");
 223         Assert.assertEquals(stringFormatIntrinsic("%X", (short) -3), "FFFD");
 224 
 225         Assert.assertEquals(format(new Formatter(), "%o", -3), "37777777775");
 226         Assert.assertEquals(formatIntrinsic(new Formatter(), "%o", -3), "37777777775");
 227         Assert.assertEquals(stringFormat("%o", -3), "37777777775");
 228         Assert.assertEquals(stringFormatIntrinsic("%o", -3), "37777777775");
 229 
 230         Assert.assertEquals(format(new Formatter(), "%o", (byte) -3), "375");
 231         Assert.assertEquals(formatIntrinsic(new Formatter(), "%o", (byte) -3), "375");
 232         Assert.assertEquals(stringFormat("%o", (byte) -3), "375");
 233         Assert.assertEquals(stringFormatIntrinsic("%o", (byte) -3), "375");
 234 
 235         Assert.assertEquals(format(new Formatter(), "%o", (short) -3), "177775");
 236         Assert.assertEquals(formatIntrinsic(new Formatter(), "%o", (short) -3), "177775");
 237         Assert.assertEquals(stringFormat("%o", (short) -3), "177775");
 238         Assert.assertEquals(stringFormatIntrinsic("%o", (short) -3), "177775");
 239     }
 240 
 241     // Empty specs test
 242     @Test
 243     public void emptySpecsTest() {
 244         Assert.assertEquals(format(new Formatter(), ""), "");
 245         Assert.assertEquals(formatIntrinsic(new Formatter(), ""), "");
 246         Assert.assertEquals(stringFormat(""), "");
 247         Assert.assertEquals(stringFormatIntrinsic(""), "");
 248     }
 249 
 250     // Locale test
 251     @Test(dataProvider = "locales")
 252     public void localeTest(Locale locale, String expected) {
 253         Locale defLocale = Locale.getDefault();
 254         try {
 255             Locale.setDefault(locale);
 256             Assert.assertEquals(format(new Formatter(), "%d", 123), expected);
 257             Assert.assertEquals(formatIntrinsic(new Formatter(), "%d", 123), expected);
 258             Assert.assertEquals(stringFormat("%d", 123), expected);
 259             Assert.assertEquals(stringFormatIntrinsic("%d", 123), expected);
 260         } finally {
 261             Locale.setDefault(defLocale);
 262         }
 263     }
 264 
 265     // Formattable tests
 266     @Test
 267     public void formattableTest() {
 268         Formatter fmt1 = new Formatter();
 269         try {
 270             format(fmt1, "%s%-#10.5S", "ok", new BrokenFormattable());
 271         } catch (Exception e) {
 272 
 273         }
 274         Formatter fmt2 = new Formatter();
 275         try {
 276             formatIntrinsic(fmt2, "%s%-#10.5S", "ok", new BrokenFormattable());
 277         } catch (Exception e) {
 278 
 279         }
 280         Assert.assertEquals(fmt1.toString(), "ok flags: 7, width: 10, precision: 5");
 281         Assert.assertEquals(fmt2.toString(), "ok flags: 7, width: 10, precision: 5");
 282     }
 283 
 284     // Exception tests
 285     @Test
 286     public void exceptionTest() {
 287         Formatter fmt1 = new Formatter();
 288         try {
 289             format(fmt1, "%s%s", "ok", new BrokenToString());
 290         } catch (Exception e) {
 291 
 292         }
 293         Formatter fmt2 = new Formatter();
 294         try {
 295             formatIntrinsic(fmt2, "%s%s", "ok", new BrokenToString());
 296         } catch (Exception e) {
 297 
 298         }
 299         Assert.assertEquals(fmt1.toString(), "ok");
 300         Assert.assertEquals(fmt2.toString(), "ok");
 301     }
 302 
 303     static class BrokenToString {
 304         @Override
 305         public String toString() {
 306             throw new RuntimeException();
 307         }
 308     }
 309 
 310     static class BrokenFormattable implements Formattable {
 311         @Override
 312         public void formatTo(Formatter formatter, int flags, int width, int precision) {
 313             try {
 314                 formatter.out().append(" flags: " + flags).append(", width: " + width).append(", precision: " + precision);
 315             } catch (IOException x) {
 316                 throw new RuntimeException(x);
 317             }
 318             throw new RuntimeException();
 319         }
 320     }
 321 }