Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/text/Format/MessageFormat/MessageRegression.java
47209 views
/*1* Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 4031438 4058973 4074764 4094906 4104976 4105380 4106659 4106660 410666126* 4111739 4112104 4113018 4114739 4114743 4116444 4118592 4118594 412055227* 4142938 4169959 4232154 429322928* @summary Regression tests for MessageFormat and associated classes29* @library /java/text/testlib30*/31/*32(C) Copyright Taligent, Inc. 1996 - All Rights Reserved33(C) Copyright IBM Corp. 1996 - All Rights Reserved3435The original version of this source code and documentation is copyrighted and36owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are37provided under terms of a License Agreement between Taligent and Sun. This38technology is protected by multiple US and International patents. This notice and39attribution to Taligent may not be removed.40Taligent is a registered trademark of Taligent, Inc.41*/4243import java.text.*;44import java.util.*;45import java.io.IOException;46import java.io.FileOutputStream;47import java.io.FileInputStream;48import java.io.ByteArrayInputStream;49import java.io.ByteArrayOutputStream;50import java.io.ObjectOutputStream;51import java.io.ObjectInputStream;52import java.io.Serializable;5354public class MessageRegression extends IntlTest {5556public static void main(String[] args) throws Exception {57new MessageRegression().run(args);58}5960/* @bug 407476461* Null exception when formatting pattern with MessageFormat62* with no parameters.63*/64public void Test4074764() {65String[] pattern = {"Message without param",66"Message with param:{0}",67"Longer Message with param {0}"};68//difference between the two param strings are that69//in the first one, the param position is within the70//length of the string without param while it is not so71//in the other case.7273MessageFormat messageFormatter = new MessageFormat("");7475try {76//Apply pattern with param and print the result77messageFormatter.applyPattern(pattern[1]);78Object[] params = {new String("BUG"), new Date()};79String tempBuffer = messageFormatter.format(params);80if (!tempBuffer.equals("Message with param:BUG"))81errln("MessageFormat with one param test failed.");82logln("Formatted with one extra param : " + tempBuffer);8384//Apply pattern without param and print the result85messageFormatter.applyPattern(pattern[0]);86tempBuffer = messageFormatter.format(null);87if (!tempBuffer.equals("Message without param"))88errln("MessageFormat with no param test failed.");89logln("Formatted with no params : " + tempBuffer);9091tempBuffer = messageFormatter.format(params);92if (!tempBuffer.equals("Message without param"))93errln("Formatted with arguments > subsitution failed. result = " + tempBuffer.toString());94logln("Formatted with extra params : " + tempBuffer);95//This statement gives an exception while formatting...96//If we use pattern[1] for the message with param,97//we get an NullPointerException in MessageFormat.java(617)98//If we use pattern[2] for the message with param,99//we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614)100//Both are due to maxOffset not being reset to -1101//in applyPattern() when the pattern does not102//contain any param.103} catch (Exception foo) {104errln("Exception when formatting with no params.");105}106}107108/* @bug 4058973109* MessageFormat.toPattern has weird rounding behavior.110*/111public void Test4058973() {112113MessageFormat fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}");114String pat = fmt.toPattern();115if (!pat.equals("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}")) {116errln("MessageFormat.toPattern failed");117}118}119/* @bug 4031438120* More robust message formats.121*/122public void Test4031438() {123String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}.";124String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'.";125126// If the current locale is hi_IN, skip this test case.127if (Locale.getDefault().equals(new Locale("hi", "IN"))) {128return;129}130131MessageFormat messageFormatter = new MessageFormat("");132133try {134logln("Apply with pattern : " + pattern1);135messageFormatter.applyPattern(pattern1);136Object[] params = {new Integer(7)};137String tempBuffer = messageFormatter.format(params);138if (!tempBuffer.equals("Impossible {1} has occurred -- status code is 7 and message is {2}."))139errln("Tests arguments < substitution failed. Formatted text=" +140"<" + tempBuffer + ">");141logln("Formatted with 7 : " + tempBuffer);142ParsePosition status = new ParsePosition(0);143Object[] objs = messageFormatter.parse(tempBuffer, status);144if (objs[params.length] != null)145errln("Parse failed with more than expected arguments");146for (int i = 0; i < objs.length; i++) {147if (objs[i] != null && !objs[i].toString().equals(params[i].toString())) {148errln("Parse failed on object " + objs[i] + " at index : " + i);149}150}151tempBuffer = messageFormatter.format(null);152if (!tempBuffer.equals("Impossible {1} has occurred -- status code is {0} and message is {2}."))153errln("Tests with no arguments failed");154logln("Formatted with null : " + tempBuffer);155logln("Apply with pattern : " + pattern2);156messageFormatter.applyPattern(pattern2);157tempBuffer = messageFormatter.format(params);158if (!tempBuffer.equals("Double ' Quotes 7 test and quoted {1} test plus other {2} stuff."))159errln("quote format test (w/ params) failed.");160logln("Formatted with params : " + tempBuffer);161tempBuffer = messageFormatter.format(null);162if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff."))163errln("quote format test (w/ null) failed.");164logln("Formatted with null : " + tempBuffer);165logln("toPattern : " + messageFormatter.toPattern());166} catch (Exception foo) {167errln("Exception when formatting in bug 4031438. "+foo.getMessage());168}169}170public void Test4052223()171{172ParsePosition pos = new ParsePosition(0);173if (pos.getErrorIndex() != -1) {174errln("ParsePosition.getErrorIndex initialization failed.");175}176MessageFormat fmt = new MessageFormat("There are {0} apples growing on the {1} tree.");177String str = new String("There is one apple growing on the peach tree.");178Object[] objs = fmt.parse(str, pos);179logln("unparsable string , should fail at " + pos.getErrorIndex());180if (pos.getErrorIndex() == -1)181errln("Bug 4052223 failed : parsing string " + str);182pos.setErrorIndex(4);183if (pos.getErrorIndex() != 4)184errln("setErrorIndex failed, got " + pos.getErrorIndex() + " instead of 4");185ChoiceFormat f = new ChoiceFormat(186"-1#are negative|0#are no or fraction|1#is one|1.0<is 1+|2#are two|2<are more than 2.");187pos.setIndex(0); pos.setErrorIndex(-1);188Number obj = f.parse("are negative", pos);189if (pos.getErrorIndex() != -1 && obj.doubleValue() == -1.0)190errln("Parse with \"are negative\" failed, at " + pos.getErrorIndex());191pos.setIndex(0); pos.setErrorIndex(-1);192obj = f.parse("are no or fraction ", pos);193if (pos.getErrorIndex() != -1 && obj.doubleValue() == 0.0)194errln("Parse with \"are no or fraction\" failed, at " + pos.getErrorIndex());195pos.setIndex(0); pos.setErrorIndex(-1);196obj = f.parse("go postal", pos);197if (pos.getErrorIndex() == -1 && !Double.isNaN(obj.doubleValue()))198errln("Parse with \"go postal\" failed, at " + pos.getErrorIndex());199}200/* @bug 4104976201* ChoiceFormat.equals(null) throws NullPointerException202*/203public void Test4104976()204{205double[] limits = {1, 20};206String[] formats = {"xyz", "abc"};207ChoiceFormat cf = new ChoiceFormat(limits, formats);208try {209log("Compares to null is always false, returned : ");210logln(cf.equals(null) ? "TRUE" : "FALSE");211} catch (Exception foo) {212errln("ChoiceFormat.equals(null) throws exception.");213}214}215/* @bug 4106659216* ChoiceFormat.ctor(double[], String[]) doesn't check217* whether lengths of input arrays are equal.218*/219public void Test4106659()220{221double[] limits = {1, 2, 3};222String[] formats = {"one", "two"};223ChoiceFormat cf = null;224try {225cf = new ChoiceFormat(limits, formats);226} catch (Exception foo) {227logln("ChoiceFormat constructor should check for the array lengths");228cf = null;229}230if (cf != null) errln(cf.format(5));231}232233/* @bug 4106660234* ChoiceFormat.ctor(double[], String[]) allows unordered double array.235* This is not a bug, added javadoc to emphasize the use of limit236* array must be in ascending order.237*/238public void Test4106660()239{240double[] limits = {3, 1, 2};241String[] formats = {"Three", "One", "Two"};242ChoiceFormat cf = new ChoiceFormat(limits, formats);243double d = 5.0;244String str = cf.format(d);245if (!str.equals("Two"))246errln("format(" + d + ") = " + cf.format(d));247}248249/* @bug 4111739250* MessageFormat is incorrectly serialized/deserialized.251*/252public void Test4111739()253{254MessageFormat format1 = null;255MessageFormat format2 = null;256ObjectOutputStream ostream = null;257ByteArrayOutputStream baos = null;258ObjectInputStream istream = null;259260try {261baos = new ByteArrayOutputStream();262ostream = new ObjectOutputStream(baos);263} catch(IOException e) {264errln("Unexpected exception : " + e.getMessage());265return;266}267268try {269format1 = new MessageFormat("pattern{0}");270ostream.writeObject(format1);271ostream.flush();272273byte bytes[] = baos.toByteArray();274275istream = new ObjectInputStream(new ByteArrayInputStream(bytes));276format2 = (MessageFormat)istream.readObject();277} catch(Exception e) {278errln("Unexpected exception : " + e.getMessage());279}280281if (!format1.equals(format2)) {282errln("MessageFormats before and after serialization are not" +283" equal\nformat1 = " + format1 + "(" + format1.toPattern() + ")\nformat2 = " +284format2 + "(" + format2.toPattern() + ")");285} else {286logln("Serialization for MessageFormat is OK.");287}288}289/* @bug 4114743290* MessageFormat.applyPattern allows illegal patterns.291*/292public void Test4114743()293{294String originalPattern = "initial pattern";295MessageFormat mf = new MessageFormat(originalPattern);296try {297String illegalPattern = "ab { '}' de";298mf.applyPattern(illegalPattern);299errln("illegal pattern: \"" + illegalPattern + "\"");300} catch (IllegalArgumentException foo) {301if (!originalPattern.equals(mf.toPattern()))302errln("pattern after: \"" + mf.toPattern() + "\"");303}304}305306/* @bug 4116444307* MessageFormat.parse has different behavior in case of null.308*/309public void Test4116444()310{311String[] patterns = {"", "one", "{0,date,short}"};312MessageFormat mf = new MessageFormat("");313314for (int i = 0; i < patterns.length; i++) {315String pattern = patterns[i];316mf.applyPattern(pattern);317try {318Object[] array = mf.parse(null, new ParsePosition(0));319logln("pattern: \"" + pattern + "\"");320log(" parsedObjects: ");321if (array != null) {322log("{");323for (int j = 0; j < array.length; j++) {324if (array[j] != null)325err("\"" + array[j].toString() + "\"");326else327log("null");328if (j < array.length - 1) log(",");329}330log("}") ;331} else {332log("null");333}334logln("");335} catch (Exception e) {336errln("pattern: \"" + pattern + "\"");337errln(" Exception: " + e.getMessage());338}339}340341}342/* @bug 4114739 (FIX and add javadoc)343* MessageFormat.format has undocumented behavior about empty format objects.344*/345public void Test4114739()346{347348MessageFormat mf = new MessageFormat("<{0}>");349Object[] objs1 = null;350Object[] objs2 = {};351Object[] objs3 = {null};352try {353logln("pattern: \"" + mf.toPattern() + "\"");354log("format(null) : ");355logln("\"" + mf.format(objs1) + "\"");356log("format({}) : ");357logln("\"" + mf.format(objs2) + "\"");358log("format({null}) :");359logln("\"" + mf.format(objs3) + "\"");360} catch (Exception e) {361errln("Exception thrown for null argument tests.");362}363}364365/* @bug 4113018366* MessageFormat.applyPattern works wrong with illegal patterns.367*/368public void Test4113018()369{370String originalPattern = "initial pattern";371MessageFormat mf = new MessageFormat(originalPattern);372String illegalPattern = "format: {0, xxxYYY}";373logln("pattern before: \"" + mf.toPattern() + "\"");374logln("illegal pattern: \"" + illegalPattern + "\"");375try {376mf.applyPattern(illegalPattern);377errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern);378} catch (IllegalArgumentException e) {379if (!originalPattern.equals(mf.toPattern()))380errln("pattern after: \"" + mf.toPattern() + "\"");381}382}383/* @bug 4106661384* ChoiceFormat is silent about the pattern usage in javadoc.385*/386public void Test4106661()387{388ChoiceFormat fmt = new ChoiceFormat(389"-1#are negative| 0#are no or fraction | 1#is one |1.0<is 1+ |2#are two |2<are more than 2.");390logln("Formatter Pattern : " + fmt.toPattern());391392logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));393logln("Format with -1.0 : " + fmt.format(-1.0));394logln("Format with 0 : " + fmt.format(0));395logln("Format with 0.9 : " + fmt.format(0.9));396logln("Format with 1.0 : " + fmt.format(1));397logln("Format with 1.5 : " + fmt.format(1.5));398logln("Format with 2 : " + fmt.format(2));399logln("Format with 2.1 : " + fmt.format(2.1));400logln("Format with NaN : " + fmt.format(Double.NaN));401logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));402}403/* @bug 4094906404* ChoiceFormat should accept \u221E as eq. to INF.405*/406public void Test4094906()407{408ChoiceFormat fmt = new ChoiceFormat(409"-\u221E<are negative|0<are no or fraction|1#is one|1.0<is 1+|\u221E<are many.");410if (!fmt.toPattern().startsWith("-\u221E<are negative|0.0<are no or fraction|1.0#is one|1.0<is 1+|\u221E<are many."))411errln("Formatter Pattern : " + fmt.toPattern());412logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));413logln("Format with -1.0 : " + fmt.format(-1.0));414logln("Format with 0 : " + fmt.format(0));415logln("Format with 0.9 : " + fmt.format(0.9));416logln("Format with 1.0 : " + fmt.format(1));417logln("Format with 1.5 : " + fmt.format(1.5));418logln("Format with 2 : " + fmt.format(2));419logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));420}421422/* @bug 4118592423* MessageFormat.parse fails with ChoiceFormat.424*/425public void Test4118592()426{427MessageFormat mf = new MessageFormat("");428String pattern = "{0,choice,1#YES|2#NO}";429String prefix = "";430for (int i = 0; i < 5; i++) {431String formatted = prefix + "YES";432mf.applyPattern(prefix + pattern);433prefix += "x";434Object[] objs = mf.parse(formatted, new ParsePosition(0));435logln(i + ". pattern :\"" + mf.toPattern() + "\"");436log(" \"" + formatted + "\" parsed as ");437if (objs == null) logln(" null");438else logln(" " + objs[0]);439}440}441/* @bug 4118594442* MessageFormat.parse fails for some patterns.443*/444public void Test4118594()445{446MessageFormat mf = new MessageFormat("{0}, {0}, {0}");447String forParsing = "x, y, z";448Object[] objs = mf.parse(forParsing, new ParsePosition(0));449logln("pattern: \"" + mf.toPattern() + "\"");450logln("text for parsing: \"" + forParsing + "\"");451if (!objs[0].toString().equals("z"))452errln("argument0: \"" + objs[0] + "\"");453mf.setLocale(Locale.US);454mf.applyPattern("{0,number,#.##}, {0,number,#.#}");455Object[] oldobjs = {new Double(3.1415)};456String result = mf.format( oldobjs );457logln("pattern: \"" + mf.toPattern() + "\"");458logln("text for parsing: \"" + result + "\"");459// result now equals "3.14, 3.1"460if (!result.equals("3.14, 3.1"))461errln("result = " + result);462Object[] newobjs = mf.parse(result, new ParsePosition(0));463// newobjs now equals {new Double(3.1)}464if (((Double)newobjs[0]).doubleValue() != 3.1)465errln( "newobjs[0] = " + newobjs[0]);466}467/* @bug 4105380468* When using ChoiceFormat, MessageFormat is not good for I18n.469*/470public void Test4105380()471{472String patternText1 = "The disk \"{1}\" contains {0}.";473String patternText2 = "There are {0} on the disk \"{1}\"";474MessageFormat form1 = new MessageFormat(patternText1);475MessageFormat form2 = new MessageFormat(patternText2);476double[] filelimits = {0,1,2};477String[] filepart = {"no files","one file","{0,number} files"};478ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);479form1.setFormat(1, fileform);480form2.setFormat(0, fileform);481Object[] testArgs = {new Long(12373), "MyDisk"};482logln(form1.format(testArgs));483logln(form2.format(testArgs));484}485/* @bug 4120552486* MessageFormat.parse incorrectly sets errorIndex.487*/488public void Test4120552()489{490MessageFormat mf = new MessageFormat("pattern");491String texts[] = {"pattern", "pat", "1234"};492logln("pattern: \"" + mf.toPattern() + "\"");493for (int i = 0; i < texts.length; i++) {494ParsePosition pp = new ParsePosition(0);495Object[] objs = mf.parse(texts[i], pp);496log(" text for parsing: \"" + texts[i] + "\"");497if (objs == null) {498logln(" (incorrectly formatted string)");499if (pp.getErrorIndex() == -1)500errln("Incorrect error index: " + pp.getErrorIndex());501} else {502logln(" (correctly formatted string)");503}504}505}506507/**508* @bug 4142938509* MessageFormat handles single quotes in pattern wrong.510* This is actually a problem in ChoiceFormat; it doesn't511* understand single quotes.512*/513public void Test4142938() {514String pat = "''Vous'' {0,choice,0#n''|1#}avez s\u00E9lectionne\u00E9 " +515"{0,choice,0#aucun|1#{0}} client{0,choice,0#s|1#|2#s} " +516"personnel{0,choice,0#s|1#|2#s}.";517MessageFormat mf = new MessageFormat(pat);518519String[] PREFIX = {520"'Vous' n'avez s\u00E9lectionne\u00E9 aucun clients personnels.",521"'Vous' avez s\u00E9lectionne\u00E9 ",522"'Vous' avez s\u00E9lectionne\u00E9 "523};524String[] SUFFIX = {525null,526" client personnel.",527" clients personnels."528};529530for (int i=0; i<3; i++) {531String out = mf.format(new Object[]{new Integer(i)});532if (SUFFIX[i] == null) {533if (!out.equals(PREFIX[i]))534errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"");535}536else {537if (!out.startsWith(PREFIX[i]) ||538!out.endsWith(SUFFIX[i]))539errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"...\"" +540SUFFIX[i] + "\"");541}542}543}544545/**546* @bug 4142938547* Test the applyPattern and toPattern handling of single quotes548* by ChoiceFormat. (This is in here because this was a bug reported549* against MessageFormat.) The single quote is used to quote the550* pattern characters '|', '#', '<', and '\u2264'. Two quotes in a row551* is a quote literal.552*/553public void TestChoicePatternQuote() {554String[] DATA = {555// Pattern 0 value 1 value556"0#can''t|1#can", "can't", "can",557"0#'pound(#)=''#'''|1#xyz", "pound(#)='#'", "xyz",558"0#'1<2 | 1\u22641'|1#''", "1<2 | 1\u22641", "'",559};560for (int i=0; i<DATA.length; i+=3) {561try {562ChoiceFormat cf = new ChoiceFormat(DATA[i]);563for (int j=0; j<=1; ++j) {564String out = cf.format(j);565if (!out.equals(DATA[i+1+j]))566errln("Fail: Pattern \"" + DATA[i] + "\" x "+j+" -> " +567out + "; want \"" + DATA[i+1+j] + '"');568}569String pat = cf.toPattern();570String pat2 = new ChoiceFormat(pat).toPattern();571if (!pat.equals(pat2))572errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');573else574logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');575}576catch (IllegalArgumentException e) {577errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e);578}579}580}581582/**583* @bug 4112104584* MessageFormat.equals(null) throws a NullPointerException. The JLS states585* that it should return false.586*/587public void Test4112104() {588MessageFormat format = new MessageFormat("");589try {590// This should NOT throw an exception591if (format.equals(null)) {592// It also should return false593errln("MessageFormat.equals(null) returns false");594}595}596catch (NullPointerException e) {597errln("MessageFormat.equals(null) throws " + e);598}599}600601/**602* @bug 4169959603* MessageFormat does not format null objects. CANNOT REPRODUCE THIS BUG.604*/605public void Test4169959() {606// This works607logln(MessageFormat.format( "This will {0}",608new String[]{"work"} ) );609610// This fails611logln(MessageFormat.format( "This will {0}",612new Object[]{ null } ) );613}614615public void test4232154() {616boolean gotException = false;617try {618MessageFormat format = new MessageFormat("The date is {0:date}");619} catch (Exception e) {620gotException = true;621if (!(e instanceof IllegalArgumentException)) {622throw new RuntimeException("got wrong exception type");623}624if ("argument number too large at ".equals(e.getMessage())) {625throw new RuntimeException("got wrong exception message");626}627}628if (!gotException) {629throw new RuntimeException("didn't get exception for invalid input");630}631}632633public void test4293229() {634MessageFormat format = new MessageFormat("'''{'0}'' '''{0}'''");635Object[] args = { null };636String expected = "'{0}' '{0}'";637String result = format.format(args);638if (!result.equals(expected)) {639throw new RuntimeException("wrong format result - expected \"" +640expected + "\", got \"" + result + "\"");641}642}643}644645646