1 /* 2 * Copyright (c) 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 import java.lang.reflect.Method; 25 import java.util.Arrays; 26 import java.util.LinkedList; 27 import java.util.Objects; 28 import java.util.Queue; 29 import java.util.ResourceBundle; 30 import java.util.concurrent.atomic.AtomicInteger; 31 import java.util.function.Consumer; 32 import java.util.logging.Handler; 33 import java.util.logging.Level; 34 import java.util.logging.LogRecord; 35 import java.util.logging.Logger; 36 37 /** 38 * @test 39 * @bug 8152389 40 * @summary Verify the correct behavior of LogRecord.inferCaller() in particular 41 * when a message is directly logged through the root logger. 42 * @run main/othervm TestInferCaller 43 * @author danielfuchs 44 */ 45 public class TestInferCaller { 46 47 static final class LogEvent { 48 public final String className; 49 public final String methodName; 50 public final LogRecord record; 51 52 public LogEvent(String className, String methodName, LogRecord record) { 53 this.className = className; 54 this.methodName = methodName; 55 this.record = record; 56 } 57 58 } 59 60 static final class TestHandler extends Handler { 61 62 public static final Queue<LogEvent> PUBLISHED = new LinkedList<LogEvent>(); 63 64 public TestHandler() { 65 initLevel(Level.ALL); 66 } 67 68 @Override 69 public void close() throws SecurityException { } 70 @Override 71 public void publish(LogRecord record) { 72 LogEvent event = new LogEvent(record.getSourceClassName(), 73 record.getSourceMethodName(), 74 record); 75 PUBLISHED.add(event); 76 } 77 @Override 78 public void flush() {} 79 80 private void initLevel(Level newLevel) { 81 super.setLevel(newLevel); 82 } 83 84 } 85 86 public void test1(Logger logger) { 87 System.out.println("test1: " + loggerName(logger)); 88 89 AtomicInteger count = new AtomicInteger(); 90 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 91 logger.setLevel(Level.ALL); 92 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 93 94 logger.severe("message " + count.incrementAndGet()); 95 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 96 LogEvent event = TestHandler.PUBLISHED.remove(); 97 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 98 checkEvent(event, this.getClass().getName(), "test1", "message " + count.get()); 99 100 logger.warning("message " + count.incrementAndGet()); 101 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 102 event = TestHandler.PUBLISHED.remove(); 103 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 104 checkEvent(event, this.getClass().getName(), "test1", "message " + count.get()); 105 106 logger.info("message " + count.incrementAndGet()); 107 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 108 event = TestHandler.PUBLISHED.remove(); 109 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 110 checkEvent(event, this.getClass().getName(), "test1", "message " + count.get()); 111 112 logger.config("message " + count.incrementAndGet()); 113 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 114 event = TestHandler.PUBLISHED.remove(); 115 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 116 checkEvent(event, this.getClass().getName(), "test1", "message " + count.get()); 117 118 logger.fine("message " + count.incrementAndGet()); 119 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 120 event = TestHandler.PUBLISHED.remove(); 121 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 122 checkEvent(event, this.getClass().getName(), "test1", "message " + count.get()); 123 124 logger.finer("message " + count.incrementAndGet()); 125 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 126 event = TestHandler.PUBLISHED.remove(); 127 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 128 checkEvent(event, this.getClass().getName(), "test1", "message " + count.get()); 129 130 logger.finest("message " + count.incrementAndGet()); 131 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 132 event = TestHandler.PUBLISHED.remove(); 133 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 134 checkEvent(event, this.getClass().getName(), "test1", "message " + count.get()); 135 } 136 137 void test2(Logger logger) { 138 AtomicInteger count = new AtomicInteger(); 139 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 140 logger.setLevel(Level.ALL); 141 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 142 143 for (Level l : Arrays.asList(Level.SEVERE, Level.WARNING, Level.INFO, 144 Level.CONFIG, Level.FINE, Level.FINER, Level.FINEST)) { 145 System.out.println("test2: " + loggerName(logger) + " " + l); 146 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 147 148 logger.log(l, "message " + count.incrementAndGet()); 149 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 150 LogEvent event = TestHandler.PUBLISHED.remove(); 151 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 152 checkEvent(event, this.getClass().getName(), "test2", "message " + count.get()); 153 154 logger.log(l, "message " + count.incrementAndGet(), "param"); 155 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 156 event = TestHandler.PUBLISHED.remove(); 157 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 158 checkEvent(event, this.getClass().getName(), "test2", "message " + count.get()); 159 160 logger.log(l, "message " + count.incrementAndGet(), new Object[] {"foo", "bar"}); 161 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 162 event = TestHandler.PUBLISHED.remove(); 163 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 164 checkEvent(event, this.getClass().getName(), "test2", "message " + count.get()); 165 166 logger.log(l, "message " + count.incrementAndGet(), new RuntimeException()); 167 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 168 event = TestHandler.PUBLISHED.remove(); 169 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 170 checkEvent(event, this.getClass().getName(), "test2", "message " + count.get()); 171 172 // JDK 8 & 9 only (uses lambda) 173 logger.log(l, () -> "message " + count.incrementAndGet()); 174 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 175 event = TestHandler.PUBLISHED.remove(); 176 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 177 checkEvent(event, this.getClass().getName(), "test2", "message " + count.get()); 178 179 // JDK 8 & 9 only (uses lambda) 180 logger.log(l, new RuntimeException(), () -> "message " + count.incrementAndGet()); 181 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 182 event = TestHandler.PUBLISHED.remove(); 183 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 184 checkEvent(event, this.getClass().getName(), "test2", "message " + count.get()); 185 186 // JDK 9 only: new API 187 logger.logrb(l, (ResourceBundle)null, "message " + count.incrementAndGet(), (Object[]) null); 188 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 189 event = TestHandler.PUBLISHED.remove(); 190 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 191 checkEvent(event, this.getClass().getName(), "test2", "message " + count.get()); 192 193 // JDK 9 only: new API 194 logger.logrb(l, (ResourceBundle)null, "message " + count.incrementAndGet(), new RuntimeException()); 195 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 196 event = TestHandler.PUBLISHED.remove(); 197 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 198 checkEvent(event, this.getClass().getName(), "test2", "message " + count.get()); 199 200 } 201 } 202 203 void test3(Logger logger) { 204 System.out.println("test3: " + loggerName(logger)); 205 AtomicInteger count = new AtomicInteger(); 206 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 207 logger.setLevel(Level.ALL); 208 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 209 210 testReflection(logger, count, "severe", "testReflection"); 211 testReflection(logger, count, "warning", "testReflection"); 212 testReflection(logger, count, "info", "testReflection"); 213 testReflection(logger, count, "config", "testReflection"); 214 testReflection(logger, count, "fine", "testReflection"); 215 testReflection(logger, count, "finer", "testReflection"); 216 testReflection(logger, count, "finest", "testReflection"); 217 } 218 219 void testReflection(Logger logger, AtomicInteger count, String logm, String method) { 220 try { 221 Method m = Logger.class.getMethod(logm, String.class); 222 m.invoke(logger, "message " + count.incrementAndGet()); 223 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 224 LogEvent event = TestHandler.PUBLISHED.remove(); 225 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 226 checkEvent(event, this.getClass().getName(), method, "message " + count.get()); 227 228 Method m2 = Method.class.getMethod("invoke", Object.class, new Object[0].getClass()); 229 m2.invoke(m, logger, new Object[] { "message " + count.incrementAndGet() }); 230 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 231 event = TestHandler.PUBLISHED.remove(); 232 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 233 checkEvent(event, this.getClass().getName(), method, "message " + count.get()); 234 235 m2.invoke(m2, m, new Object[] {logger, new Object[] { "message " + count.incrementAndGet() }}); 236 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 237 event = TestHandler.PUBLISHED.remove(); 238 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 239 checkEvent(event, this.getClass().getName(), method, "message " + count.get()); 240 241 m2.invoke(m2, m2, new Object[] { m, new Object[] {logger, new Object[] { "message " + count.incrementAndGet() }}}); 242 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 243 event = TestHandler.PUBLISHED.remove(); 244 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 245 checkEvent(event, this.getClass().getName(), method, "message " + count.get()); 246 247 } catch (Error | RuntimeException x ) { 248 throw x; 249 } catch (Exception x) { 250 throw new RuntimeException(x); 251 } 252 } 253 254 // JDK 8 & 9 only (uses lambda) 255 public void test4(Logger logger) { 256 System.out.println("test4: " + loggerName(logger)); 257 AtomicInteger count = new AtomicInteger(); 258 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 259 logger.setLevel(Level.ALL); 260 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 261 262 logger.severe(() -> "message " + count.incrementAndGet()); 263 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 264 LogEvent event = TestHandler.PUBLISHED.remove(); 265 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 266 checkEvent(event, this.getClass().getName(), "test4", "message " + count.get()); 267 268 logger.warning(() -> "message " + count.incrementAndGet()); 269 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 270 event = TestHandler.PUBLISHED.remove(); 271 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 272 checkEvent(event, this.getClass().getName(), "test4", "message " + count.get()); 273 274 logger.info(() -> "message " + count.incrementAndGet()); 275 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 276 event = TestHandler.PUBLISHED.remove(); 277 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 278 checkEvent(event, this.getClass().getName(), "test4", "message " + count.get()); 279 280 logger.config(() -> "message " + count.incrementAndGet()); 281 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 282 event = TestHandler.PUBLISHED.remove(); 283 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 284 checkEvent(event, this.getClass().getName(), "test4", "message " + count.get()); 285 286 logger.fine(() -> "message " + count.incrementAndGet()); 287 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 288 event = TestHandler.PUBLISHED.remove(); 289 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 290 checkEvent(event, this.getClass().getName(), "test4", "message " + count.get()); 291 292 logger.finer(() -> "message " + count.incrementAndGet()); 293 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 294 event = TestHandler.PUBLISHED.remove(); 295 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 296 checkEvent(event, this.getClass().getName(), "test4", "message " + count.get()); 297 298 logger.finest(() -> "message " + count.incrementAndGet()); 299 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 300 event = TestHandler.PUBLISHED.remove(); 301 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 302 checkEvent(event, this.getClass().getName(), "test4", "message " + count.get()); 303 } 304 305 // JDK 8 & 9 only (uses lambda) 306 void test5(Logger logger) { 307 System.out.println("test5: " + loggerName(logger)); 308 AtomicInteger count = new AtomicInteger(); 309 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 310 logger.setLevel(Level.ALL); 311 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 312 313 testLambda(count, logger::severe, "testLambda"); 314 testLambda(count, logger::warning, "testLambda"); 315 testLambda(count, logger::info, "testLambda"); 316 testLambda(count, logger::config, "testLambda"); 317 testLambda(count, logger::fine, "testLambda"); 318 testLambda(count, logger::finer, "testLambda"); 319 testLambda(count, logger::finest, "testLambda"); 320 } 321 322 // JDK 8 & 9 only (uses lambda) 323 void testLambda(AtomicInteger count, Consumer<String> logm, String method) { 324 logm.accept("message " + count.incrementAndGet()); 325 assertEquals(1, TestHandler.PUBLISHED.size(), "No event in queue: "); 326 LogEvent event = TestHandler.PUBLISHED.remove(); 327 assertEquals(0, TestHandler.PUBLISHED.size(), "Queue should be empty: "); 328 checkEvent(event, this.getClass().getName(), method, "message " + count.get()); 329 } 330 331 private static String loggerName(Logger logger) { 332 String name = logger.getName(); 333 if (name == null) return "<anonymous>"; 334 if (name.isEmpty()) return "<RootLogger>"; 335 return "\"" + name + "\""; 336 } 337 338 public void test(Logger logger) { 339 test1(logger); 340 test2(logger); 341 test3(logger); 342 343 // JDK 8 & 9 only (uses lambda) 344 test4(logger); 345 test5(logger); 346 } 347 348 public static void main(String[] args) { 349 TestInferCaller test = new TestInferCaller(); 350 Logger root = Logger.getLogger(""); 351 for (Handler h : root.getHandlers()) { 352 h.setLevel(Level.OFF); 353 } 354 root.addHandler(new TestHandler()); 355 356 for (Logger logger : Arrays.asList(root, Logger.getGlobal(), 357 Logger.getAnonymousLogger(), Logger.getLogger("foo.bar"))) { 358 System.out.println("Testing with: " + loggerName(logger) + " " + logger.getClass()); 359 test.test(logger); 360 } 361 } 362 363 private static void assertEquals(int expected, int actual, String what) { 364 if (expected != actual) { 365 throw new RuntimeException(what 366 + "\n\texpected: " + expected 367 + "\n\tactual: " + actual); 368 } 369 } 370 371 private static void assertEquals(String expected, String actual, String what) { 372 if (!Objects.equals(expected, actual)) { 373 throw new RuntimeException(what 374 + "\n\texpected: " + expected 375 + "\n\tactual: " + actual); 376 } 377 } 378 379 private void checkEvent(LogEvent event, String className, String methodName, String message) { 380 assertEquals(className, event.className, "Bad class name: "); 381 assertEquals(className, event.record.getSourceClassName(), "Bad source class name: "); 382 assertEquals(methodName, event.methodName, "Bad method name: "); 383 assertEquals(methodName, event.record.getSourceMethodName(), "Bad source method name: "); 384 assertEquals(message, event.record.getMessage(), "Bad message: "); 385 } 386 387 388 }