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 
33 import java.io.*;
34 import java.text.*;
35 import java.util.*;
36 
37 // Usage: java Bug4407042 [duration]
38 public 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 
test()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 
getFormatter()83     synchronized static SimpleDateFormat getFormatter() {
84         return (SimpleDateFormat) masterFormat.clone();
85     }
86 
87     static class DateParseThread extends Thread {
run()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 {
run()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 
main(String[] args)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