/* * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 4031438 4058973 4074764 4094906 4104976 4105380 4106659 4106660 4106661 * 4111739 4112104 4113018 4114739 4114743 4116444 4118592 4118594 4120552 * 4142938 4169959 4232154 4293229 8187551 * @summary Regression tests for MessageFormat and associated classes * @library /java/text/testlib * @run main MessageRegression */ /* (C) Copyright Taligent, Inc. 1996 - All Rights Reserved (C) Copyright IBM Corp. 1996 - All Rights Reserved The original version of this source code and documentation is copyrighted and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are provided under terms of a License Agreement between Taligent and Sun. This technology is protected by multiple US and International patents. This notice and attribution to Taligent may not be removed. Taligent is a registered trademark of Taligent, Inc. */ import java.text.*; import java.util.*; import java.io.IOException; import java.io.FileOutputStream; import java.io.FileInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.Serializable; public class MessageRegression extends IntlTest { public static void main(String[] args) throws Exception { new MessageRegression().run(args); } /* @bug 4074764 * Null exception when formatting pattern with MessageFormat * with no parameters. */ public void Test4074764() { String[] pattern = {"Message without param", "Message with param:{0}", "Longer Message with param {0}"}; //difference between the two param strings are that //in the first one, the param position is within the //length of the string without param while it is not so //in the other case. MessageFormat messageFormatter = new MessageFormat(""); try { //Apply pattern with param and print the result messageFormatter.applyPattern(pattern[1]); Object[] params = {new String("BUG"), new Date()}; String tempBuffer = messageFormatter.format(params); if (!tempBuffer.equals("Message with param:BUG")) errln("MessageFormat with one param test failed."); logln("Formatted with one extra param : " + tempBuffer); //Apply pattern without param and print the result messageFormatter.applyPattern(pattern[0]); tempBuffer = messageFormatter.format(null); if (!tempBuffer.equals("Message without param")) errln("MessageFormat with no param test failed."); logln("Formatted with no params : " + tempBuffer); tempBuffer = messageFormatter.format(params); if (!tempBuffer.equals("Message without param")) errln("Formatted with arguments > subsitution failed. result = " + tempBuffer.toString()); logln("Formatted with extra params : " + tempBuffer); //This statement gives an exception while formatting... //If we use pattern[1] for the message with param, //we get an NullPointerException in MessageFormat.java(617) //If we use pattern[2] for the message with param, //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614) //Both are due to maxOffset not being reset to -1 //in applyPattern() when the pattern does not //contain any param. } catch (Exception foo) { errln("Exception when formatting with no params."); } } /* @bug 4058973 * MessageFormat.toPattern has weird rounding behavior. */ public void Test4058973() { MessageFormat fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}"); String pat = fmt.toPattern(); if (!pat.equals("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}")) { errln("MessageFormat.toPattern failed"); } } /* @bug 4031438 * More robust message formats. */ public void Test4031438() { Locale locale = Locale.getDefault(); if (!TestUtils.usesAsciiDigits(locale)) { logln("Skipping this test because locale is " + locale); return; } String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}."; String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'."; MessageFormat messageFormatter = new MessageFormat(""); try { logln("Apply with pattern : " + pattern1); messageFormatter.applyPattern(pattern1); Object[] params = {7}; String tempBuffer = messageFormatter.format(params); if (!tempBuffer.equals("Impossible {1} has occurred -- status code is 7 and message is {2}.")) errln("Tests arguments < substitution failed. Formatted text=" + "<" + tempBuffer + ">"); logln("Formatted with 7 : " + tempBuffer); ParsePosition status = new ParsePosition(0); Object[] objs = messageFormatter.parse(tempBuffer, status); if (objs[params.length] != null) errln("Parse failed with more than expected arguments"); for (int i = 0; i < objs.length; i++) { if (objs[i] != null && !objs[i].toString().equals(params[i].toString())) { errln("Parse failed on object " + objs[i] + " at index : " + i); } } tempBuffer = messageFormatter.format(null); if (!tempBuffer.equals("Impossible {1} has occurred -- status code is {0} and message is {2}.")) errln("Tests with no arguments failed"); logln("Formatted with null : " + tempBuffer); logln("Apply with pattern : " + pattern2); messageFormatter.applyPattern(pattern2); tempBuffer = messageFormatter.format(params); if (!tempBuffer.equals("Double ' Quotes 7 test and quoted {1} test plus other {2} stuff.")) errln("quote format test (w/ params) failed."); logln("Formatted with params : " + tempBuffer); tempBuffer = messageFormatter.format(null); if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff.")) errln("quote format test (w/ null) failed."); logln("Formatted with null : " + tempBuffer); logln("toPattern : " + messageFormatter.toPattern()); } catch (Exception foo) { errln("Exception when formatting in bug 4031438. "+foo.getMessage()); } } public void Test4052223() { ParsePosition pos = new ParsePosition(0); if (pos.getErrorIndex() != -1) { errln("ParsePosition.getErrorIndex initialization failed."); } MessageFormat fmt = new MessageFormat("There are {0} apples growing on the {1} tree."); String str = new String("There is one apple growing on the peach tree."); Object[] objs = fmt.parse(str, pos); logln("unparsable string , should fail at " + pos.getErrorIndex()); if (pos.getErrorIndex() == -1) errln("Bug 4052223 failed : parsing string " + str); pos.setErrorIndex(4); if (pos.getErrorIndex() != 4) errln("setErrorIndex failed, got " + pos.getErrorIndex() + " instead of 4"); ChoiceFormat f = new ChoiceFormat( "-1#are negative|0#are no or fraction|1#is one|1.0"); Object[] objs1 = null; Object[] objs2 = {}; Object[] objs3 = {null}; try { logln("pattern: \"" + mf.toPattern() + "\""); log("format(null) : "); logln("\"" + mf.format(objs1) + "\""); log("format({}) : "); logln("\"" + mf.format(objs2) + "\""); log("format({null}) :"); logln("\"" + mf.format(objs3) + "\""); } catch (Exception e) { errln("Exception thrown for null argument tests."); } } /* @bug 4113018 * MessageFormat.applyPattern works wrong with illegal patterns. */ public void Test4113018() { String originalPattern = "initial pattern"; MessageFormat mf = new MessageFormat(originalPattern); String illegalPattern = "format: {0, xxxYYY}"; logln("pattern before: \"" + mf.toPattern() + "\""); logln("illegal pattern: \"" + illegalPattern + "\""); try { mf.applyPattern(illegalPattern); errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern); } catch (IllegalArgumentException e) { if (!originalPattern.equals(mf.toPattern())) errln("pattern after: \"" + mf.toPattern() + "\""); } } /* @bug 4106661 * ChoiceFormat is silent about the pattern usage in javadoc. */ public void Test4106661() { ChoiceFormat fmt = new ChoiceFormat( "-1#are negative| 0#are no or fraction | 1#is one |1.0 " + out + "; want \"" + DATA[i+1+j] + '"'); } String pat = cf.toPattern(); String pat2 = new ChoiceFormat(pat).toPattern(); if (!pat.equals(pat2)) errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); else logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"'); } catch (IllegalArgumentException e) { errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e); } } } /** * @bug 4112104 * MessageFormat.equals(null) throws a NullPointerException. The JLS states * that it should return false. */ public void Test4112104() { MessageFormat format = new MessageFormat(""); try { // This should NOT throw an exception if (format.equals(null)) { // It also should return false errln("MessageFormat.equals(null) returns false"); } } catch (NullPointerException e) { errln("MessageFormat.equals(null) throws " + e); } } /** * @bug 4169959 * MessageFormat does not format null objects. CANNOT REPRODUCE THIS BUG. */ public void Test4169959() { // This works logln(MessageFormat.format( "This will {0}", "work")); // This fails logln(MessageFormat.format( "This will {0}", new Object[]{ null } ) ); } public void test4232154() { boolean gotException = false; try { MessageFormat format = new MessageFormat("The date is {0:date}"); } catch (Exception e) { gotException = true; if (!(e instanceof IllegalArgumentException)) { throw new RuntimeException("got wrong exception type"); } if ("argument number too large at ".equals(e.getMessage())) { throw new RuntimeException("got wrong exception message"); } } if (!gotException) { throw new RuntimeException("didn't get exception for invalid input"); } } public void test4293229() { MessageFormat format = new MessageFormat("'''{'0}'' '''{0}'''"); Object[] args = { null }; String expected = "'{0}' '{0}'"; String result = format.format(args); if (!result.equals(expected)) { throw new RuntimeException("wrong format result - expected \"" + expected + "\", got \"" + result + "\""); } } /** * @bug 8187551 * test MessageFormat.setFormat() method to throw AIOOBE on invalid index. */ public void test8187551() { //invalid cases ("pattern", "invalid format element index") String[][] invalidCases = {{"The disk \"{1}\" contains {0}.", "2"}, {"The disk \"{1}\" contains {0}.", "9"}, {"On {1}, there are {0} and {2} folders", "3"}}; //invalid cases (must throw exception) Arrays.stream(invalidCases).forEach(entry -> messageSetFormat(entry[0], Integer.valueOf(entry[1]))); } // test MessageFormat.setFormat() method for the given pattern and // format element index private void messageSetFormat(String pattern, int elemIndex) { MessageFormat form = new MessageFormat(pattern); double[] fileLimits = {0, 1, 2}; String[] filePart = {"no files", "one file", "{0,number} files"}; ChoiceFormat fileForm = new ChoiceFormat(fileLimits, filePart); boolean AIOOBEThrown = false; try { form.setFormat(elemIndex, fileForm); } catch (ArrayIndexOutOfBoundsException ex) { AIOOBEThrown = true; } if (!AIOOBEThrown) { throw new RuntimeException("[FAILED: Must throw" + " ArrayIndexOutOfBoundsException for" + " invalid index " + elemIndex + " used in" + " MessageFormat.setFormat(index, format)]"); } } }