< prev index next >

test/jdk/java/text/Format/DateFormat/DateFormatRoundTripTest.java

Print this page

  1 /*
  2  * Copyright (c) 1997, 2022, 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  * @summary test Date Format (Round Trip)
 27  * @bug 8008577
 28  * @library /java/text/testlib
 29  * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRoundTripTest
 30  */
 31 
 32 import java.text.*;
 33 import java.util.*;
 34 
 35 public class DateFormatRoundTripTest extends IntlTest {











 36 
 37     static Random RANDOM = null;
 38 
 39     static final long FIXED_SEED = 3141592653589793238L; // Arbitrary fixed value
 40 
 41     // Useful for turning up subtle bugs: Use -infinite and run while at lunch.
 42     boolean INFINITE = false; // Warning -- makes test run infinite loop!!!
 43 
 44     boolean random = false;
 45 
 46     // Options used to reproduce failures
 47     Locale locale = null;
 48     String pattern = null;
 49     Date initialDate = null;
 50 
 51     Locale[] avail;
 52     TimeZone defaultZone;
 53 
 54     // If SPARSENESS is > 0, we don't run each exhaustive possibility.
 55     // There are 24 total possible tests per each locale.  A SPARSENESS

 90         }
 91         if ((i = country.indexOf('_')) >= 0) {
 92             variant = country.substring(i+1);
 93             country = country.substring(0, i);
 94         }
 95         return Locale.of(name, country, variant);
 96     }
 97 
 98     public static void main(String[] args) throws Exception {
 99         // Command-line parameters
100         Locale loc = null;
101         boolean infinite = false;
102         boolean random = false;
103         long seed = FIXED_SEED;
104         String pat = null;
105         Date date = null;
106 
107         List<String> newArgs = new ArrayList<>();
108         for (int i=0; i<args.length; ++i) {
109             if (args[i].equals("-locale")
110                 && (i+1) < args.length) {
111                 loc = createLocale(args[i+1]);
112                 ++i;
113             } else if (args[i].equals("-date")
114                        && (i+1) < args.length) {
115                 date = new Date(Long.parseLong(args[i+1]));
116                 ++i;
117             } else if (args[i].equals("-pattern")
118                 && (i+1) < args.length) {
119                 pat = args[i+1];
120                 ++i;
121             } else if (args[i].equals("-INFINITE")) {
122                 infinite = true;
123             } else if (args[i].equals("-random")) {
124                 random = true;
125             } else if (args[i].equals("-randomseed")) {
126                 random = true;
127                 seed = System.currentTimeMillis();
128             } else if (args[i].equals("-seed")
129                        && (i+1) < args.length) {
130                 random = true;
131                 seed = Long.parseLong(args[i+1]);
132                 ++i;
133             } else {
134                 newArgs.add(args[i]);
135             }
136         }
137 
138         if (newArgs.size() != args.length) {
139             args = new String[newArgs.size()];
140             newArgs.addAll(Arrays.asList(args));
141         }
142 
143         new DateFormatRoundTripTest(random, seed, infinite, date, pat, loc).run(args);

144     }
145 
146     /**
147      * Print a usage message for this test class.
148      */
149     void usage() {
150         System.out.println(getClass().getName() +
151                            ": [-pattern <pattern>] [-locale <locale>] [-date <ms>] [-INFINITE]");
152         System.out.println(" [-random | -randomseed | -seed <seed>]");
153         System.out.println("* Warning: Some patterns will fail with some locales.");
154         System.out.println("* Do not use -pattern unless you know what you are doing!");
155         System.out.println("When specifying a locale, use a format such as fr_FR.");
156         System.out.println("Use -pattern, -locale, and -date to reproduce a failure.");
157         System.out.println("-random     Random with fixed seed (same data every run).");
158         System.out.println("-randomseed Random with a random seed.");
159         System.out.println("-seed <s>   Random using <s> as seed.");
160         super.usage();
161     }
162 
163     static private class TestCase {
164         private int[] date;
165         TimeZone zone;
166         FormatFactory ff;
167         boolean timeOnly;
168         private Date _date;
169 
170         TestCase(int[] d, TimeZone z, FormatFactory f, boolean timeOnly) {
171             date = d;
172             zone = z;
173             ff  = f;
174             this.timeOnly = timeOnly;
175         }
176 
177         TestCase(Date d, TimeZone z, FormatFactory f, boolean timeOnly) {
178             date = null;
179             _date = d;
180             zone = z;

293                                                                DateFormat.LONG);
294                      }}, false),
295 
296         // October 4, 1582 11:59:59 PM PDT -- just before Gregorian change
297         new TestCase(new int[] {1582, 10, 4, 23, 59, 59}, null,
298                      new FormatFactory() { public DateFormat createFormat() {
299                          return DateFormat.getDateTimeInstance(DateFormat.LONG,
300                                                                DateFormat.LONG);
301                      }}, false),
302 
303         // October 15, 1582 12:00:00 AM PDT -- just after Gregorian change
304         new TestCase(new int[] {1582, 10, 15, 0, 0, 0}, null,
305                      new FormatFactory() { public DateFormat createFormat() {
306                          return DateFormat.getDateTimeInstance(DateFormat.LONG,
307                                                                DateFormat.LONG);
308                      }}, false),
309     };
310 
311     public void TestDateFormatRoundTrip() {
312         avail = DateFormat.getAvailableLocales();
313         logln("DateFormat available locales: " + avail.length);
314         logln("Default TimeZone: " +
315               (defaultZone = TimeZone.getDefault()).getID());
316 
317         if (random || initialDate != null) {
318             if (RANDOM == null) {
319                 // Need this for sparse coverage to reduce combinatorial explosion,
320                 // even for non-random looped testing (i.e., with explicit date but
321                 // not pattern or locale).
322                 RANDOM = new Random(FIXED_SEED);
323             }
324             loopedTest();
325         } else {
326             for (int i=0; i<TESTS.length; ++i) {
327                 doTest(TESTS[i]);
328             }
329         }
330     }
331 
332     /**
333      * TimeZone must be set to tc.zone before this method is called.
334      */
335     private void doTestInZone(TestCase tc) {
336         logln(escape(tc.toString()));
337         Locale save = Locale.getDefault();
338         try {
339             if (locale != null) {
340                 Locale.setDefault(locale);
341                 doTest(locale, tc.createFormat(), tc.timeOnly, tc.getDate());
342             } else {
343                 for (int i=0; i<avail.length; ++i) {
344                     Locale.setDefault(avail[i]);
345                     doTest(avail[i], tc.createFormat(), tc.timeOnly, tc.getDate());
346                 }
347             }
348         } finally {
349             Locale.setDefault(save);
350         }
351     }
352 
353     private void doTest(TestCase tc) {
354         if (tc.zone == null) {
355             // Just run in the default zone
356             doTestInZone(tc);
357         } else {
358             try {
359                 TimeZone.setDefault(tc.zone);
360                 doTestInZone(tc);
361             } finally {
362                 TimeZone.setDefault(defaultZone);
363             }
364         }
365     }
366 
367     private void loopedTest() {
368         if (INFINITE) {
369             // Special infinite loop test mode for finding hard to reproduce errors
370             if (locale != null) {
371                 logln("ENTERING INFINITE TEST LOOP, LOCALE " + locale.getDisplayName());
372                 for (;;) doTest(locale);
373             } else {
374                 logln("ENTERING INFINITE TEST LOOP, ALL LOCALES");
375                 for (;;) {
376                     for (int i=0; i<avail.length; ++i) {
377                         doTest(avail[i]);
378                     }
379                 }
380             }
381         }
382         else {
383             if (locale != null) {
384                 doTest(locale);
385             } else {
386                 doTest(Locale.getDefault());
387 
388                 for (int i=0; i<avail.length; ++i) {
389                     doTest(avail[i]);
390                 }
391             }
392         }
393     }
394 
395     void doTest(Locale loc) {
396         if (!INFINITE) logln("Locale: " + loc.getDisplayName());
397 
398         if (pattern != null) {
399             doTest(loc, new SimpleDateFormat(pattern, loc));
400             return;
401         }
402 
403         // Total possibilities = 24
404         //  4 date
405         //  4 time
406         //  16 date-time
407         boolean[] TEST_TABLE = new boolean[24];
408         for (int i=0; i<24; ++i) TEST_TABLE[i] = true;
409 
410         // If we have some sparseness, implement it here.  Sparseness decreases
411         // test time by eliminating some tests, up to 23.
412         if (!INFINITE) {
413             for (int i=0; i<SPARSENESS; ) {
414                 int random = (int)(java.lang.Math.random() * 24);
415                 if (random >= 0 && random < 24 && TEST_TABLE[i]) {
416                     TEST_TABLE[i] = false;

587                 if (dmatch > maxDmatch || smatch > maxSmatch
588                     || dmatch < 0 || smatch < 0) {
589                     StringBuffer out = new StringBuffer();
590                     if (error != null) {
591                         out.append(error + '\n');
592                     }
593                     out.append("FAIL: Pattern: " + pat + ", Locale: " + loc + '\n');
594                     out.append("      Initial date (ms): " + d[0].getTime() + '\n');
595                     out.append("     Date matched in " + dmatch
596                                + ", wanted " + maxDmatch + '\n');
597                     out.append("     String matched in " + smatch
598                                + ", wanted " + maxSmatch);
599 
600                     for (int j=0; j<=loop && j<DEPTH; ++j) {
601                         out.append("\n    " +
602                                    (j>0?" P> ":"    ") + refFormat.format(d[j]) + " F> " +
603                                    escape(s[j]) +
604                                    (j>0&&d[j].getTime()==d[j-1].getTime()?" d==":"") +
605                                    (j>0&&s[j].equals(s[j-1])?" s==":""));
606                     }
607                     errln(escape(out.toString()));
608                 }
609             }
610         }
611         catch (ParseException e) {
612             errln(e.toString());
613         }
614     }
615 
616     /**
617      * Return a field of the given date
618      */
619     static int getField(Calendar cal, Date d, int f) {
620         // Should be synchronized, but we're single threaded so it's ok
621         cal.setTime(d);
622         return cal.get(f);
623     }
624 
625     /**
626      * Return true if the given Date is in the 1 hour window BEFORE the
627      * change from STD to DST for the given Calendar.
628      */
629     static final boolean justBeforeOnset(Calendar cal, Date d) {
630         return nearOnset(cal, d, false);
631     }
632 

  1 /*
  2  * Copyright (c) 1997, 2024, 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  * @summary test Date Format (Round Trip)
 27  * @bug 8008577

 28  * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRoundTripTest
 29  */
 30 
 31 import java.text.DateFormat;
 32 import java.text.ParseException;
 33 import java.text.SimpleDateFormat;
 34 import java.util.ArrayList;
 35 import java.util.Arrays;
 36 import java.util.Calendar;
 37 import java.util.Date;
 38 import java.util.GregorianCalendar;
 39 import java.util.List;
 40 import java.util.Locale;
 41 import java.util.Random;
 42 import java.util.SimpleTimeZone;
 43 import java.util.TimeZone;
 44 
 45 public class DateFormatRoundTripTest {
 46 
 47     static Random RANDOM = null;
 48 
 49     static final long FIXED_SEED = 3141592653589793238L; // Arbitrary fixed value
 50 
 51     // Useful for turning up subtle bugs: Use -infinite and run while at lunch.
 52     boolean INFINITE = false; // Warning -- makes test run infinite loop!!!
 53 
 54     boolean random = false;
 55 
 56     // Options used to reproduce failures
 57     Locale locale = null;
 58     String pattern = null;
 59     Date initialDate = null;
 60 
 61     Locale[] avail;
 62     TimeZone defaultZone;
 63 
 64     // If SPARSENESS is > 0, we don't run each exhaustive possibility.
 65     // There are 24 total possible tests per each locale.  A SPARSENESS

100         }
101         if ((i = country.indexOf('_')) >= 0) {
102             variant = country.substring(i+1);
103             country = country.substring(0, i);
104         }
105         return Locale.of(name, country, variant);
106     }
107 
108     public static void main(String[] args) throws Exception {
109         // Command-line parameters
110         Locale loc = null;
111         boolean infinite = false;
112         boolean random = false;
113         long seed = FIXED_SEED;
114         String pat = null;
115         Date date = null;
116 
117         List<String> newArgs = new ArrayList<>();
118         for (int i=0; i<args.length; ++i) {
119             if (args[i].equals("-locale")
120                     && (i+1) < args.length) {
121                 loc = createLocale(args[i+1]);
122                 ++i;
123             } else if (args[i].equals("-date")
124                     && (i+1) < args.length) {
125                 date = new Date(Long.parseLong(args[i+1]));
126                 ++i;
127             } else if (args[i].equals("-pattern")
128                     && (i+1) < args.length) {
129                 pat = args[i+1];
130                 ++i;
131             } else if (args[i].equals("-INFINITE")) {
132                 infinite = true;
133             } else if (args[i].equals("-random")) {
134                 random = true;
135             } else if (args[i].equals("-randomseed")) {
136                 random = true;
137                 seed = System.currentTimeMillis();
138             } else if (args[i].equals("-seed")
139                     && (i+1) < args.length) {
140                 random = true;
141                 seed = Long.parseLong(args[i+1]);
142                 ++i;
143             } else {
144                 newArgs.add(args[i]);
145             }
146         }
147 
148         if (newArgs.size() != args.length) {
149             args = new String[newArgs.size()];
150             newArgs.addAll(Arrays.asList(args));
151         }
152 
153         new DateFormatRoundTripTest(random, seed, infinite, date, pat, loc)
154                 .TestDateFormatRoundTrip();
155     }
156 
157     /**
158      * Print a usage message for this test class.
159      */
160     void usage() {
161         System.out.println(getClass().getName() +
162                            ": [-pattern <pattern>] [-locale <locale>] [-date <ms>] [-INFINITE]");
163         System.out.println(" [-random | -randomseed | -seed <seed>]");
164         System.out.println("* Warning: Some patterns will fail with some locales.");
165         System.out.println("* Do not use -pattern unless you know what you are doing!");
166         System.out.println("When specifying a locale, use a format such as fr_FR.");
167         System.out.println("Use -pattern, -locale, and -date to reproduce a failure.");
168         System.out.println("-random     Random with fixed seed (same data every run).");
169         System.out.println("-randomseed Random with a random seed.");
170         System.out.println("-seed <s>   Random using <s> as seed.");

171     }
172 
173     static private class TestCase {
174         private int[] date;
175         TimeZone zone;
176         FormatFactory ff;
177         boolean timeOnly;
178         private Date _date;
179 
180         TestCase(int[] d, TimeZone z, FormatFactory f, boolean timeOnly) {
181             date = d;
182             zone = z;
183             ff  = f;
184             this.timeOnly = timeOnly;
185         }
186 
187         TestCase(Date d, TimeZone z, FormatFactory f, boolean timeOnly) {
188             date = null;
189             _date = d;
190             zone = z;

303                                                                DateFormat.LONG);
304                      }}, false),
305 
306         // October 4, 1582 11:59:59 PM PDT -- just before Gregorian change
307         new TestCase(new int[] {1582, 10, 4, 23, 59, 59}, null,
308                      new FormatFactory() { public DateFormat createFormat() {
309                          return DateFormat.getDateTimeInstance(DateFormat.LONG,
310                                                                DateFormat.LONG);
311                      }}, false),
312 
313         // October 15, 1582 12:00:00 AM PDT -- just after Gregorian change
314         new TestCase(new int[] {1582, 10, 15, 0, 0, 0}, null,
315                      new FormatFactory() { public DateFormat createFormat() {
316                          return DateFormat.getDateTimeInstance(DateFormat.LONG,
317                                                                DateFormat.LONG);
318                      }}, false),
319     };
320 
321     public void TestDateFormatRoundTrip() {
322         avail = DateFormat.getAvailableLocales();
323         System.out.println("DateFormat available locales: " + avail.length);
324         System.out.println("Default TimeZone: " +
325               (defaultZone = TimeZone.getDefault()).getID());
326 
327         if (random || initialDate != null) {
328             if (RANDOM == null) {
329                 // Need this for sparse coverage to reduce combinatorial explosion,
330                 // even for non-random looped testing (i.e., with explicit date but
331                 // not pattern or locale).
332                 RANDOM = new Random(FIXED_SEED);
333             }
334             loopedTest();
335         } else {
336             for (int i=0; i<TESTS.length; ++i) {
337                 doTest(TESTS[i]);
338             }
339         }
340     }
341 
342     /**
343      * TimeZone must be set to tc.zone before this method is called.
344      */
345     private void doTestInZone(TestCase tc) {
346         System.out.println(escape(tc.toString()));
347         Locale save = Locale.getDefault();
348         try {
349             if (locale != null) {
350                 Locale.setDefault(locale);
351                 doTest(locale, tc.createFormat(), tc.timeOnly, tc.getDate());
352             } else {
353                 for (int i=0; i<avail.length; ++i) {
354                     Locale.setDefault(avail[i]);
355                     doTest(avail[i], tc.createFormat(), tc.timeOnly, tc.getDate());
356                 }
357             }
358         } finally {
359             Locale.setDefault(save);
360         }
361     }
362 
363     private void doTest(TestCase tc) {
364         if (tc.zone == null) {
365             // Just run in the default zone
366             doTestInZone(tc);
367         } else {
368             try {
369                 TimeZone.setDefault(tc.zone);
370                 doTestInZone(tc);
371             } finally {
372                 TimeZone.setDefault(defaultZone);
373             }
374         }
375     }
376 
377     private void loopedTest() {
378         if (INFINITE) {
379             // Special infinite loop test mode for finding hard to reproduce errors
380             if (locale != null) {
381                 System.out.println("ENTERING INFINITE TEST LOOP, LOCALE " + locale.getDisplayName());
382                 for (;;) doTest(locale);
383             } else {
384                 System.out.println("ENTERING INFINITE TEST LOOP, ALL LOCALES");
385                 for (;;) {
386                     for (int i=0; i<avail.length; ++i) {
387                         doTest(avail[i]);
388                     }
389                 }
390             }
391         }
392         else {
393             if (locale != null) {
394                 doTest(locale);
395             } else {
396                 doTest(Locale.getDefault());
397 
398                 for (int i=0; i<avail.length; ++i) {
399                     doTest(avail[i]);
400                 }
401             }
402         }
403     }
404 
405     void doTest(Locale loc) {
406         if (!INFINITE) System.out.println("Locale: " + loc.getDisplayName());
407 
408         if (pattern != null) {
409             doTest(loc, new SimpleDateFormat(pattern, loc));
410             return;
411         }
412 
413         // Total possibilities = 24
414         //  4 date
415         //  4 time
416         //  16 date-time
417         boolean[] TEST_TABLE = new boolean[24];
418         for (int i=0; i<24; ++i) TEST_TABLE[i] = true;
419 
420         // If we have some sparseness, implement it here.  Sparseness decreases
421         // test time by eliminating some tests, up to 23.
422         if (!INFINITE) {
423             for (int i=0; i<SPARSENESS; ) {
424                 int random = (int)(java.lang.Math.random() * 24);
425                 if (random >= 0 && random < 24 && TEST_TABLE[i]) {
426                     TEST_TABLE[i] = false;

597                 if (dmatch > maxDmatch || smatch > maxSmatch
598                     || dmatch < 0 || smatch < 0) {
599                     StringBuffer out = new StringBuffer();
600                     if (error != null) {
601                         out.append(error + '\n');
602                     }
603                     out.append("FAIL: Pattern: " + pat + ", Locale: " + loc + '\n');
604                     out.append("      Initial date (ms): " + d[0].getTime() + '\n');
605                     out.append("     Date matched in " + dmatch
606                                + ", wanted " + maxDmatch + '\n');
607                     out.append("     String matched in " + smatch
608                                + ", wanted " + maxSmatch);
609 
610                     for (int j=0; j<=loop && j<DEPTH; ++j) {
611                         out.append("\n    " +
612                                    (j>0?" P> ":"    ") + refFormat.format(d[j]) + " F> " +
613                                    escape(s[j]) +
614                                    (j>0&&d[j].getTime()==d[j-1].getTime()?" d==":"") +
615                                    (j>0&&s[j].equals(s[j-1])?" s==":""));
616                     }
617                     throw new RuntimeException(escape(out.toString()));
618                 }
619             }
620         }
621         catch (ParseException e) {
622             throw new RuntimeException(e.toString());
623         }
624     }
625 
626     /**
627      * Return a field of the given date
628      */
629     static int getField(Calendar cal, Date d, int f) {
630         // Should be synchronized, but we're single threaded so it's ok
631         cal.setTime(d);
632         return cal.get(f);
633     }
634 
635     /**
636      * Return true if the given Date is in the 1 hour window BEFORE the
637      * change from STD to DST for the given Calendar.
638      */
639     static final boolean justBeforeOnset(Calendar cal, Date d) {
640         return nearOnset(cal, d, false);
641     }
642 
< prev index next >