1/*
2 * Copyright (c) 2001, 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 * @bug 4407042
27 * @summary Make sure that cloned SimpleDateFormat objects work
28 * independently in multiple threads.
29 * @library /java/text/testlib
30 * @run main Bug4407042 10
31 */
32
33import java.io.*;
34import java.text.*;
35import java.util.*;
36
37// Usage: java Bug4407042 [duration]
38public class Bug4407042 {
39
40    static final String TIME_STRING = "2000/11/18 00:01:00";
41    static final long UTC_LONG = 974534460000L;
42    static SimpleDateFormat masterFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
43    static boolean runrun = true;
44    static int duration = 100;
45
46    void test() {
47        Locale locale = Locale.getDefault();
48        if (!TestUtils.usesAsciiDigits(locale)
49                || !TestUtils.usesGregorianCalendar(locale)) {
50            System.out.println("Skipping this test because locale is " + locale);
51            return;
52        }
53
54        masterFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
55        DateParseThread d1 = new DateParseThread();
56        DateFormatThread d2 = new DateFormatThread();
57        d1.start();
58        d2.start();
59        int n = Thread.activeCount();
60        boolean failed = false;
61
62        for (int i = 0; i < duration; i++) {
63            try {
64                Thread.sleep(1000);
65                if (Thread.activeCount() != n) {
66                    failed = true;
67                    break;
68                }
69            } catch (InterruptedException e) {
70            }
71        }
72        runrun = false;
73        try {
74            d1.join();
75            d2.join();
76        } catch (InterruptedException e) {
77        }
78        if (failed) {
79            throw new RuntimeException("Failed");
80        }
81    }
82
83    synchronized static SimpleDateFormat getFormatter() {
84        return (SimpleDateFormat) masterFormat.clone();
85    }
86
87    static class DateParseThread extends Thread {
88        public void run() {
89            SimpleDateFormat sdf = getFormatter();
90            Calendar cal = null;
91
92            try {
93                int i = 0;
94                while (runrun) {
95                    Date date =sdf.parse(TIME_STRING);
96                    long t = date.getTime();
97                    i++;
98                    if (t != UTC_LONG) {
99                        throw new RuntimeException("Parse Error: " + i +
100                                                   " (" + sdf.format(date) + ") " + t +
101                                                   " != " + UTC_LONG);
102                    }
103                }
104            } catch (ParseException e) {
105                e.printStackTrace();
106                throw new RuntimeException("Parse Error");
107            }
108        }
109    }
110
111    static class DateFormatThread extends Thread {
112        public  void run () {
113            SimpleDateFormat sdf = getFormatter();
114            Calendar cal = null;
115
116            int i = 0;
117            while (runrun) {
118                i++;
119                String s = sdf.format(new Date(UTC_LONG));
120                if (!s.equals(TIME_STRING)) {
121                    throw new RuntimeException("Format Error: " + i + " " +
122                                               s + " != " + TIME_STRING);
123                }
124            }
125        }
126    }
127
128    public static void main (String[] args) {
129        if (args.length == 1) {
130            duration = Math.max(10, Integer.parseInt(args[0]));
131        }
132        new Bug4407042().test();
133    }
134}
135