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
37owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These materials are
38provided under terms of a License Agreement between Taligent and Sun. This
39technology is protected by multiple US and International patents. This notice and
40attribution to Taligent may not be removed.
41  Taligent is a registered trademark of Taligent, Inc.
42*/
43
44import java.text.*;
45import java.util.*;
46
47public 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
274