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 import java.util.Collections;
24 import java.util.Enumeration;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.concurrent.CopyOnWriteArrayList;
28 import java.util.concurrent.Phaser;
29 import java.util.concurrent.Semaphore;
30 import java.util.logging.Handler;
31 import java.util.logging.LogManager;
32 import java.util.logging.Logger;
33
34
35 /**
36 * @test
37 * @bug 7113878
38 * @summary This is not a test that will check that 7113878 is fixed, but
39 * rather a test that will invoke the modified code & try to verify
40 * that fixing 7113878 has not introduced some big regression.
41 * This test should pass, whether 7113878 is there or not.
42 * @run main/othervm TestLoggerNames
90 }
91 }
92
93 static volatile boolean stop;
94 static volatile Throwable resetFailed;
95 static volatile Throwable checkLoggerNamesFailed;
96 static volatile Phaser phaser = new Phaser(2);
97
98
99 static void checkLoggerNames(List<Logger> loggers) {
100 Enumeration<String> names = LogManager.getLogManager().getLoggerNames();
101 if (names instanceof Iterator) {
102 for (Iterator<?> it = Iterator.class.cast(names); it.hasNext(); ) {
103 try {
104 it.remove();
105 throw new RuntimeException("Iterator supports remove!");
106 } catch (UnsupportedOperationException x) {
107 System.out.println("OK: Iterator doesn't support remove.");
108 }
109 }
110 }
111 List<String> loggerNames = Collections.list(names);
112 if (!loggerNames.contains("")) {
113 throw new RuntimeException("\"\"" +
114 " not found in " + loggerNames);
115 }
116 if (!loggerNames.contains("global")) {
117 throw new RuntimeException("global" +
118 " not found in " + loggerNames);
119 }
120 for (Logger l : loggers) {
121 if (!loggerNames.contains(l.getName())) {
122 throw new RuntimeException(l.getName() +
123 " not found in " + loggerNames);
124 }
125 }
126 System.out.println("Got all expected logger names");
127 }
128
129
130 public static void main(String[] args) throws InterruptedException {
131 LogManager.getLogManager().addLogger(new TestLogger("com.foo.bar.zzz", null));
132 try {
133 Logger.getLogger(null);
134 throw new RuntimeException("Logger.getLogger(null) didn't throw expected NPE");
135 } catch (NullPointerException x) {
136 System.out.println("Got expected NullPointerException for Logger.getLogger(null)");
137 }
138 List<Logger> loggers = new CopyOnWriteArrayList<>();
139 loggers.add(Logger.getLogger("one.two.addMeAChild"));
140 loggers.add(Logger.getLogger("aaa.bbb.replaceMe"));
141 loggers.add(Logger.getLogger("bbb.aaa.addMeAChild"));
142 TestLogger test = (TestLogger)Logger.getLogger("com.foo.bar.zzz");
143 loggers.add(Logger.getLogger("ddd.aaa.addMeAChild"));
144
145 checkLoggerNames(loggers);
146
147 Thread loggerNamesThread = new Thread(() -> {
148 try {
149 while (!stop) {
150 checkLoggerNames(loggers);
151 Thread.sleep(10);
152 if (!stop) {
153 phaser.arriveAndAwaitAdvance();
154 }
155 }
156 } catch (Throwable t) {
157 t.printStackTrace(System.err);
158 checkLoggerNamesFailed = t;
159 }
160 }, "loggerNames");
161
162 Thread resetThread = new Thread(() -> {
163 try {
164 System.out.println("Calling reset...");
165 LogManager.getLogManager().reset();
166 System.out.println("Reset done...");
167 System.out.println("Reset again...");
168 LogManager.getLogManager().reset();
169 System.out.println("Reset done...");
170 } catch(Throwable t) {
171 resetFailed = t;
172 System.err.println("Unexpected exception or error in reset Thread");
173 t.printStackTrace(System.err);
174 }
175 }, "reset");
176
177 resetThread.setDaemon(true);
178 resetThread.start();
180 System.out.println("Waiting for reset to get handlers");
181 test.sem.acquire();
182 try {
183 loggerNamesThread.start();
184 System.out.println("Reset has called getHandlers on " + test.getName());
185 int i = 0;
186 for (Enumeration<String> e = LogManager.getLogManager().getLoggerNames();
187 e.hasMoreElements();) {
188 String name = e.nextElement();
189 if (name.isEmpty()) continue;
190 if (name.endsWith(".addMeAChild")) {
191 Logger l = Logger.getLogger(name+".child");
192 loggers.add(l);
193 System.out.println("*** Added " + l.getName());
194 i++;
195 } else if (name.endsWith("replaceMe")) {
196 Logger l = Logger.getLogger(name);
197 loggers.remove(l);
198 l = Logger.getLogger(name.replace("replaceMe", "meReplaced"));
199 loggers.add(l);
200 System.gc();
201 if (LogManager.getLogManager().getLogger(name) == null) {
202 System.out.println("*** "+ name + " successfully replaced with " + l.getName());
203 }
204 i++;
205 } else {
206 System.out.println("Nothing to do for logger: " + name);
207 }
208 phaser.arriveAndAwaitAdvance();
209 if (i >= 3 && i++ == 3) {
210 System.out.println("Loggers are now: " +
211 Collections.list(LogManager.getLogManager().getLoggerNames()));
212 test.wait.release();
213 test.sem.release();
214 System.out.println("Joining " + resetThread);
215 resetThread.join();
216 }
217 }
218 } catch (RuntimeException | InterruptedException | Error x) {
219 test.wait.release();
220 test.sem.release();
221 throw x;
222 } finally {
223 stop = true;
224 phaser.arriveAndDeregister();
225 loggerNamesThread.join();
226 loggers.clear();
227 }
|
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 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.Enumeration;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.concurrent.CopyOnWriteArrayList;
29 import java.util.concurrent.Phaser;
30 import java.util.concurrent.Semaphore;
31 import java.util.logging.Handler;
32 import java.util.logging.LogManager;
33 import java.util.logging.Logger;
34
35
36 /**
37 * @test
38 * @bug 7113878
39 * @summary This is not a test that will check that 7113878 is fixed, but
40 * rather a test that will invoke the modified code & try to verify
41 * that fixing 7113878 has not introduced some big regression.
42 * This test should pass, whether 7113878 is there or not.
43 * @run main/othervm TestLoggerNames
91 }
92 }
93
94 static volatile boolean stop;
95 static volatile Throwable resetFailed;
96 static volatile Throwable checkLoggerNamesFailed;
97 static volatile Phaser phaser = new Phaser(2);
98
99
100 static void checkLoggerNames(List<Logger> loggers) {
101 Enumeration<String> names = LogManager.getLogManager().getLoggerNames();
102 if (names instanceof Iterator) {
103 for (Iterator<?> it = Iterator.class.cast(names); it.hasNext(); ) {
104 try {
105 it.remove();
106 throw new RuntimeException("Iterator supports remove!");
107 } catch (UnsupportedOperationException x) {
108 System.out.println("OK: Iterator doesn't support remove.");
109 }
110 }
111 // We're not supposed to come here, but if we do then we
112 // need to rewind names...
113 names = LogManager.getLogManager().getLoggerNames();
114 }
115
116 List<String> loggerNames = Collections.list(names);
117 if (!loggerNames.contains("")) {
118 throw new RuntimeException("\"\"" +
119 " not found in " + loggerNames);
120 }
121 if (!loggerNames.contains("global")) {
122 throw new RuntimeException("global" +
123 " not found in " + loggerNames);
124 }
125 for (Logger l : loggers) {
126 if (!loggerNames.contains(l.getName())) {
127 throw new RuntimeException(l.getName() +
128 " not found in " + loggerNames);
129 }
130 }
131 System.out.println("Got all expected logger names");
132 }
133
134
135 public static void main(String[] args) throws InterruptedException {
136 LogManager.getLogManager().addLogger(new TestLogger("com.foo.bar.zzz", null));
137 try {
138 Logger.getLogger(null);
139 throw new RuntimeException("Logger.getLogger(null) didn't throw expected NPE");
140 } catch (NullPointerException x) {
141 System.out.println("Got expected NullPointerException for Logger.getLogger(null)");
142 }
143 List<Logger> loggers = new CopyOnWriteArrayList<>();
144 loggers.add(Logger.getLogger("one.two.addMeAChild"));
145 loggers.add(Logger.getLogger("aaa.bbb.replaceMe"));
146 loggers.add(Logger.getLogger("bbb.aaa.addMeAChild"));
147 TestLogger test = (TestLogger)Logger.getLogger("com.foo.bar.zzz");
148 loggers.add(Logger.getLogger("ddd.aaa.addMeAChild"));
149
150 checkLoggerNames(loggers);
151
152 Thread loggerNamesThread = new Thread(() -> {
153 try {
154 while (!stop) {
155 // Make a defensive copy of the list of loggers that we pass
156 // to checkLoggerNames - in order to make sure that
157 // we won't see new loggers that might appear after
158 // checkLoggerNames has called LogManager.getLoggerNames().
159 // ('loggers' is a live list and the main thread adds and
160 // and removes loggers from it concurrently to this thread).
161 checkLoggerNames(new ArrayList<>(loggers));
162 Thread.sleep(10);
163 if (!stop) {
164 phaser.arriveAndAwaitAdvance();
165 }
166 }
167 } catch (Throwable t) {
168 t.printStackTrace(System.err);
169 checkLoggerNamesFailed = t;
170 // makes sure the main thread isn't going to wait
171 // forever waiting for this dead thread to arrive at the
172 // phaser.
173 phaser.arrive();
174 }
175 }, "loggerNames");
176
177 Thread resetThread = new Thread(() -> {
178 try {
179 System.out.println("Calling reset...");
180 LogManager.getLogManager().reset();
181 System.out.println("Reset done...");
182 System.out.println("Reset again...");
183 LogManager.getLogManager().reset();
184 System.out.println("Reset done...");
185 } catch(Throwable t) {
186 resetFailed = t;
187 System.err.println("Unexpected exception or error in reset Thread");
188 t.printStackTrace(System.err);
189 }
190 }, "reset");
191
192 resetThread.setDaemon(true);
193 resetThread.start();
195 System.out.println("Waiting for reset to get handlers");
196 test.sem.acquire();
197 try {
198 loggerNamesThread.start();
199 System.out.println("Reset has called getHandlers on " + test.getName());
200 int i = 0;
201 for (Enumeration<String> e = LogManager.getLogManager().getLoggerNames();
202 e.hasMoreElements();) {
203 String name = e.nextElement();
204 if (name.isEmpty()) continue;
205 if (name.endsWith(".addMeAChild")) {
206 Logger l = Logger.getLogger(name+".child");
207 loggers.add(l);
208 System.out.println("*** Added " + l.getName());
209 i++;
210 } else if (name.endsWith("replaceMe")) {
211 Logger l = Logger.getLogger(name);
212 loggers.remove(l);
213 l = Logger.getLogger(name.replace("replaceMe", "meReplaced"));
214 loggers.add(l);
215 // Give some chance to the loggerNames thread to arrive at the
216 // phaser first. We don't really care if the logger is actually
217 // replaced this turn - or the next.
218 Thread.sleep(100);
219 System.gc();
220 if (LogManager.getLogManager().getLogger(name) == null) {
221 // The original logger may not have been gc'ed yet, since
222 // it could still be referenced by the list being processed
223 // by the loggerNamesThread, if that thread hasn't arrived
224 // to the phaser yet...
225 System.out.println("*** "+ name
226 + " successfully replaced with " + l.getName());
227 }
228 i++;
229 } else {
230 System.out.println("Nothing to do for logger: " + name);
231 }
232 if (checkLoggerNamesFailed != null) {
233 // The checkLoggerNames thread failed. No need to
234 // continue.
235 break;
236 }
237 // Waits for the checkLoggerNamesThread to arrive
238 phaser.arriveAndAwaitAdvance();
239 if (i >= 3 && i++ == 3) {
240 System.out.println("Loggers are now: " +
241 Collections.list(LogManager.getLogManager().getLoggerNames()));
242 test.wait.release();
243 test.sem.release();
244 System.out.println("Joining " + resetThread);
245 resetThread.join();
246 }
247 }
248 } catch (RuntimeException | InterruptedException | Error x) {
249 test.wait.release();
250 test.sem.release();
251 throw x;
252 } finally {
253 stop = true;
254 phaser.arriveAndDeregister();
255 loggerNamesThread.join();
256 loggers.clear();
257 }
|