1 /*
2  * Copyright (c) 1997, 2017, 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 /*
25  * @test
26  * @bug 4031438 4058973 4074764 4094906 4104976 4105380 4106659 4106660 4106661
27  * 4111739 4112104 4113018 4114739 4114743 4116444 4118592 4118594 4120552
28  * 4142938 4169959 4232154 4293229 8187551
29  * @summary Regression tests for MessageFormat and associated classes
30  * @library /java/text/testlib
31  * @run main MessageRegression
32  */
33 /*
34 (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
35 (C) Copyright IBM Corp. 1996 - All Rights Reserved
36 
37   The original version of this source code and documentation is copyrighted and
38 owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
39 provided under terms of a License Agreement between Taligent and Sun. This
40 technology is protected by multiple US and International patents. This notice and
41 attribution to Taligent may not be removed.
42   Taligent is a registered trademark of Taligent, Inc.
43 */
44 
45 package test.java.text.Format.MessageFormat;
46 
47 import java.text.*;
48 import java.util.*;
49 import java.io.IOException;
50 import java.io.FileOutputStream;
51 import java.io.FileInputStream;
52 import java.io.ByteArrayInputStream;
53 import java.io.ByteArrayOutputStream;
54 import java.io.ObjectOutputStream;
55 import java.io.ObjectInputStream;
56 import java.io.Serializable;
57 
58 import test.java.text.testlib.IntlTest;
59 import test.java.text.testlib.TestUtils;
60 
61 public class MessageRegression extends IntlTest {
62 
main(String[] args)63     public static void main(String[] args) throws Exception {
64         new MessageRegression().run(args);
65     }
66 
67     /* @bug 4074764
68      * Null exception when formatting pattern with MessageFormat
69      * with no parameters.
70      */
Test4074764()71     public void Test4074764() {
72         String[] pattern = {"Message without param",
73         "Message with param:{0}",
74         "Longer Message with param {0}"};
75         //difference between the two param strings are that
76         //in the first one, the param position is within the
77         //length of the string without param while it is not so
78         //in the other case.
79 
80         MessageFormat messageFormatter = new MessageFormat("");
81 
82         try {
83             //Apply pattern with param and print the result
84             messageFormatter.applyPattern(pattern[1]);
85             Object[] params = {new String("BUG"), new Date()};
86             String tempBuffer = messageFormatter.format(params);
87             if (!tempBuffer.equals("Message with param:BUG"))
88                 errln("MessageFormat with one param test failed.");
89             logln("Formatted with one extra param : " + tempBuffer);
90 
91             //Apply pattern without param and print the result
92             messageFormatter.applyPattern(pattern[0]);
93             tempBuffer = messageFormatter.format(null);
94             if (!tempBuffer.equals("Message without param"))
95                 errln("MessageFormat with no param test failed.");
96             logln("Formatted with no params : " + tempBuffer);
97 
98              tempBuffer = messageFormatter.format(params);
99              if (!tempBuffer.equals("Message without param"))
100                 errln("Formatted with arguments > subsitution failed. result = " + tempBuffer.toString());
101              logln("Formatted with extra params : " + tempBuffer);
102             //This statement gives an exception while formatting...
103             //If we use pattern[1] for the message with param,
104             //we get an NullPointerException in MessageFormat.java(617)
105             //If we use pattern[2] for the message with param,
106             //we get an StringArrayIndexOutOfBoundsException in MessageFormat.java(614)
107             //Both are due to maxOffset not being reset to -1
108             //in applyPattern() when the pattern does not
109             //contain any param.
110         } catch (Exception foo) {
111             errln("Exception when formatting with no params.");
112         }
113     }
114 
115     /* @bug 4058973
116      * MessageFormat.toPattern has weird rounding behavior.
117      */
Test4058973()118     public void Test4058973() {
119 
120         MessageFormat fmt = new MessageFormat("{0,choice,0#no files|1#one file|1< {0,number,integer} files}");
121         String pat = fmt.toPattern();
122         if (!pat.equals("{0,choice,0.0#no files|1.0#one file|1.0< {0,number,integer} files}")) {
123             errln("MessageFormat.toPattern failed");
124         }
125     }
126     /* @bug 4031438
127      * More robust message formats.
128      */
Test4031438()129     public void Test4031438() {
130         Locale locale = Locale.getDefault();
131         if (!TestUtils.usesAsciiDigits(locale)) {
132             logln("Skipping this test because locale is " + locale);
133             return;
134         }
135 
136         String pattern1 = "Impossible {1} has occurred -- status code is {0} and message is {2}.";
137         String pattern2 = "Double '' Quotes {0} test and quoted '{1}' test plus 'other {2} stuff'.";
138 
139         MessageFormat messageFormatter = new MessageFormat("");
140 
141         try {
142             logln("Apply with pattern : " + pattern1);
143             messageFormatter.applyPattern(pattern1);
144             Object[] params = {7};
145             String tempBuffer = messageFormatter.format(params);
146             if (!tempBuffer.equals("Impossible {1} has occurred -- status code is 7 and message is {2}."))
147                 errln("Tests arguments < substitution failed. Formatted text=" +
148                       "<" + tempBuffer + ">");
149             logln("Formatted with 7 : " + tempBuffer);
150             ParsePosition status = new ParsePosition(0);
151             Object[] objs = messageFormatter.parse(tempBuffer, status);
152             if (objs[params.length] != null)
153                 errln("Parse failed with more than expected arguments");
154             for (int i = 0; i < objs.length; i++) {
155                 if (objs[i] != null && !objs[i].toString().equals(params[i].toString())) {
156                     errln("Parse failed on object " + objs[i] + " at index : " + i);
157                 }
158             }
159             tempBuffer = messageFormatter.format(null);
160             if (!tempBuffer.equals("Impossible {1} has occurred -- status code is {0} and message is {2}."))
161                 errln("Tests with no arguments failed");
162             logln("Formatted with null : " + tempBuffer);
163             logln("Apply with pattern : " + pattern2);
164             messageFormatter.applyPattern(pattern2);
165             tempBuffer = messageFormatter.format(params);
166             if (!tempBuffer.equals("Double ' Quotes 7 test and quoted {1} test plus other {2} stuff."))
167                 errln("quote format test (w/ params) failed.");
168             logln("Formatted with params : " + tempBuffer);
169             tempBuffer = messageFormatter.format(null);
170             if (!tempBuffer.equals("Double ' Quotes {0} test and quoted {1} test plus other {2} stuff."))
171                 errln("quote format test (w/ null) failed.");
172             logln("Formatted with null : " + tempBuffer);
173             logln("toPattern : " + messageFormatter.toPattern());
174         } catch (Exception foo) {
175             errln("Exception when formatting in bug 4031438. "+foo.getMessage());
176         }
177     }
Test4052223()178     public void Test4052223()
179     {
180         ParsePosition pos = new ParsePosition(0);
181         if (pos.getErrorIndex() != -1) {
182             errln("ParsePosition.getErrorIndex initialization failed.");
183         }
184         MessageFormat fmt = new MessageFormat("There are {0} apples growing on the {1} tree.");
185         String str = new String("There is one apple growing on the peach tree.");
186         Object[] objs = fmt.parse(str, pos);
187         logln("unparsable string , should fail at " + pos.getErrorIndex());
188         if (pos.getErrorIndex() == -1)
189             errln("Bug 4052223 failed : parsing string " + str);
190         pos.setErrorIndex(4);
191         if (pos.getErrorIndex() != 4)
192             errln("setErrorIndex failed, got " + pos.getErrorIndex() + " instead of 4");
193         ChoiceFormat f = new ChoiceFormat(
194             "-1#are negative|0#are no or fraction|1#is one|1.0<is 1+|2#are two|2<are more than 2.");
195         pos.setIndex(0); pos.setErrorIndex(-1);
196         Number obj = f.parse("are negative", pos);
197         if (pos.getErrorIndex() != -1 && obj.doubleValue() == -1.0)
198             errln("Parse with \"are negative\" failed, at " + pos.getErrorIndex());
199         pos.setIndex(0); pos.setErrorIndex(-1);
200         obj = f.parse("are no or fraction ", pos);
201         if (pos.getErrorIndex() != -1 && obj.doubleValue() == 0.0)
202             errln("Parse with \"are no or fraction\" failed, at " + pos.getErrorIndex());
203         pos.setIndex(0); pos.setErrorIndex(-1);
204         obj = f.parse("go postal", pos);
205         if (pos.getErrorIndex() == -1 && !Double.isNaN(obj.doubleValue()))
206             errln("Parse with \"go postal\" failed, at " + pos.getErrorIndex());
207     }
208     /* @bug 4104976
209      * ChoiceFormat.equals(null) throws NullPointerException
210      */
Test4104976()211     public void Test4104976()
212     {
213         double[] limits = {1, 20};
214         String[] formats = {"xyz", "abc"};
215         ChoiceFormat cf = new ChoiceFormat(limits, formats);
216         try {
217             log("Compares to null is always false, returned : ");
218             logln(cf.equals(null) ? "TRUE" : "FALSE");
219         } catch (Exception foo) {
220             errln("ChoiceFormat.equals(null) throws exception.");
221         }
222     }
223     /* @bug 4106659
224      * ChoiceFormat.ctor(double[], String[]) doesn't check
225      * whether lengths of input arrays are equal.
226      */
Test4106659()227     public void Test4106659()
228     {
229         double[] limits = {1, 2, 3};
230         String[] formats = {"one", "two"};
231         ChoiceFormat cf = null;
232         try {
233             cf = new ChoiceFormat(limits, formats);
234         } catch (Exception foo) {
235             logln("ChoiceFormat constructor should check for the array lengths");
236             cf = null;
237         }
238         if (cf != null) errln(cf.format(5));
239     }
240 
241     /* @bug 4106660
242      * ChoiceFormat.ctor(double[], String[]) allows unordered double array.
243      * This is not a bug, added javadoc to emphasize the use of limit
244      * array must be in ascending order.
245      */
Test4106660()246     public void Test4106660()
247     {
248         double[] limits = {3, 1, 2};
249         String[] formats = {"Three", "One", "Two"};
250         ChoiceFormat cf = new ChoiceFormat(limits, formats);
251         double d = 5.0;
252         String str = cf.format(d);
253         if (!str.equals("Two"))
254             errln("format(" + d + ") = " + cf.format(d));
255     }
256 
257     /* @bug 4111739
258      * MessageFormat is incorrectly serialized/deserialized.
259      */
Test4111739()260     public void Test4111739()
261     {
262         MessageFormat format1 = null;
263         MessageFormat format2 = null;
264         ObjectOutputStream ostream = null;
265         ByteArrayOutputStream baos = null;
266         ObjectInputStream istream = null;
267 
268         try {
269             baos = new ByteArrayOutputStream();
270             ostream = new ObjectOutputStream(baos);
271         } catch(IOException e) {
272             errln("Unexpected exception : " + e.getMessage());
273             return;
274         }
275 
276         try {
277             format1 = new MessageFormat("pattern{0}");
278             ostream.writeObject(format1);
279             ostream.flush();
280 
281             byte bytes[] = baos.toByteArray();
282 
283             istream = new ObjectInputStream(new ByteArrayInputStream(bytes));
284             format2 = (MessageFormat)istream.readObject();
285         } catch(Exception e) {
286             errln("Unexpected exception : " + e.getMessage());
287         }
288 
289         if (!format1.equals(format2)) {
290             errln("MessageFormats before and after serialization are not" +
291                 " equal\nformat1 = " + format1 + "(" + format1.toPattern() + ")\nformat2 = " +
292                 format2 + "(" + format2.toPattern() + ")");
293         } else {
294             logln("Serialization for MessageFormat is OK.");
295         }
296     }
297     /* @bug 4114743
298      * MessageFormat.applyPattern allows illegal patterns.
299      */
Test4114743()300     public void Test4114743()
301     {
302         String originalPattern = "initial pattern";
303         MessageFormat mf = new MessageFormat(originalPattern);
304         try {
305             String illegalPattern = "ab { '}' de";
306             mf.applyPattern(illegalPattern);
307             errln("illegal pattern: \"" + illegalPattern + "\"");
308         } catch (IllegalArgumentException foo) {
309             if (!originalPattern.equals(mf.toPattern()))
310                 errln("pattern after: \"" + mf.toPattern() + "\"");
311         }
312     }
313 
314     /* @bug 4116444
315      * MessageFormat.parse has different behavior in case of null.
316      */
Test4116444()317     public void Test4116444()
318     {
319         String[] patterns = {"", "one", "{0,date,short}"};
320         MessageFormat mf = new MessageFormat("");
321 
322         for (int i = 0; i < patterns.length; i++) {
323             String pattern = patterns[i];
324             mf.applyPattern(pattern);
325             try {
326                 Object[] array = mf.parse(null, new ParsePosition(0));
327                 logln("pattern: \"" + pattern + "\"");
328                 log(" parsedObjects: ");
329                 if (array != null) {
330                     log("{");
331                     for (int j = 0; j < array.length; j++) {
332                         if (array[j] != null)
333                             err("\"" + array[j].toString() + "\"");
334                         else
335                             log("null");
336                         if (j < array.length - 1) log(",");
337                     }
338                     log("}") ;
339                 } else {
340                     log("null");
341                 }
342                 logln("");
343             } catch (Exception e) {
344                 errln("pattern: \"" + pattern + "\"");
345                 errln("  Exception: " + e.getMessage());
346             }
347         }
348 
349     }
350     /* @bug 4114739 (FIX and add javadoc)
351      * MessageFormat.format has undocumented behavior about empty format objects.
352      */
Test4114739()353     public void Test4114739()
354     {
355 
356         MessageFormat mf = new MessageFormat("<{0}>");
357         Object[] objs1 = null;
358         Object[] objs2 = {};
359         Object[] objs3 = {null};
360         try {
361             logln("pattern: \"" + mf.toPattern() + "\"");
362             log("format(null) : ");
363             logln("\"" + mf.format(objs1) + "\"");
364             log("format({})   : ");
365             logln("\"" + mf.format(objs2) + "\"");
366             log("format({null}) :");
367             logln("\"" + mf.format(objs3) + "\"");
368         } catch (Exception e) {
369             errln("Exception thrown for null argument tests.");
370         }
371     }
372 
373     /* @bug 4113018
374      * MessageFormat.applyPattern works wrong with illegal patterns.
375      */
Test4113018()376     public void Test4113018()
377     {
378         String originalPattern = "initial pattern";
379         MessageFormat mf = new MessageFormat(originalPattern);
380         String illegalPattern = "format: {0, xxxYYY}";
381         logln("pattern before: \"" + mf.toPattern() + "\"");
382         logln("illegal pattern: \"" + illegalPattern + "\"");
383         try {
384             mf.applyPattern(illegalPattern);
385             errln("Should have thrown IllegalArgumentException for pattern : " + illegalPattern);
386         } catch (IllegalArgumentException e) {
387             if (!originalPattern.equals(mf.toPattern()))
388                 errln("pattern after: \"" + mf.toPattern() + "\"");
389         }
390     }
391     /* @bug 4106661
392      * ChoiceFormat is silent about the pattern usage in javadoc.
393      */
Test4106661()394     public void Test4106661()
395     {
396         ChoiceFormat fmt = new ChoiceFormat(
397           "-1#are negative| 0#are no or fraction | 1#is one |1.0<is 1+ |2#are two |2<are more than 2.");
398         logln("Formatter Pattern : " + fmt.toPattern());
399 
400         logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
401         logln("Format with -1.0 : " + fmt.format(-1.0));
402         logln("Format with 0 : " + fmt.format(0));
403         logln("Format with 0.9 : " + fmt.format(0.9));
404         logln("Format with 1.0 : " + fmt.format(1));
405         logln("Format with 1.5 : " + fmt.format(1.5));
406         logln("Format with 2 : " + fmt.format(2));
407         logln("Format with 2.1 : " + fmt.format(2.1));
408         logln("Format with NaN : " + fmt.format(Double.NaN));
409         logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
410     }
411     /* @bug 4094906
412      * ChoiceFormat should accept \u221E as eq. to INF.
413      */
Test4094906()414     public void Test4094906()
415     {
416         ChoiceFormat fmt = new ChoiceFormat(
417           "-\u221E<are negative|0<are no or fraction|1#is one|1.0<is 1+|\u221E<are many.");
418         if (!fmt.toPattern().startsWith("-\u221E<are negative|0.0<are no or fraction|1.0#is one|1.0<is 1+|\u221E<are many."))
419             errln("Formatter Pattern : " + fmt.toPattern());
420         logln("Format with -INF : " + fmt.format(Double.NEGATIVE_INFINITY));
421         logln("Format with -1.0 : " + fmt.format(-1.0));
422         logln("Format with 0 : " + fmt.format(0));
423         logln("Format with 0.9 : " + fmt.format(0.9));
424         logln("Format with 1.0 : " + fmt.format(1));
425         logln("Format with 1.5 : " + fmt.format(1.5));
426         logln("Format with 2 : " + fmt.format(2));
427         logln("Format with +INF : " + fmt.format(Double.POSITIVE_INFINITY));
428     }
429 
430     /* @bug 4118592
431      * MessageFormat.parse fails with ChoiceFormat.
432      */
Test4118592()433     public void Test4118592()
434     {
435         MessageFormat mf = new MessageFormat("");
436         String pattern = "{0,choice,1#YES|2#NO}";
437         String prefix = "";
438         for (int i = 0; i < 5; i++) {
439             String formatted = prefix + "YES";
440             mf.applyPattern(prefix + pattern);
441             prefix += "x";
442             Object[] objs = mf.parse(formatted, new ParsePosition(0));
443             logln(i + ". pattern :\"" + mf.toPattern() + "\"");
444             log(" \"" + formatted + "\" parsed as ");
445             if (objs == null) logln("  null");
446             else logln("  " + objs[0]);
447         }
448     }
449     /* @bug 4118594
450      * MessageFormat.parse fails for some patterns.
451      */
Test4118594()452     public void Test4118594()
453     {
454         MessageFormat mf = new MessageFormat("{0}, {0}, {0}");
455         String forParsing = "x, y, z";
456         Object[] objs = mf.parse(forParsing, new ParsePosition(0));
457         logln("pattern: \"" + mf.toPattern() + "\"");
458         logln("text for parsing: \"" + forParsing + "\"");
459         if (!objs[0].toString().equals("z"))
460             errln("argument0: \"" + objs[0] + "\"");
461         mf.setLocale(Locale.US);
462         mf.applyPattern("{0,number,#.##}, {0,number,#.#}");
463         Object[] oldobjs = {3.1415};
464         String result = mf.format( oldobjs );
465         logln("pattern: \"" + mf.toPattern() + "\"");
466         logln("text for parsing: \"" + result + "\"");
467         // result now equals "3.14, 3.1"
468         if (!result.equals("3.14, 3.1"))
469             errln("result = " + result);
470         Object[] newobjs = mf.parse(result, new ParsePosition(0));
471         // newobjs now equals {new Double(3.1)}
472         if (((Double)newobjs[0]).doubleValue() != 3.1)
473             errln( "newobjs[0] = " + newobjs[0]);
474     }
475     /* @bug 4105380
476      * When using ChoiceFormat, MessageFormat is not good for I18n.
477      */
Test4105380()478     public void Test4105380()
479     {
480         String patternText1 = "The disk \"{1}\" contains {0}.";
481         String patternText2 = "There are {0} on the disk \"{1}\"";
482         MessageFormat form1 = new MessageFormat(patternText1);
483         MessageFormat form2 = new MessageFormat(patternText2);
484         double[] filelimits = {0,1,2};
485         String[] filepart = {"no files","one file","{0,number} files"};
486         ChoiceFormat fileform = new ChoiceFormat(filelimits, filepart);
487         form1.setFormat(1, fileform);
488         form2.setFormat(0, fileform);
489         Object[] testArgs = {12373L, "MyDisk"};
490         logln(form1.format(testArgs));
491         logln(form2.format(testArgs));
492     }
493     /* @bug 4120552
494      * MessageFormat.parse incorrectly sets errorIndex.
495      */
Test4120552()496     public void Test4120552()
497     {
498         MessageFormat mf = new MessageFormat("pattern");
499         String texts[] = {"pattern", "pat", "1234"};
500         logln("pattern: \"" + mf.toPattern() + "\"");
501         for (int i = 0; i < texts.length; i++) {
502             ParsePosition pp = new ParsePosition(0);
503             Object[] objs = mf.parse(texts[i], pp);
504             log("  text for parsing: \"" + texts[i] + "\"");
505             if (objs == null) {
506                 logln("  (incorrectly formatted string)");
507                 if (pp.getErrorIndex() == -1)
508                     errln("Incorrect error index: " + pp.getErrorIndex());
509             } else {
510                 logln("  (correctly formatted string)");
511             }
512         }
513     }
514 
515     /**
516      * @bug 4142938
517      * MessageFormat handles single quotes in pattern wrong.
518      * This is actually a problem in ChoiceFormat; it doesn't
519      * understand single quotes.
520      */
Test4142938()521     public void Test4142938() {
522         String pat = "''Vous'' {0,choice,0#n''|1#}avez s\u00E9lectionne\u00E9 " +
523             "{0,choice,0#aucun|1#{0}} client{0,choice,0#s|1#|2#s} " +
524             "personnel{0,choice,0#s|1#|2#s}.";
525         MessageFormat mf = new MessageFormat(pat);
526 
527         String[] PREFIX = {
528             "'Vous' n'avez s\u00E9lectionne\u00E9 aucun clients personnels.",
529             "'Vous' avez s\u00E9lectionne\u00E9 ",
530             "'Vous' avez s\u00E9lectionne\u00E9 "
531         };
532         String[] SUFFIX = {
533             null,
534             " client personnel.",
535             " clients personnels."
536         };
537 
538         for (int i=0; i<3; i++) {
539             String out = mf.format(new Object[]{i});
540             if (SUFFIX[i] == null) {
541                 if (!out.equals(PREFIX[i]))
542                     errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"");
543             }
544             else {
545                 if (!out.startsWith(PREFIX[i]) ||
546                     !out.endsWith(SUFFIX[i]))
547                     errln("" + i + ": Got \"" + out + "\"; Want \"" + PREFIX[i] + "\"...\"" +
548                           SUFFIX[i] + "\"");
549             }
550         }
551     }
552 
553     /**
554      * @bug 4142938
555      * Test the applyPattern and toPattern handling of single quotes
556      * by ChoiceFormat.  (This is in here because this was a bug reported
557      * against MessageFormat.)  The single quote is used to quote the
558      * pattern characters '|', '#', '<', and '\u2264'.  Two quotes in a row
559      * is a quote literal.
560      */
TestChoicePatternQuote()561     public void TestChoicePatternQuote() {
562         String[] DATA = {
563             // Pattern                  0 value           1 value
564             "0#can''t|1#can",           "can't",          "can",
565             "0#'pound(#)=''#'''|1#xyz", "pound(#)='#'",   "xyz",
566             "0#'1<2 | 1\u22641'|1#''",  "1<2 | 1\u22641", "'",
567         };
568         for (int i=0; i<DATA.length; i+=3) {
569             try {
570                 ChoiceFormat cf = new ChoiceFormat(DATA[i]);
571                 for (int j=0; j<=1; ++j) {
572                     String out = cf.format(j);
573                     if (!out.equals(DATA[i+1+j]))
574                         errln("Fail: Pattern \"" + DATA[i] + "\" x "+j+" -> " +
575                               out + "; want \"" + DATA[i+1+j] + '"');
576                 }
577                 String pat = cf.toPattern();
578                 String pat2 = new ChoiceFormat(pat).toPattern();
579                 if (!pat.equals(pat2))
580                     errln("Fail: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');
581                 else
582                     logln("Ok: Pattern \"" + DATA[i] + "\" x toPattern -> \"" + pat + '"');
583             }
584             catch (IllegalArgumentException e) {
585                 errln("Fail: Pattern \"" + DATA[i] + "\" -> " + e);
586             }
587         }
588     }
589 
590     /**
591      * @bug 4112104
592      * MessageFormat.equals(null) throws a NullPointerException.  The JLS states
593      * that it should return false.
594      */
Test4112104()595     public void Test4112104() {
596         MessageFormat format = new MessageFormat("");
597         try {
598             // This should NOT throw an exception
599             if (format.equals(null)) {
600                 // It also should return false
601                 errln("MessageFormat.equals(null) returns false");
602             }
603         }
604         catch (NullPointerException e) {
605             errln("MessageFormat.equals(null) throws " + e);
606         }
607     }
608 
609     /**
610      * @bug 4169959
611      * MessageFormat does not format null objects. CANNOT REPRODUCE THIS BUG.
612      */
Test4169959()613     public void Test4169959() {
614         // This works
615         logln(MessageFormat.format( "This will {0}", "work"));
616 
617         // This fails
618         logln(MessageFormat.format( "This will {0}",
619                                     new Object[]{ null } ) );
620     }
621 
test4232154()622     public void test4232154() {
623         boolean gotException = false;
624         try {
625             MessageFormat format = new MessageFormat("The date is {0:date}");
626         } catch (Exception e) {
627             gotException = true;
628             if (!(e instanceof IllegalArgumentException)) {
629                 throw new RuntimeException("got wrong exception type");
630             }
631             if ("argument number too large at ".equals(e.getMessage())) {
632                 throw new RuntimeException("got wrong exception message");
633             }
634         }
635         if (!gotException) {
636             throw new RuntimeException("didn't get exception for invalid input");
637         }
638     }
639 
test4293229()640     public void test4293229() {
641         MessageFormat format = new MessageFormat("'''{'0}'' '''{0}'''");
642         Object[] args = { null };
643         String expected = "'{0}' '{0}'";
644         String result = format.format(args);
645         if (!result.equals(expected)) {
646             throw new RuntimeException("wrong format result - expected \"" +
647                     expected + "\", got \"" + result + "\"");
648         }
649     }
650 
651     /**
652      * @bug 8187551
653      * test MessageFormat.setFormat() method to throw AIOOBE on invalid index.
654      */
test8187551()655     public void test8187551() {
656         //invalid cases ("pattern", "invalid format element index")
657         String[][] invalidCases = {{"The disk \"{1}\" contains {0}.", "2"},
658                 {"The disk \"{1}\" contains {0}.", "9"},
659                 {"On {1}, there are {0} and {2} folders", "3"}};
660 
661         //invalid cases (must throw exception)
662         Arrays.stream(invalidCases).forEach(entry -> messageSetFormat(entry[0],
663                 Integer.valueOf(entry[1])));
664     }
665 
666     // test MessageFormat.setFormat() method for the given pattern and
667     // format element index
messageSetFormat(String pattern, int elemIndex)668     private void messageSetFormat(String pattern, int elemIndex) {
669         MessageFormat form = new MessageFormat(pattern);
670 
671         double[] fileLimits = {0, 1, 2};
672         String[] filePart = {"no files", "one file", "{0,number} files"};
673         ChoiceFormat fileForm = new ChoiceFormat(fileLimits, filePart);
674 
675         boolean AIOOBEThrown = false;
676         try {
677             form.setFormat(elemIndex, fileForm);
678         } catch (ArrayIndexOutOfBoundsException ex) {
679             AIOOBEThrown = true;
680         }
681 
682         if (!AIOOBEThrown) {
683             throw new RuntimeException("[FAILED: Must throw" +
684                     " ArrayIndexOutOfBoundsException for" +
685                     " invalid index " + elemIndex + " used in" +
686                     " MessageFormat.setFormat(index, format)]");
687         }
688     }
689 
690 }
691