blob: 742df10774151f25e35c4bcc67896c0b6371cddf [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright (c) 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any questions.
22 */
23/*
24 * @test
25 * @bug 5102289
26 * @summary Stress test for ResourceBundle.getBundle with ResourceBundle.Control.
27 * @run main/timeout=300/othervm -esa StressTest
28 */
29
30import java.util.*;
31import java.util.concurrent.atomic.*;
32
33public class StressTest {
34 static final Locale ROOT_LOCALE = new Locale("");
35 static final Random rand = new Random();
36 static final Locale[] locales = {
37 Locale.US,
38 Locale.CHINA,
39 ROOT_LOCALE,
40 Locale.JAPAN,
41 Locale.CANADA,
42 Locale.KOREA
43 };
44 static final String[] expected = {
45 "U.S.A.",
46 "China",
47 "U.S.A.",
48 "Japan",
49 "U.S.A.", // StressOut_en_CA.properties is empty.
50 "Korea"
51 };
52 final static long startTime = System.currentTimeMillis();
53
54 // increment each element when one getBundle call is done.
55 static AtomicIntegerArray counters;
56 static int[] prevCounters;
57 static int intervalForCounterCheck;
58 static AtomicInteger clearCounter = new AtomicInteger();
59
60 static volatile boolean runrun = true;
61
62 public static void main(String[] args) {
63 int nThreads = 2;
64 if (args.length > 0) {
65 nThreads = Math.max(Integer.parseInt(args[0]), 2);
66 }
67 int nSeconds = 180;
68 if (args.length > 1) {
69 nSeconds = Integer.parseInt(args[1]);
70 }
71 Locale.setDefault(Locale.US);
72 Thread[] tasks = new Thread[locales.length * nThreads];
73 counters = new AtomicIntegerArray(tasks.length);
74
75 for (int i = 0; i < tasks.length; i++) {
76 tasks[i] = new Thread(new Worker(i));
77 }
78 for (int i = 0; i < tasks.length; i++) {
79 tasks[i].start();
80 }
81
82 int nProcessors = Runtime.getRuntime().availableProcessors();
83 intervalForCounterCheck = Math.max(tasks.length / nProcessors, 1);
84 System.out.printf("%d processors, intervalForCounterCheck = %d [sec]%n",
85 nProcessors, intervalForCounterCheck);
86 try {
87 for (int i = 0; runrun && i < nSeconds; i++) {
88 Thread.sleep(1000); // 1 seconds
89 if ((i % intervalForCounterCheck) == 0) {
90 checkCounters();
91 }
92 }
93 runrun = false;
94 for (int i = 0; i < tasks.length; i++) {
95 tasks[i].join();
96 }
97 } catch (InterruptedException e) {
98 }
99
100 printCounters();
101 }
102
103 static void checkCounters() {
104 int length = counters.length();
105 int[] snapshot = new int[length];
106 for (int i = 0; i < length; i++) {
107 snapshot[i] = counters.get(i);
108 }
109
110 if (prevCounters == null) {
111 prevCounters = snapshot;
112 return;
113 }
114
115 for (int i = 0; i < length; i++) {
116 if (snapshot[i] > prevCounters[i]) {
117 continue;
118 }
119 System.out.printf(
120 "Warning: Thread #%d hasn't updated its counter for the last %d second(s).%n",
121 i, intervalForCounterCheck);
122 }
123 prevCounters = snapshot;
124 }
125
126 static void printCounters() {
127 long total = 0;
128 int min = Integer.MAX_VALUE;
129 int max = Integer.MIN_VALUE;
130 for (int i = 0; i < counters.length(); i++) {
131 int counter = counters.get(i);
132 total += counter;
133 min = Math.min(min, counter);
134 max = Math.max(max, counter);
135 }
136 System.out.printf("Total: %d calls, min=%d, max=%d, cache cleared %d times%n",
137 total, min, max, clearCounter.get());
138 }
139
140 static class Worker implements Runnable {
141 final int id;
142 final int index;
143 final Locale locale;
144 final String str;
145 final int max;
146 final boolean cleaner;
147 ResourceBundle.Control control;
148
149 Worker(int i) {
150 id = i;
151 index = i % locales.length;
152 locale = locales[index];
153 cleaner = locale.equals(ROOT_LOCALE);
154 str = expected[index];
155 max = rand.nextInt((index + 1) * 500) + 1000;
156 control = new TestControl(max);
157 System.out.println("Worker" + i + ": locale="+locale+", expected="+str+
158 ", max="+max);
159 }
160
161 public void run() {
162 while (runrun) {
163 ResourceBundle rb = ResourceBundle.getBundle("StressOut", locale, control);
164 counters.incrementAndGet(id);
165 String s = rb.getString("data");
166 if (!s.equals(str)) {
167 runrun = false;
168 throw new RuntimeException(locale + ": rb.locale=" + rb.getLocale() +
169 ", got " + s + ", expected " + str);
170 }
171 try {
172 Thread.sleep(rand.nextInt(max/500));
173 } catch (InterruptedException e) {
174 }
175 if (cleaner && (rand.nextInt(10000) == 0)) {
176 //System.out.println("Clearing cache!");
177 ResourceBundle.clearCache();
178 clearCounter.incrementAndGet();
179 }
180 }
181 }
182
183 static class TestControl extends ResourceBundle.Control {
184 int max;
185
186 public List<Locale> getCandidateLocales(String baseName, Locale locale) {
187 List<Locale> list = super.getCandidateLocales(baseName, locale);
188 //System.out.println("Candidate locales=" + list);
189 return list;
190 }
191 public TestControl(int max) {
192 this.max = max;
193 }
194 public long getTimeToLive(String baseName, Locale locale) {
195 // This will set TTL to a random value for each bundle.
196 long ttl = rand.nextInt(max);
197 //System.out.println("TTL: " + baseName + "_" + locale + " for " + ttl);
198 return ttl;
199 }
200 public boolean needsReload(String baseName, Locale locale,
201 String format, ClassLoader loader,
202 ResourceBundle bundle, long loadTime) {
203 //System.out.println("Expired: " + baseName + "_" + locale + "." + format +
204 // " at " + (loadTime-startTime) + ", bundle=" + bundle);
205 return rand.nextBoolean();
206 }
207 }
208 }
209}