blob: aabbc140f85a0bb2723284866f184c5cde3d8955 [file] [log] [blame]
dcubedf7f66812011-06-01 17:11:23 -07001/*
katlemand08780c2012-12-20 16:24:50 -08002 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
dcubedf7f66812011-06-01 17:11:23 -07003 * 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 7045594
27 * @summary ResourceBundle setting race in Logger.getLogger(name, rbName)
28 * @author Daniel D. Daugherty
29 * @build RacingThreadsTest LoggerResourceBundleRace
30 * @run main LoggerResourceBundleRace
31 */
32
dcubedf7f66812011-06-01 17:11:23 -070033import java.util.ListResourceBundle;
dcubedf7f66812011-06-01 17:11:23 -070034import java.util.MissingResourceException;
jgish8d2b8af2012-11-29 12:28:02 +000035import java.util.concurrent.atomic.AtomicInteger;
36import java.util.logging.Logger;
dcubedf7f66812011-06-01 17:11:23 -070037
38
39public class LoggerResourceBundleRace extends RacingThreadsTest {
40 private final static int N_LOOPS = 500000; // # of race loops
41 private final static int N_SECS = 15; // # of secs to run test
42 // # of parallel threads; must match number of MyResources inner classes
43 private final static int N_THREADS = 3;
44
45 private final static String LOGGER_PREFIX = "myLogger-";
46 private final static String RESOURCE_PREFIX
47 = "LoggerResourceBundleRace$MyResources";
48 // these counters are AtomicInteger since any worker thread can increment
49 private final static AtomicInteger iaeCnt = new AtomicInteger();
50 private final static AtomicInteger worksCnt = new AtomicInteger();
51
52 Logger dummy; // dummy Logger
53
54 LoggerResourceBundleRace(String name, int n_threads, int n_loops,
55 int n_secs) {
56 super(name, n_threads, n_loops, n_secs);
57 }
58
59
60 // Main test driver
61 //
62 public static void main(String[] args) {
63 LoggerResourceBundleRace test
64 = new LoggerResourceBundleRace("LoggerResourceBundleRace",
65 N_THREADS, N_LOOPS, N_SECS);
66 test.setVerbose(
67 Boolean.getBoolean("LoggerResourceBundleRace.verbose"));
68
69 DriverThread driver = new DriverThread(test);
70 MyWorkerThread[] workers = new MyWorkerThread[N_THREADS];
71 for (int i = 0; i < workers.length; i++) {
72 workers[i] = new MyWorkerThread(i, test);
73 }
74 test.runTest(driver, workers);
75 }
76
77 public void oneTimeDriverInit(DriverThread dt) {
78 super.oneTimeDriverInit(dt);
79 dummy = null;
80 }
81
82 public void perRaceDriverInit(DriverThread dt) {
83 super.perRaceDriverInit(dt);
84
85 // - allocate a new dummy Logger without a ResourceBundle;
86 // this gives the racing threads less to do
87 // - reset the counters
88 dummy = Logger.getLogger(LOGGER_PREFIX + getLoopCnt());
89 iaeCnt.set(0);
90 worksCnt.set(0);
91 }
92
93 public void executeRace(WorkerThread wt) {
94 super.executeRace(wt);
95
96 Logger myLogger = null;
97 try {
98 MyWorkerThread mwt = (MyWorkerThread) wt; // short hand
99
100 // Here is the race:
101 // - the target Logger object has already been created by
102 // the DriverThread without a ResourceBundle name
103 // - in parallel, each WorkerThread calls Logger.getLogger()
104 // with a different ResourceBundle name
105 // - Logger.getLogger() should only successfully set the
106 // ResourceBundle name for one WorkerThread; all other
107 // WorkerThread calls to Logger.getLogger() should throw
108 // IllegalArgumentException
109 myLogger = Logger.getLogger(LOGGER_PREFIX + getLoopCnt(),
110 mwt.rbName);
111 if (myLogger.getResourceBundleName().equals(mwt.rbName)) {
112 // no exception and the ResourceBundle names match
113 worksCnt.incrementAndGet(); // ignore return
114 } else {
115 System.err.println(wt.getName()
116 + ": ERROR: expected ResourceBundleName '"
117 + mwt.rbName + "' does not match actual '"
118 + myLogger.getResourceBundleName() + "'");
119 incAndGetFailCnt(); // ignore return
120 }
121 } catch (IllegalArgumentException iae) {
122 iaeCnt.incrementAndGet(); // ignore return
123 } catch (MissingResourceException mre) {
124 // This exception happens when N_THREADS above does not
125 // match the number of MyResources inner classes below.
126 // We exit since this is a coding error.
127 unexpectedException(wt, mre);
128 System.exit(2);
129 }
130 }
131
132 public void checkRaceResults(DriverThread dt) {
133 super.checkRaceResults(dt);
134
135 if (worksCnt.get() != 1) {
136 System.err.println(dt.getName() + ": ERROR: worksCnt should be 1"
137 + ": loopCnt=" + getLoopCnt() + ", worksCnt=" + worksCnt.get());
138 incAndGetFailCnt(); // ignore return
139 } else if (iaeCnt.get() != N_THREADS - 1) {
140 System.err.println(dt.getName() + ": ERROR: iaeCnt should be "
141 + (N_THREADS - 1) + ": loopCnt=" + getLoopCnt()
142 + ", iaeCnt=" + iaeCnt.get());
143 incAndGetFailCnt(); // ignore return
144 }
145 }
146
147 public void oneTimeDriverEpilog(DriverThread dt) {
148 super.oneTimeDriverEpilog(dt);
149
150 // Use the dummy Logger after the testing loop to make sure that
151 // dummy doesn't get optimized away in the testing loop.
152 dummy.info("This is a test message.");
153 }
154
155 // N_THREADS above must match number of MyResources inner classes
156 //
157 public static class MyResources0 extends ListResourceBundle {
158 final static Object[][] contents = {
159 {"sample1", "translation #1 for sample1"},
160 {"sample2", "translation #1 for sample2"},
161 };
162
163 public Object[][] getContents() {
164 return contents;
165 }
166 }
167
168 public static class MyResources1 extends ListResourceBundle {
169 final static Object[][] contents = {
170 {"sample1", "translation #2 for sample1"},
171 {"sample2", "translation #2 for sample2"},
172 };
173
174 public Object[][] getContents() {
175 return contents;
176 }
177 }
178
179 public static class MyResources2 extends ListResourceBundle {
180 final static Object[][] contents = {
181 {"sample1", "translation #3 for sample1"},
182 {"sample2", "translation #3 for sample2"},
183 };
184
185 public Object[][] getContents() {
186 return contents;
187 }
188 }
189
190
191 // WorkerThread with a thread specific ResourceBundle name
192 //
193 public static class MyWorkerThread extends WorkerThread {
194 public final String rbName; // ResourceBundle name
195
196 MyWorkerThread(int workerNum, RacingThreadsTest test) {
197 super(workerNum, test);
198
199 rbName = RESOURCE_PREFIX + workerNum;
200 }
201 }
202}