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