1 /*
  2  * Copyright (c) 1998, 2016, 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 International Date Format
 27  * @bug 8008577
 28  * @library /java/text/testlib
 29  * @run main/othervm -Djava.locale.providers=COMPAT,SPI IntlTestDateFormat
 30  * @key randomness
 31  */
 32 /*
 33 (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
 34 (C) Copyright IBM Corp. 1996, 1997 - All Rights Reserved
 35 
 36   The original version of this source code and documentation is copyrighted and
 37 owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
 38 provided under terms of a License Agreement between Taligent and Sun. This
 39 technology is protected by multiple US and International patents. This notice and
 40 attribution to Taligent may not be removed.
 41   Taligent is a registered trademark of Taligent, Inc.
 42 */
 43 
 44 import java.text.*;
 45 import java.util.*;
 46 
 47 public class IntlTestDateFormat extends IntlTest {
 48     // Values in milliseconds (== Date)
 49     private static final long ONESECOND = 1000;
 50     private static final long ONEMINUTE = 60 * ONESECOND;
 51     private static final long ONEHOUR = 60 * ONEMINUTE;
 52     private static final long ONEDAY = 24 * ONEHOUR;
 53     private static final double ONEYEAR = 365.25 * ONEDAY; // Approximate
 54 
 55     // EModes
 56     private static final byte GENERIC = 0;
 57     private static final byte TIME = GENERIC + 1;
 58     private static final byte DATE = TIME + 1;
 59     private static final byte DATE_TIME = DATE + 1;
 60 
 61     private DateFormat fFormat = DateFormat.getInstance();
 62     private String fTestName = new String("getInstance");
 63     private int fLimit = 3; // How many iterations it should take to reach convergence
 64 
 65     public static void main(String[] args) throws Exception {
 66         new IntlTestDateFormat().run(args);
 67     }
 68 
 69     public void TestLocale() {
 70         localeTest(Locale.getDefault(), "Default Locale");
 71     }
 72 
 73     // This test does round-trip testing (format -> parse -> format -> parse -> etc.) of DateFormat.
 74     public void localeTest(final Locale locale, final String localeName) {
 75         int timeStyle, dateStyle;
 76 
 77         // For patterns including only time information and a timezone, it may take
 78         // up to three iterations, since the timezone may shift as the year number
 79         // is determined.  For other patterns, 2 iterations should suffice.
 80         fLimit = 3;
 81 
 82         for(timeStyle = 0; timeStyle < 4; timeStyle++) {
 83             fTestName = new String("Time test " + timeStyle + " (" + localeName + ")");
 84             try {
 85                 fFormat = DateFormat.getTimeInstance(timeStyle, locale);
 86             }
 87             catch(StringIndexOutOfBoundsException e) {
 88                 errln("FAIL: localeTest time getTimeInstance exception");
 89                 throw e;
 90             }
 91             TestFormat();
 92         }
 93 
 94         fLimit = 2;
 95 
 96         for(dateStyle = 0; dateStyle < 4; dateStyle++) {
 97             fTestName = new String("Date test " + dateStyle + " (" + localeName + ")");
 98             try {
 99                 fFormat = DateFormat.getDateInstance(dateStyle, locale);
100             }
101             catch(StringIndexOutOfBoundsException e) {
102                 errln("FAIL: localeTest date getTimeInstance exception");
103                 throw e;
104             }
105             TestFormat();
106         }
107 
108         for(dateStyle = 0; dateStyle < 4; dateStyle++) {
109             for(timeStyle = 0; timeStyle < 4; timeStyle++) {
110                 fTestName = new String("DateTime test " + dateStyle + "/" + timeStyle + " (" + localeName + ")");
111                 try {
112                     fFormat = DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
113                 }
114                 catch(StringIndexOutOfBoundsException e) {
115                     errln("FAIL: localeTest date/time getDateTimeInstance exception");
116                     throw e;
117                 }
118                 TestFormat();
119             }
120         }
121     }
122 
123     public void TestFormat() {
124         if (fFormat == null) {
125             errln("FAIL: DateFormat creation failed");
126             return;
127         }
128         //        logln("TestFormat: " + fTestName);
129         Date now = new Date();
130         tryDate(new Date(0));
131         tryDate(new Date((long) 1278161801778.0));
132         tryDate(now);
133         // Shift 6 months into the future, AT THE SAME TIME OF DAY.
134         // This will test the DST handling.
135         tryDate(new Date(now.getTime() + 6*30*ONEDAY));
136 
137         Date limit = new Date(now.getTime() * 10); // Arbitrary limit
138         for (int i=0; i<2; ++i)
139             //            tryDate(new Date(floor(randDouble() * limit)));
140             tryDate(new Date((long) (randDouble() * limit.getTime())));
141     }
142 
143     private void describeTest() {
144         if (fFormat == null) {
145             errln("FAIL: no DateFormat");
146             return;
147         }
148 
149         // Assume it's a SimpleDateFormat and get some info
150         SimpleDateFormat s = (SimpleDateFormat) fFormat;
151         logln(fTestName + " Pattern " + s.toPattern());
152     }
153 
154     private void tryDate(Date theDate) {
155         final int DEPTH = 10;
156         Date[] date = new Date[DEPTH];
157         StringBuffer[] string = new StringBuffer[DEPTH];
158 
159         int dateMatch = 0;
160         int stringMatch = 0;
161         boolean dump = false;
162         int i;
163         for (i=0; i<DEPTH; ++i) string[i] = new StringBuffer();
164         for (i=0; i<DEPTH; ++i) {
165             if (i == 0) date[i] = theDate;
166             else {
167                 try {
168                     date[i] = fFormat.parse(string[i-1].toString());
169                 }
170                 catch (ParseException e) {
171                     describeTest();
172                     errln("********** FAIL: Parse of " + string[i-1] + " failed.");
173                     dump = true;
174                     break;
175                 }
176             }
177             FieldPosition position = new FieldPosition(0);
178             fFormat.format(date[i], string[i], position);
179             if (i > 0) {
180                 if (dateMatch == 0 && date[i] == date[i-1]) dateMatch = i;
181                 else if (dateMatch > 0 && date[i] != date[i-1]) {
182                     describeTest();
183                     errln("********** FAIL: Date mismatch after match.");
184                     dump = true;
185                     break;
186                 }
187                 if (stringMatch == 0 && string[i] == string[i-1]) stringMatch = i;
188                 else if (stringMatch > 0 && string[i] != string[i-1]) {
189                     describeTest();
190                     errln("********** FAIL: String mismatch after match.");
191                     dump = true;
192                     break;
193                 }
194             }
195             if (dateMatch > 0 && stringMatch > 0) break;
196         }
197         if (i == DEPTH) --i;
198 
199         if (stringMatch > fLimit || dateMatch > fLimit) {
200             describeTest();
201             errln("********** FAIL: No string and/or date match within " + fLimit + " iterations.");
202             dump = true;
203         }
204 
205         if (dump) {
206             for (int k=0; k<=i; ++k) {
207                 logln("" + k + ": " + date[k] + " F> " + string[k] + " P> ");
208             }
209         }
210     }
211 
212     // Return a random double from 0.01 to 1, inclusive
213     private double randDouble() {
214         // Assume 8-bit (or larger) rand values.  Also assume
215         // that the system rand() function is very poor, which it always is.
216         //        double d;
217         //        int i;
218         //        do {
219         //            for (i=0; i < sizeof(double); ++i)
220         //            {
221         //                char poke = (char*)&d;
222         //                poke[i] = (rand() & 0xFF);
223         //            }
224         //        } while (TPlatformUtilities.isNaN(d) || TPlatformUtilities.isInfinite(d));
225 
226         //        if (d < 0.0) d = -d;
227         //        if (d > 0.0)
228         //        {
229         //            double e = floor(log10(d));
230         //            if (e < -2.0) d *= pow(10.0, -e-2);
231         //            else if (e > -1.0) d /= pow(10.0, e+1);
232         //        }
233         //        return d;
234         Random rand = new Random();
235         return rand.nextDouble();
236     }
237 
238     public void TestAvailableLocales() {
239         final Locale[] locales = DateFormat.getAvailableLocales();
240         long count = locales.length;
241         logln("" + count + " available locales");
242         if (locales != null  &&  count != 0) {
243             StringBuffer all = new StringBuffer();
244             for (int i=0; i<count; ++i) {
245                 if (i!=0) all.append(", ");
246                 all.append(locales[i].getDisplayName());
247             }
248             logln(all.toString());
249         }
250         else errln("********** FAIL: Zero available locales or null array pointer");
251     }
252 
253     /* This test is too slow; we disable it for now
254     public void TestMonster() {
255         final Locale[] locales = DateFormat.getAvailableLocales();
256         long count = locales.length;
257         if (locales != null  &&  count != 0) {
258             for (int i=0; i<count; ++i) {
259                 String name = locales[i].getDisplayName();
260                 logln("Testing " + name + "...");
261                 try {
262                     localeTest(locales[i], name);
263                 }
264                 catch(Exception e) {
265                     errln("FAIL: TestMonster localeTest exception" + e);
266                 }
267             }
268         }
269     }
270     */
271 }
272 
273 //eof