/* * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /** * @test * @bug 8140364 * @author danielfuchs * @summary JDK implementation specific unit test for JDK internal artifacts. * This test tests all the public API methods defined in the {@link * java.lang.System.Logger} interface, as well as all the JDK * internal methods defined in the * {@link sun.util.logging.PlatformLogger.Bridge} * interface, with loggers returned by {@link * java.lang.System.LoggerFinder#getLogger(java.lang.String, java.lang.Class)} * and {@link java.lang.System.LoggerFinder#getLocalizedLogger(java.lang.String, * java.util.ResourceBundle, java.lang.Class)} * (using both a null resource bundle and a non null resource bundle). * It calls both the {@link java.lang.System} factory methods and * {@link jdk.internal.logger.LazyLoggers} to obtains those loggers, * and configure them with all possible known levels. * @modules java.base/java.lang:open * java.base/sun.util.logging * java.base/jdk.internal.logger * java.logging/sun.util.logging.internal * @build LoggerFinderBackendTest SystemClassLoader * @run main/othervm -Djava.system.class.loader=SystemClassLoader -Dtest.logger.hidesProvider=true LoggerFinderBackendTest * @run main/othervm -Djava.system.class.loader=SystemClassLoader -Dtest.logger.hidesProvider=false LoggerFinderBackendTest */ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.ResourceBundle; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.function.BooleanSupplier; import java.util.function.Function; import java.util.function.Supplier; import java.lang.System.LoggerFinder; import java.util.logging.ConsoleHandler; import java.util.logging.Handler; import sun.util.logging.PlatformLogger.Level; import java.util.logging.LogManager; import java.util.logging.LogRecord; import java.util.logging.Logger; import sun.util.logging.internal.LoggingProviderImpl; import java.lang.reflect.Module; /** * @author danielfuchs */ public class LoggerFinderBackendTest { // whether the implementation of Logger try to do a best // effort for logp... If the provider is not hidden, then // the logp() implementation comes from LoggerWrapper - which does a // best effort. Otherwise, it comes from the default provider // which does support logp. static final boolean BEST_EFFORT_FOR_LOGP = !Boolean.getBoolean("test.logger.hidesProvider"); static final boolean VERBOSE = false; static final Class<java.lang.System.Logger> spiLoggerClass = java.lang.System.Logger.class; static final Class<java.lang.System.Logger> jdkLoggerClass = java.lang.System.Logger.class; static final Class<sun.util.logging.PlatformLogger.Bridge> bridgeLoggerClass = sun.util.logging.PlatformLogger.Bridge.class; /** Use to retrieve the log records that were produced by the JUL backend */ static class LoggerTesterHandler extends Handler { public final List<LogRecord> records = Collections.synchronizedList(new ArrayList<>()); @Override public void publish(LogRecord record) { record.getSourceClassName(); record.getSourceMethodName(); records.add(record); } @Override public void flush() { } @Override public void close() throws SecurityException { records.clear(); } public void reset() { records.clear(); } } /** The {@link LoggerTesterHandler} handler is added to the root logger. */ static final LoggerTesterHandler handler = new LoggerTesterHandler(); static { for (Handler h : Logger.getLogger("").getHandlers()) { if (h instanceof ConsoleHandler) { Logger.getLogger("").removeHandler(h); } } Logger.getLogger("").addHandler(handler); } /** * A resource handler parameter that will be used when calling out the * logrb-like methods - as well as when calling the level-specific * methods that take a ResourceBundle parameter. */ public static class ResourceBundeParam extends ResourceBundle { Map<String, String> map = Collections.synchronizedMap(new LinkedHashMap<>()); @Override protected Object handleGetObject(String key) { map.putIfAbsent(key, "${"+key+"}"); return map.get(key); } @Override public Enumeration<String> getKeys() { return Collections.enumeration(new LinkedHashSet<>(map.keySet())); } } final static ResourceBundle bundleParam = ResourceBundle.getBundle(ResourceBundeParam.class.getName()); /** * A resource handler parameter that will be used when creating localized * loggers by calling {@link * LoggerFinder#getLocalizedLogger(java.lang.String, java.util.ResourceBundle, java.lang.Class)}. */ public static class ResourceBundeLocalized extends ResourceBundle { Map<String, String> map = Collections.synchronizedMap(new LinkedHashMap<>()); @Override protected Object handleGetObject(String key) { map.putIfAbsent(key, "Localized:${"+key+"}"); return map.get(key); } @Override public Enumeration<String> getKeys() { return Collections.enumeration(new LinkedHashSet<>(map.keySet())); } } /** * The Levels enum is used to call all the level-specific methods on * a logger instance. To minimize the amount of code it uses reflection * to do so. */ static Lookup lookup = MethodHandles.lookup(); public enum Levels { /** Used to call all forms of Logger.log?(SEVERE, ...) */ SEVERE("severe", bridgeLoggerClass, Level.SEVERE, null, "error", false), /** Used to call all forms of Logger.log?(WARNING,...) */ WARNING("warning", bridgeLoggerClass, Level.WARNING, "warning", "warning", false), /** Used to call all forms of Logger.log?(INFO,...) */ INFO("info", bridgeLoggerClass, Level.INFO, "info", "info", false), /** Used to call all forms of Logger.log?(CONFIG,...) */ CONFIG("config", bridgeLoggerClass, Level.CONFIG, null, "debug", false), /** Used to call all forms of Logger.log?(FINE,...) */ FINE("fine", bridgeLoggerClass, Level.FINE, null, "debug", false), /** Used to call all forms of Logger.log?(FINER,...) */ FINER("finer", bridgeLoggerClass, Level.FINER, null, "trace", false), /** Used to call all forms of Logger.log?(FINEST,...) */ FINEST("finest", bridgeLoggerClass, Level.FINEST, null, "trace", false), ; public final String method; // The name of the level-specific method to call public final Class<?> definingClass; // which interface j.u.logger.Logger or j.u.logging.spi.Logger defines it public final Level platformLevel; // The platform Level it will be mapped to in Jul when Jul is the backend public final String jdkExtensionToJUL; // The name of the method called on the JUL logger when JUL is the backend public final String julToJdkExtension; // The name of the method called in the jdk extension by the default impl in jdk.internal.logging.Logger public final String enableMethod; // The name of the isXxxxEnabled method public final boolean hasSpecificIsEnabled; Levels(String method, Class<?> definingClass, Level defaultMapping, String jdkExtensionToJUL, String julToJdkExtension, boolean hasSpecificIsEnabled) { this.method = method; this.definingClass = definingClass; this.platformLevel = defaultMapping; this.jdkExtensionToJUL = jdkExtensionToJUL; this.julToJdkExtension = julToJdkExtension; this.hasSpecificIsEnabled = hasSpecificIsEnabled; if (hasSpecificIsEnabled) { this.enableMethod = "is" + method.substring(0,1).toUpperCase() + method.substring(1) + "Enabled"; } else { this.enableMethod = "isLoggable"; } } /* * calls this level specific method - e.g. if this==INFO: logger.info(msg); */ public void level(Object logger, String msg) { MethodType mt = MethodType.methodType(void.class, Level.class, String.class); invoke("log", logger, mt, platformLevel, msg); } /* * calls this level specific method - e.g. if this==INFO: logger.info(msgSupplier); */ public void level(Object logger, Supplier<String> msgSupplier) { MethodType mt = MethodType.methodType(void.class, Level.class, Supplier.class); invoke("log", logger, mt, platformLevel, msgSupplier); } /* * calls this level specific method - e.g. if this==INFO: logger.info(msg, params); */ public void level(Object logger, String msg, Object... params) { MethodType mt = MethodType.methodType(void.class, Level.class, String.class, Object[].class); invoke("log", logger, mt, platformLevel, msg, params); } /* * calls this level specific method - e.g. if this==INFO: logger.info(msg, thrown); */ public void level(Object logger, String msg, Throwable thrown) { MethodType mt = MethodType.methodType(void.class, Level.class, String.class, Throwable.class); invoke("log", logger, mt, platformLevel, msg, thrown); } /* * calls this level specific method - e.g. if this==INFO: logger.info(msgSupplier, thrown); */ public void level(Object logger, Supplier<String> msgSupplier, Throwable thrown) { MethodType mt = MethodType.methodType(void.class, Level.class, Throwable.class, Supplier.class); invoke("log", logger, mt, platformLevel, thrown, msgSupplier); } /* * calls this level specific method - e.g. if this==INFO: logger.info(bundle, msg); */ public void level(Object logger, String msg, ResourceBundle bundle) { MethodType mt = MethodType.methodType(void.class, Level.class, ResourceBundle.class, String.class, Object[].class); invoke("logrb", logger, mt, platformLevel, bundle, msg, null); } public void level(Object logger, String msg, ResourceBundle bundle, Object... params) { MethodType mt = MethodType.methodType(void.class, Level.class, ResourceBundle.class, String.class, Object[].class); invoke("logrb", logger, mt, platformLevel, bundle, msg, params); } public void level(Object logger, String msg, ResourceBundle bundle, Throwable thrown) { MethodType mt = MethodType.methodType(void.class, Level.class, ResourceBundle.class, String.class, Throwable.class); invoke("logrb", logger, mt, platformLevel, bundle, msg, thrown); } public boolean isEnabled(Object logger) { try { if (hasSpecificIsEnabled) { MethodType mt = MethodType.methodType(boolean.class); final MethodHandle handle = lookup.findVirtual(definingClass, enableMethod, mt).bindTo(logger); return Boolean.class.cast(handle.invoke()); } else { MethodType mt = MethodType.methodType(boolean.class, Level.class); final MethodHandle handle = lookup.findVirtual(definingClass, enableMethod, mt).bindTo(logger); return Boolean.class.cast(handle.invoke(platformLevel)); } } catch (Throwable ex) { throw new RuntimeException(ex); } } private void invoke(String method, Object logger, MethodType mt, Object... args) { try { final int last = mt.parameterCount()-1; boolean isVarargs = mt.parameterType(last).isArray(); final MethodHandle handle = lookup.findVirtual(definingClass, method, mt).bindTo(logger); final StringBuilder builder = new StringBuilder(); builder.append(logger.getClass().getSimpleName()).append('.') .append(method).append('('); String sep = ""; int offset = 0; Object[] params = args; for (int i=0; (i-offset) < params.length; i++) { if (isVarargs && i == last) { offset = last; params = (Object[])args[i]; if (params == null) break; } Object p = params[i - offset]; String quote = (p instanceof String) ? "\"" : ""; builder.append(sep).append(quote).append(p).append(quote); sep = ", "; } builder.append(')'); if (verbose) { System.out.println(builder); } handle.invokeWithArguments(args); } catch (Throwable ex) { throw new RuntimeException(ex); } } }; static interface Checker<LogResult, L> extends BiFunction<LogResult, L, Void> {} static interface JdkLogTester extends BiFunction<sun.util.logging.PlatformLogger.Bridge, Level, Void> {} static interface SpiLogTester extends BiFunction<java.lang.System.Logger, java.lang.System.Logger.Level, Void> {} static interface MethodInvoker<LOGGER, LEVEL> { public void logX(LOGGER logger, LEVEL level, Object... args); } public enum JdkLogMethodInvoker implements MethodInvoker<sun.util.logging.PlatformLogger.Bridge, Level> { /** * Tests {@link * jdk.internal.logging.Logger#log(Level, String, Object...)}; **/ LOG_STRING_PARAMS("log", MethodType.methodType(void.class, Level.class, String.class, Object[].class)), /** * Tests {@link * jdk.internal.logging.Logger#log(Level, String, Throwable)}; **/ LOG_STRING_THROWN("log", MethodType.methodType(void.class, Level.class, String.class, Throwable.class)), /** * Tests {@link * jdk.internal.logging.Logger#log(Level, Supplier<String>)}; **/ LOG_SUPPLIER("log", MethodType.methodType(void.class, Level.class, Supplier.class)), /** * Tests {@link * jdk.internal.logging.Logger#log(Level, Throwable, Supplier<String>)}; **/ LOG_SUPPLIER_THROWN("log", MethodType.methodType(void.class, Level.class, Throwable.class, Supplier.class)), /** * Tests {@link * jdk.internal.logging.Logger#logp(Level, String, String, String)}; **/ LOGP_STRING("logp", MethodType.methodType(void.class, Level.class, String.class, String.class, String.class)), /** * Tests {@link * jdk.internal.logging.Logger#logp(Level, String, String, String, Object...)}; **/ LOGP_STRING_PARAMS("logp", MethodType.methodType(void.class, Level.class, String.class, String.class, String.class, Object[].class)), /** * Tests {@link * jdk.internal.logging.Logger#logp(Level, String, String, String, Throwable)}; **/ LOGP_STRING_THROWN("logp", MethodType.methodType(void.class, Level.class, String.class, String.class, String.class, Throwable.class)), /** * Tests {@link * jdk.internal.logging.Logger#logp(Level, String, String, Supplier<String>)}; **/ LOGP_SUPPLIER("logp", MethodType.methodType(void.class, Level.class, String.class, String.class, Supplier.class)), /** * Tests {@link * jdk.internal.logging.Logger#logp(Level, String, String, Throwable, Supplier<String>)}; **/ LOGP_SUPPLIER_THROWN("logp", MethodType.methodType(void.class, Level.class, String.class, String.class, Throwable.class, Supplier.class)), /** * Tests {@link * jdk.internal.logging.Logger#logrb(Level, ResourceBundle, String, Object...)}; **/ LOGRB_STRING_PARAMS("logrb", MethodType.methodType(void.class, Level.class, ResourceBundle.class, String.class, Object[].class)), /** * Tests {@link * jdk.internal.logging.Logger#logrb(Level, ResourceBundle, String, Throwable)}; **/ LOGRB_STRING_THROWN("logrb", MethodType.methodType(void.class, Level.class, ResourceBundle.class, String.class, Throwable.class)), /** * Tests {@link * jdk.internal.logging.Logger#logrb(Level, String, String, ResourceBundle, String, Object...)}; **/ LOGRBP_STRING_PARAMS("logrb", MethodType.methodType(void.class, Level.class, String.class, String.class, ResourceBundle.class, String.class, Object[].class)), /** * Tests {@link * jdk.internal.logging.Logger#logrb(Level, String, String, ResourceBundle, String, Throwable)}; **/ LOGRBP_STRING_THROWN("logrb", MethodType.methodType(void.class, Level.class, String.class, String.class, ResourceBundle.class, String.class, Throwable.class)), ; final MethodType mt; final String method; JdkLogMethodInvoker(String method, MethodType mt) { this.mt = mt; this.method = method; } Object[] makeArgs(Level level, Object... rest) { List<Object> list = new ArrayList<>(rest == null ? 1 : rest.length + 1); list.add(level); if (rest != null) { list.addAll(Arrays.asList(rest)); } return list.toArray(new Object[list.size()]); } @Override public void logX(sun.util.logging.PlatformLogger.Bridge logger, Level level, Object... args) { try { MethodHandle handle = lookup.findVirtual(bridgeLoggerClass, method, mt).bindTo(logger); final int last = mt.parameterCount()-1; boolean isVarargs = mt.parameterType(last).isArray(); args = makeArgs(level, args); final StringBuilder builder = new StringBuilder(); builder.append(logger.getClass().getSimpleName()).append('.') .append(this.method).append('('); String sep = ""; int offset = 0; Object[] params = args; for (int i=0; (i-offset) < params.length; i++) { if (isVarargs && i == last) { offset = last; params = (Object[])args[i]; if (params == null) break; } Object p = params[i - offset]; String quote = (p instanceof String) ? "\"" : ""; p = p instanceof Level ? "Level."+p : p; builder.append(sep).append(quote).append(p).append(quote); sep = ", "; } builder.append(')'); if (verbose) System.out.println(builder); handle.invokeWithArguments(args); } catch (Throwable ex) { throw new RuntimeException(ex); } } } public enum SpiLogMethodInvoker implements MethodInvoker<java.lang.System.Logger, java.lang.System.Logger.Level> { /** * Tests {@link * jdk.internal.logging.Logger#log(Level, String, Object...)}; **/ LOG_STRING_PARAMS("log", MethodType.methodType(void.class, java.lang.System.Logger.Level.class, String.class, Object[].class)), /** * Tests {@link * jdk.internal.logging.Logger#log(Level, String, Throwable)}; **/ LOG_STRING_THROWN("log", MethodType.methodType(void.class, java.lang.System.Logger.Level.class, String.class, Throwable.class)), /** * Tests {@link * jdk.internal.logging.Logger#log(Level, Supplier<String>)}; **/ LOG_SUPPLIER("log", MethodType.methodType(void.class, java.lang.System.Logger.Level.class, Supplier.class)), /** * Tests {@link * jdk.internal.logging.Logger#log(Level, Throwable, Supplier<String>)}; **/ LOG_SUPPLIER_THROWN("log", MethodType.methodType(void.class, java.lang.System.Logger.Level.class, Supplier.class, Throwable.class)), /** * Tests {@link * jdk.internal.logging.Logger#log(Level, Supplier<String>)}; **/ LOG_OBJECT("log", MethodType.methodType(void.class, java.lang.System.Logger.Level.class, Object.class)), /** * Tests {@link * jdk.internal.logging.Logger#logrb(Level, ResourceBundle, String, Object...)}; **/ LOGRB_STRING_PARAMS("log", MethodType.methodType(void.class, java.lang.System.Logger.Level.class, ResourceBundle.class, String.class, Object[].class)), /** * Tests {@link * jdk.internal.logging.Logger#logrb(Level, ResourceBundle, String, Throwable)}; **/ LOGRB_STRING_THROWN("log", MethodType.methodType(void.class, java.lang.System.Logger.Level.class, ResourceBundle.class, String.class, Throwable.class)), ; final MethodType mt; final String method; SpiLogMethodInvoker(String method, MethodType mt) { this.mt = mt; this.method = method; } Object[] makeArgs(java.lang.System.Logger.Level level, Object... rest) { List<Object> list = new ArrayList<>(rest == null ? 1 : rest.length + 1); list.add(level); if (rest != null) { list.addAll(Arrays.asList(rest)); } return list.toArray(new Object[list.size()]); } @Override public void logX(java.lang.System.Logger logger, java.lang.System.Logger.Level level, Object... args) { try { MethodHandle handle = lookup.findVirtual(spiLoggerClass, method, mt).bindTo(logger); final int last = mt.parameterCount()-1; boolean isVarargs = mt.parameterType(last).isArray(); args = makeArgs(level, args); final StringBuilder builder = new StringBuilder(); builder.append(logger.getClass().getSimpleName()).append('.') .append(this.method).append('('); String sep = ""; int offset = 0; Object[] params = args; for (int i=0; (i-offset) < params.length; i++) { if (isVarargs && i == last) { offset = last; params = (Object[])args[i]; if (params == null) break; } Object p = params[i - offset]; String quote = (p instanceof String) ? "\"" : ""; p = p instanceof Level ? "Level."+p : p; builder.append(sep).append(quote).append(p).append(quote); sep = ", "; } builder.append(')'); if (verbose) System.out.println(builder); handle.invokeWithArguments(args); } catch (Throwable ex) { throw new RuntimeException(ex); } } } public abstract static class BackendTester<BackendRecord> { static final Level[] levelMap = {Level.ALL, Level.FINER, Level.FINE, Level.INFO, Level.WARNING, Level.SEVERE, Level.OFF}; abstract class BackendAdaptor { public abstract String getLoggerName(BackendRecord res); public abstract Object getLevel(BackendRecord res); public abstract String getMessage(BackendRecord res); public abstract String getSourceClassName(BackendRecord res); public abstract String getSourceMethodName(BackendRecord res); public abstract Throwable getThrown(BackendRecord res); public abstract ResourceBundle getResourceBundle(BackendRecord res); public abstract void setLevel(java.lang.System.Logger logger, Level level); public abstract void setLevel(java.lang.System.Logger logger, java.lang.System.Logger.Level level); public abstract List<BackendRecord> getBackendRecords(); public abstract void resetBackendRecords(); public boolean shouldBeLoggable(Levels level, Level loggerLevel) { final Level logLevel = level.platformLevel; return shouldBeLoggable(logLevel, loggerLevel); } public boolean shouldBeLoggable(Level logLevel, Level loggerLevel) { return loggerLevel.intValue() != Level.OFF.intValue() && logLevel.intValue() >= loggerLevel.intValue(); } public boolean shouldBeLoggable(java.lang.System.Logger.Level logLevel, java.lang.System.Logger.Level loggerLevel) { return loggerLevel != java.lang.System.Logger.Level.OFF && logLevel.ordinal() >= loggerLevel.ordinal(); } public boolean isLoggable(java.lang.System.Logger logger, Level l) { return bridgeLoggerClass.cast(logger).isLoggable(l); } public String getCallerClassName(Levels level, String clazz) { return clazz != null ? clazz : Levels.class.getName(); } public String getCallerClassName(MethodInvoker<?,?> logMethod, String clazz) { return clazz != null ? clazz : logMethod.getClass().getName(); } public String getCallerMethodName(Levels level, String method) { return method != null ? method : "invoke"; } public String getCallerMethodName(MethodInvoker<?,?> logMethod, String method) { return method != null ? method : "logX"; } public Object getMappedLevel(Object level) { return level; } public Level toJUL(java.lang.System.Logger.Level level) { return levelMap[level.ordinal()]; } } public final boolean isSystem; public final Class<? extends java.lang.System.Logger> restrictedTo; public final ResourceBundle localized; public BackendTester(boolean isSystem) { this(isSystem,null,null); } public BackendTester(boolean isSystem, ResourceBundle localized) { this(isSystem,null,localized); } public BackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo) { this(isSystem, restrictedTo, null); } public BackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo, ResourceBundle localized) { this.isSystem = isSystem; this.restrictedTo = restrictedTo; this.localized = localized; } public java.lang.System.Logger convert(java.lang.System.Logger logger) { return logger; } public static Level[] LEVELS = { Level.OFF, Level.SEVERE, Level.WARNING, Level.INFO, Level.CONFIG, Level.FINE, Level.FINER, Level.FINEST, Level.ALL }; abstract BackendAdaptor adaptor(); protected void checkRecord(Levels test, BackendRecord res, String loggerName, Level level, String msg, String className, String methodName, Throwable thrown, ResourceBundle bundle, Object... params) { checkRecord(test, res, loggerName, level, ()->msg, className, methodName, thrown, bundle, params); } protected void checkRecord(Levels test, BackendRecord res, String loggerName, Level level, Supplier<String> msg, String className, String methodName, Throwable thrown, ResourceBundle bundle, Object... params) { checkRecord(test.method, res, loggerName, level, msg, className, methodName, thrown, bundle, params); } protected <L> void checkRecord(String logMethod, BackendRecord res, String loggerName, L level, Supplier<String> msg, String className, String methodName, Throwable thrown, ResourceBundle bundle, Object... params) { final BackendAdaptor analyzer = adaptor(); if (! Objects.equals(analyzer.getLoggerName(res), loggerName)) { throw new RuntimeException(logMethod+": expected logger name " + loggerName + " got " + analyzer.getLoggerName(res)); } if (!Objects.equals(analyzer.getLevel(res), analyzer.getMappedLevel(level))) { throw new RuntimeException(logMethod+": expected level " + analyzer.getMappedLevel(level) + " got " + analyzer.getLevel(res)); } if (!Objects.equals(analyzer.getMessage(res), msg.get())) { throw new RuntimeException(logMethod+": expected message \"" + msg.get() + "\" got \"" + analyzer.getMessage(res) +"\""); } if (!Objects.equals(analyzer.getSourceClassName(res), className)) { throw new RuntimeException(logMethod + ": expected class name \"" + className + "\" got \"" + analyzer.getSourceClassName(res) +"\""); } if (!Objects.equals(analyzer.getSourceMethodName(res), methodName)) { throw new RuntimeException(logMethod + ": expected method name \"" + methodName + "\" got \"" + analyzer.getSourceMethodName(res) +"\""); } final Throwable thrownRes = analyzer.getThrown(res); if (!Objects.equals(thrownRes, thrown)) { throw new RuntimeException(logMethod + ": expected throwable \"" + thrown + "\" got \"" + thrownRes + "\""); } if (!Objects.equals(analyzer.getResourceBundle(res), bundle)) { throw new RuntimeException(logMethod + ": expected bundle \"" + bundle + "\" got \"" + analyzer.getResourceBundle(res) +"\""); } } public void testLevel(Levels level, java.lang.System.Logger logger, String msg) { Runnable test = () -> level.level(logger, msg); Checker<BackendRecord, Level> check = (res, l) -> { checkRecord(level, res, logger.getName(), l, msg, adaptor().getCallerClassName(level, Levels.class.getName()), adaptor().getCallerMethodName(level, "invoke"), null, localized); return null; }; test("msg", level, logger, test, check); } public void testLevel(Levels level, java.lang.System.Logger logger, String msg, Object... params) { Runnable test = () -> level.level(logger, msg, (Object[])params); Checker<BackendRecord, Level> check = (res, l) -> { checkRecord(level, res, logger.getName(), l, msg, adaptor().getCallerClassName(level, Levels.class.getName()), adaptor().getCallerMethodName(level, "invoke"), null, localized, (Object[])params); return null; }; test("msg, params", level, logger, test, check); } public void testLevel(Levels level, java.lang.System.Logger logger, String msg, Throwable thrown) { Runnable test = () -> level.level(logger, msg, thrown); Checker<BackendRecord, Level> check = (res, l) -> { checkRecord(level, res, logger.getName(), l, msg, adaptor().getCallerClassName(level, Levels.class.getName()), adaptor().getCallerMethodName(level, "invoke"), thrown, localized); return null; }; test("msg, thrown", level, logger, test, check); } public void testLevel(Levels level, java.lang.System.Logger logger, Supplier<String> msg) { Runnable test = () -> level.level(logger, msg); Checker<BackendRecord, Level> check = (res, l) -> { checkRecord(level, res, logger.getName(), l, msg, adaptor().getCallerClassName(level, Levels.class.getName()), adaptor().getCallerMethodName(level, "invoke"), null, null); return null; }; test("msgSupplier", level, logger, test, check); } public void testLevel(Levels level, java.lang.System.Logger logger, Supplier<String> msg, Throwable thrown) { Runnable test = () -> level.level(logger, msg, thrown); Checker<BackendRecord, Level> check = (res, l) -> { checkRecord(level, res, logger.getName(), l, msg, adaptor().getCallerClassName(level, Levels.class.getName()), adaptor().getCallerMethodName(level, "invoke"), thrown, null); return null; }; test("throw, msgSupplier", level, logger, test, check); } public void testLevel(Levels level, java.lang.System.Logger logger, String msg, ResourceBundle bundle) { Runnable test = () -> level.level(logger, msg, bundle); Checker<BackendRecord, Level> check = (res, l) -> { checkRecord(level, res, logger.getName(), l, msg, adaptor().getCallerClassName(level, Levels.class.getName()), adaptor().getCallerMethodName(level, "invoke"), null, bundle); return null; }; test("bundle, msg", level, logger, test, check); } public void testLevel(Levels level, java.lang.System.Logger logger, String msg, ResourceBundle bundle, Object... params) { Runnable test = () -> level.level(logger, msg, bundle, (Object[])params); Checker<BackendRecord, Level> check = (res, l) -> { checkRecord(level, res, logger.getName(), l, msg, adaptor().getCallerClassName(level, Levels.class.getName()), adaptor().getCallerMethodName(level, "invoke"), null, bundle, (Object[])params); return null; }; test("bundle, msg, params", level, logger, test, check); } public void testLevel(Levels level, java.lang.System.Logger logger, String msg, ResourceBundle bundle, Throwable thrown) { Runnable test = () -> level.level(logger, msg, bundle, thrown); Checker<BackendRecord, Level> check = (res, l) -> { checkRecord(level, res, logger.getName(), l, msg, adaptor().getCallerClassName(level, Levels.class.getName()), adaptor().getCallerMethodName(level, "invoke"), thrown, bundle); return null; }; test("bundle, msg, throwable", level, logger, test, check); } // System.Logger public void testSpiLog(java.lang.System.Logger logger, String msg) { Checker<BackendRecord, java.lang.System.Logger.Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( SpiLogMethodInvoker.LOG_STRING_PARAMS, SpiLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( SpiLogMethodInvoker.LOG_STRING_PARAMS, "logX"), null, localized); return null; }; SpiLogTester tester = (x, level) -> { SpiLogMethodInvoker.LOG_STRING_PARAMS.logX(x, level, msg, (Object[])null); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", \"" + msg + "\")"; testSpiLog(logger, tester, check, nameProducer); } public void testSpiLog(java.lang.System.Logger logger, ResourceBundle bundle, String msg) { Checker<BackendRecord, java.lang.System.Logger.Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( SpiLogMethodInvoker.LOGRB_STRING_PARAMS, SpiLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( SpiLogMethodInvoker.LOGRB_STRING_PARAMS, "logX"), null, bundle); return null; }; SpiLogTester tester = (x, level) -> { SpiLogMethodInvoker.LOGRB_STRING_PARAMS.logX(x, level, bundle, msg, (Object[])null); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", bundle, \"" + msg + "\")"; testSpiLog(logger, tester, check, nameProducer); } public void testSpiLog(java.lang.System.Logger logger, String msg, Object... params) { Checker<BackendRecord, java.lang.System.Logger.Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( SpiLogMethodInvoker.LOG_STRING_PARAMS, SpiLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( SpiLogMethodInvoker.LOG_STRING_PARAMS, "logX"), null, localized, params); return null; }; SpiLogTester tester = (x, level) -> { SpiLogMethodInvoker.LOG_STRING_PARAMS.logX(x, level, msg, params); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", \"" + msg + "\", params...)"; testSpiLog(logger, tester, check, nameProducer); } public void testSpiLog(java.lang.System.Logger logger, ResourceBundle bundle, String msg, Object... params) { Checker<BackendRecord, java.lang.System.Logger.Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( SpiLogMethodInvoker.LOGRB_STRING_PARAMS, SpiLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( SpiLogMethodInvoker.LOGRB_STRING_PARAMS, "logX"), null, bundle, params); return null; }; SpiLogTester tester = (x, level) -> { SpiLogMethodInvoker.LOGRB_STRING_PARAMS.logX(x, level, bundle, msg, params); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", bundle, \"" + msg + "\", params...)"; testSpiLog(logger, tester, check, nameProducer); } public void testSpiLog(java.lang.System.Logger logger, String msg, Throwable thrown) { Checker<BackendRecord, java.lang.System.Logger.Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( SpiLogMethodInvoker.LOG_STRING_THROWN, SpiLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( SpiLogMethodInvoker.LOG_STRING_THROWN, "logX"), thrown, localized); return null; }; SpiLogTester tester = (x, level) -> { SpiLogMethodInvoker.LOG_STRING_THROWN.logX(x, level, msg, thrown); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", \"" + msg + "\", thrown)"; testSpiLog(logger, tester, check, nameProducer); } public void testSpiLog(java.lang.System.Logger logger, ResourceBundle bundle, String msg, Throwable thrown) { Checker<BackendRecord, java.lang.System.Logger.Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( SpiLogMethodInvoker.LOGRB_STRING_THROWN, SpiLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( SpiLogMethodInvoker.LOGRB_STRING_THROWN, "logX"), thrown, bundle); return null; }; SpiLogTester tester = (x, level) -> { SpiLogMethodInvoker.LOGRB_STRING_THROWN.logX(x, level, bundle, msg, thrown); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", bundle, \"" + msg + "\", thrown)"; testSpiLog(logger, tester, check, nameProducer); } public void testSpiLog(java.lang.System.Logger logger, Supplier<String> msg) { Checker<BackendRecord, java.lang.System.Logger.Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, msg, adaptor().getCallerClassName( SpiLogMethodInvoker.LOG_SUPPLIER, SpiLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( SpiLogMethodInvoker.LOG_SUPPLIER, "logX"), null, null); return null; }; SpiLogTester tester = (x, level) -> { SpiLogMethodInvoker.LOG_SUPPLIER.logX(x, level, msg); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", () -> \"" + msg.get() + "\")"; testSpiLog(logger, tester, check, nameProducer); } public void testSpiLog(java.lang.System.Logger logger, Object obj) { Checker<BackendRecord, java.lang.System.Logger.Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> obj.toString(), adaptor().getCallerClassName( SpiLogMethodInvoker.LOG_OBJECT, SpiLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( SpiLogMethodInvoker.LOG_OBJECT, "logX"), null, null); return null; }; SpiLogTester tester = (x, level) -> { SpiLogMethodInvoker.LOG_OBJECT.logX(x, level, obj); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", new "+obj.getClass().getSimpleName()+"(\"" + obj.toString() + "\"))"; testSpiLog(logger, tester, check, nameProducer); } public void testSpiLog(java.lang.System.Logger logger, Throwable thrown, Supplier<String> msg) { Checker<BackendRecord, java.lang.System.Logger.Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, msg, adaptor().getCallerClassName( SpiLogMethodInvoker.LOG_SUPPLIER_THROWN, SpiLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( SpiLogMethodInvoker.LOG_SUPPLIER_THROWN, "logX"), thrown, null); return null; }; SpiLogTester tester = (x, level) -> { SpiLogMethodInvoker.LOG_SUPPLIER_THROWN.logX(x, level, msg, thrown); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", () -> \"" + msg.get() + "\", thrown)"; testSpiLog(logger, tester, check, nameProducer); } // JDK public void testLog(java.lang.System.Logger logger, String msg) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOG_STRING_PARAMS, JdkLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( JdkLogMethodInvoker.LOG_STRING_PARAMS, "logX"), null, localized); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOG_STRING_PARAMS.logX(x, level, msg, (Object[])null); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", \"" + msg + "\")"; testJdkLog(logger, tester, check, nameProducer); } public void testLogrb(java.lang.System.Logger logger, ResourceBundle bundle, String msg) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOGRB_STRING_PARAMS, JdkLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( JdkLogMethodInvoker.LOGRB_STRING_PARAMS, "logX"), null, bundle); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGRB_STRING_PARAMS.logX(x, level, bundle, msg, (Object[])null); return null; }; Function<String, String> nameProducer = (l) -> "logrb(Level." + l + ", bundle, \"" + msg + "\")"; testJdkLog(logger, tester, check, nameProducer); } public void testLog(java.lang.System.Logger logger, String msg, Object... params) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOG_STRING_PARAMS, JdkLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( JdkLogMethodInvoker.LOG_STRING_PARAMS, "logX"), null, localized, params); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOG_STRING_PARAMS.logX(x, level, msg, params); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", \"" + msg + "\", params...)"; testJdkLog(logger, tester, check, nameProducer); } public void testLogrb(java.lang.System.Logger logger, ResourceBundle bundle, String msg, Object... params) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOGRB_STRING_PARAMS, JdkLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( JdkLogMethodInvoker.LOGRB_STRING_PARAMS, "logX"), null, bundle, params); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGRB_STRING_PARAMS.logX(x, level, bundle, msg, params); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", bundle, \"" + msg + "\", params...)"; testJdkLog(logger, tester, check, nameProducer); } public void testLog(java.lang.System.Logger logger, String msg, Throwable thrown) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOG_STRING_THROWN, JdkLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( JdkLogMethodInvoker.LOG_STRING_THROWN, "logX"), thrown, localized); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOG_STRING_THROWN.logX(x, level, msg, thrown); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", \"" + msg + "\", thrown)"; testJdkLog(logger, tester, check, nameProducer); } public void testLogrb(java.lang.System.Logger logger, ResourceBundle bundle, String msg, Throwable thrown) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOGRB_STRING_THROWN, JdkLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( JdkLogMethodInvoker.LOGRB_STRING_THROWN, "logX"), thrown, bundle); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGRB_STRING_THROWN.logX(x, level, bundle, msg, thrown); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", bundle, \"" + msg + "\", thrown)"; testJdkLog(logger, tester, check, nameProducer); } public void testLog(java.lang.System.Logger logger, Supplier<String> msg) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOG_SUPPLIER, JdkLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( JdkLogMethodInvoker.LOG_SUPPLIER, "logX"), null, null); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOG_SUPPLIER.logX(x, level, msg); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", () -> \"" + msg.get() + "\")"; testJdkLog(logger, tester, check, nameProducer); } public void testLog(java.lang.System.Logger logger, Throwable thrown, Supplier<String> msg) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOG_SUPPLIER_THROWN, JdkLogMethodInvoker.class.getName()), adaptor().getCallerMethodName( JdkLogMethodInvoker.LOG_SUPPLIER_THROWN, "logX"), thrown, null); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOG_SUPPLIER_THROWN.logX(x, level, thrown, msg); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", () -> \"" + msg.get() + "\", thrown)"; testJdkLog(logger, tester, check, nameProducer); } static Supplier<String> logpMessage(ResourceBundle bundle, String className, String methodName, Supplier<String> msg) { if (BEST_EFFORT_FOR_LOGP && bundle == null && (className != null || methodName != null)) { final String cName = className == null ? "" : className; final String mName = methodName == null ? "" : methodName; return () -> { String m = msg.get(); return String.format("[%s %s] %s", cName, mName, m == null ? "" : m); }; } else { return msg; } } public void testLogp(java.lang.System.Logger logger, String className, String methodName, String msg) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("logp", res, logger.getName(), l, logpMessage(localized, className, methodName, () -> msg), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_STRING, className), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_STRING, methodName), null, localized); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGP_STRING.logX(x, level, className, methodName, msg); return null; }; Function<String, String> nameProducer = (l) -> "logp(Level." + l + ", class, method, \"" + msg + "\")"; testJdkLog(logger, tester, check, nameProducer); } public void testLogrb(java.lang.System.Logger logger, String className, String methodName, ResourceBundle bundle, String msg) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("logp", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOGRBP_STRING_PARAMS, className), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGRBP_STRING_PARAMS, methodName), null, bundle); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGRBP_STRING_PARAMS.logX(x, level, className, methodName, bundle, msg, (Object[])null); return null; }; Function<String, String> nameProducer = (l) -> "logp(Level." + l + ", class, method, bundle, \"" + msg + "\")"; testJdkLog(logger, tester, check, nameProducer); } public void testLogp(java.lang.System.Logger logger, String className, String methodName, String msg, Object... params) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("logp", res, logger.getName(), l, logpMessage(localized, className, methodName, () -> msg), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_STRING_PARAMS, className), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_STRING_PARAMS, methodName), null, localized, params); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGP_STRING_PARAMS.logX(x, level, className, methodName, msg, params); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", class, method, \"" + msg + "\", params...)"; testJdkLog(logger, tester, check, nameProducer); } public void testLogrb(java.lang.System.Logger logger, String className, String methodName, ResourceBundle bundle, String msg, Object... params) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("logp", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOGRBP_STRING_PARAMS, className), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGRBP_STRING_PARAMS, methodName), null, bundle, params); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGRBP_STRING_PARAMS.logX(x, level, className, methodName, bundle, msg, params); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", class, method, bundle, \"" + msg + "\", params...)"; testJdkLog(logger, tester, check, nameProducer); } public void testLogp(java.lang.System.Logger logger, String className, String methodName, String msg, Throwable thrown) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, logpMessage(localized, className, methodName, () -> msg), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_STRING_THROWN, className), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_STRING_THROWN, methodName), thrown, localized); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGP_STRING_THROWN.logX(x, level, className, methodName, msg, thrown); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", class, method, \"" + msg + "\", thrown)"; testJdkLog(logger, tester, check, nameProducer); } public void testLogrb(java.lang.System.Logger logger, String className, String methodName, ResourceBundle bundle, String msg, Throwable thrown) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, () -> msg, adaptor().getCallerClassName( JdkLogMethodInvoker.LOGRBP_STRING_THROWN, className), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGRBP_STRING_THROWN, methodName), thrown, bundle); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGRBP_STRING_THROWN.logX(x, level, className, methodName, bundle, msg, thrown); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", class, method, bundle, \"" + msg + "\", thrown)"; testJdkLog(logger, tester, check, nameProducer); } public void testLogp(java.lang.System.Logger logger, String className, String methodName, Supplier<String> msg) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, logpMessage(null, className, methodName, msg), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_SUPPLIER, className), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_SUPPLIER, methodName), null, null); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGP_SUPPLIER.logX(x, level, className, methodName, msg); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", class, method, () -> \"" + msg.get() + "\")"; testJdkLog(logger, tester, check, nameProducer); } public void testLogp(java.lang.System.Logger logger, String className, String methodName, Throwable thrown, Supplier<String> msg) { Checker<BackendRecord, Level> check = (res, l) -> { checkRecord("log", res, logger.getName(), l, logpMessage(null, className, methodName, msg), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_SUPPLIER_THROWN, className), adaptor().getCallerClassName( JdkLogMethodInvoker.LOGP_SUPPLIER_THROWN, methodName), thrown, null); return null; }; JdkLogTester tester = (x, level) -> { JdkLogMethodInvoker.LOGP_SUPPLIER_THROWN.logX(x, level, className, methodName, thrown, msg); return null; }; Function<String, String> nameProducer = (l) -> "log(Level." + l + ", class, method, () -> \"" + msg.get() + "\", thrown)"; testJdkLog(logger, tester, check, nameProducer); } private void testJdkLog(java.lang.System.Logger logger, JdkLogTester log, Checker<BackendRecord,Level> check, Function<String, String> nameProducer) { if (restrictedTo != null) { if (!bridgeLoggerClass.isAssignableFrom(restrictedTo)) { if (VERBOSE) { System.out.println("Skipping method from " + bridgeLoggerClass); } return; } } System.out.println("Testing Logger." + nameProducer.apply("*") + " on " + logger); final BackendAdaptor adaptor = adaptor(); for (Level loggerLevel : LEVELS) { adaptor.setLevel(logger, loggerLevel); for (Level l : LEVELS) { check(logger, () -> log.apply(bridgeLoggerClass.cast(logger), l), check, () -> adaptor.isLoggable(logger, l), () -> adaptor.shouldBeLoggable(l, loggerLevel), l, loggerLevel, nameProducer.apply(l.toString())); } } } private void testSpiLog(java.lang.System.Logger logger, SpiLogTester log, Checker<BackendRecord, java.lang.System.Logger.Level> check, Function<String, String> nameProducer) { System.out.println("Testing System.Logger." + nameProducer.apply("*") + " on " + logger); final BackendAdaptor adaptor = adaptor(); for (java.lang.System.Logger.Level loggerLevel : java.lang.System.Logger.Level.values()) { adaptor.setLevel(logger, loggerLevel); for (java.lang.System.Logger.Level l : java.lang.System.Logger.Level.values()) { check(logger, () -> log.apply(logger, l), check, () -> logger.isLoggable(l), () -> adaptor.shouldBeLoggable(l, loggerLevel), l, loggerLevel, nameProducer.apply(l.toString())); } } } private void test(String args, Levels level, java.lang.System.Logger logger, Runnable test, Checker<BackendRecord, Level> check) { if (restrictedTo != null) { if (!level.definingClass.isAssignableFrom(restrictedTo)) { if (VERBOSE) { System.out.println("Skipping method from " + level.definingClass); } return; } } String method = args.contains("bundle") ? "logrb" : "log"; System.out.println("Testing Logger." + method + "(Level." + level.platformLevel + ", "+ args + ")" + " on " + logger); final BackendAdaptor adaptor = adaptor(); for (Level loggerLevel : LEVELS) { adaptor.setLevel(logger, loggerLevel); check(logger, test, check, () -> level.isEnabled(logger), () -> adaptor.shouldBeLoggable(level, loggerLevel), level.platformLevel, loggerLevel, level.method); } } private <L> void check(java.lang.System.Logger logger, Runnable test, Checker<BackendRecord,L> check, BooleanSupplier checkLevelEnabled, BooleanSupplier shouldBeLoggable, L logLevel, L loggerLevel, String logMethod) { final BackendAdaptor adaptor = adaptor(); adaptor.resetBackendRecords(); test.run(); final List<BackendRecord> records = adaptor.getBackendRecords(); if (shouldBeLoggable.getAsBoolean()) { if (!checkLevelEnabled.getAsBoolean()) { throw new RuntimeException("Logger is not enabled for " + logMethod + " although logger level is " + loggerLevel); } if (records.size() != 1) { throw new RuntimeException(loggerLevel + " [" + logLevel + "] : Unexpected record sizes: " + records.toString()); } BackendRecord res = records.get(0); check.apply(res, logLevel); } else { if (checkLevelEnabled.getAsBoolean()) { throw new RuntimeException("Logger is enabled for " + logMethod + " although logger level is " + loggerLevel); } if (!records.isEmpty()) { throw new RuntimeException(loggerLevel + " [" + logLevel + "] : Unexpected record sizes: " + records.toString()); } } } } public static class JULBackendTester extends BackendTester<LogRecord>{ public JULBackendTester(boolean isSystem) { this(isSystem,null,null); } public JULBackendTester(boolean isSystem, ResourceBundle localized) { this(isSystem,null,localized); } public JULBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo) { this(isSystem, restrictedTo, null); } public JULBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo, ResourceBundle localized) { super(isSystem, restrictedTo, localized); } Logger getBackendLogger(String name) { if (isSystem) { return LoggingProviderImpl.getLogManagerAccess().demandLoggerFor( LogManager.getLogManager(), name, Thread.class.getModule()); } else { return Logger.getLogger(name); } } class JULBackendAdaptor extends BackendAdaptor { @Override public String getLoggerName(LogRecord res) { return res.getLoggerName(); } @Override public Level getLevel(LogRecord res) { return Level.valueOf(res.getLevel().getName()); } @Override public String getMessage(LogRecord res) { return res.getMessage(); } @Override public String getSourceClassName(LogRecord res) { return res.getSourceClassName(); } @Override public String getSourceMethodName(LogRecord res) { return res.getSourceMethodName(); } @Override public Throwable getThrown(LogRecord res) { return res.getThrown(); } @Override public ResourceBundle getResourceBundle(LogRecord res) { return res.getResourceBundle(); } @Override public void setLevel(java.lang.System.Logger logger, Level level) { Logger backend = getBackendLogger(logger.getName()); backend.setLevel(java.util.logging.Level.parse(level.name())); } @Override public void setLevel(java.lang.System.Logger logger, java.lang.System.Logger.Level level) { setLevel(logger, toJUL(level)); } @Override public List<LogRecord> getBackendRecords() { return handler.records; } @Override public void resetBackendRecords() { handler.reset(); } @Override public Level getMappedLevel(Object level) { if (level instanceof java.lang.System.Logger.Level) { return toJUL((java.lang.System.Logger.Level)level); } return (Level)level; } } final JULBackendAdaptor julAdaptor = new JULBackendAdaptor(); @Override BackendAdaptor adaptor() { return julAdaptor; } } public abstract static class BackendTesterFactory { public abstract BackendTester createBackendTester(boolean isSystem); public abstract BackendTester createBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo); public abstract BackendTester createBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo, ResourceBundle bundle); public abstract BackendTester createBackendTester(boolean isSystem, ResourceBundle bundle); } public static class JULBackendTesterFactory extends BackendTesterFactory { @Override public BackendTester createBackendTester(boolean isSystem) { return new JULBackendTester(isSystem); } @Override public BackendTester createBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo) { return new JULBackendTester(isSystem, restrictedTo); } @Override public BackendTester createBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo, ResourceBundle bundle) { return new JULBackendTester(isSystem, restrictedTo, bundle); } @Override public BackendTester createBackendTester(boolean isSystem, ResourceBundle bundle) { return new JULBackendTester(isSystem, bundle); } } public static class CustomLoggerFinder extends LoggerFinder { static enum CustomLevel { OFF, FATAL, ERROR, WARN, INFO, DEBUG, TRACE, ALL }; static CustomLevel[] customLevelMap = { CustomLevel.ALL, CustomLevel.TRACE, CustomLevel.DEBUG, CustomLevel.INFO, CustomLevel.WARN, CustomLevel.ERROR, CustomLevel.OFF }; static class CustomLogRecord { public final CustomLevel logLevel; public final java.lang.System.Logger logger; public final String msg; public final Object[] params; public final Throwable thrown; public final ResourceBundle bundle; CustomLogRecord(java.lang.System.Logger producer, CustomLevel level, String msg) { this(producer, level, msg, (ResourceBundle)null, (Throwable)null, (Object[])null); } CustomLogRecord(java.lang.System.Logger producer, CustomLevel level, String msg, ResourceBundle bundle, Throwable thrown, Object... params) { this.logger = producer; this.logLevel = level; this.msg = msg; this.params = params; this.thrown = thrown; this.bundle = bundle; } } static final List<CustomLogRecord> records = Collections.synchronizedList(new ArrayList<>()); static class CustomLogger implements java.lang.System.Logger { final String name; volatile CustomLevel level; CustomLogger(String name) { this.name = name; this.level = CustomLevel.INFO; } @Override public String getName() { return name; } public void setLevel(CustomLevel level) { this.level = level; } @Override public boolean isLoggable(java.lang.System.Logger.Level level) { return this.level != CustomLevel.OFF && this.level.ordinal() >= customLevelMap[level.ordinal()].ordinal(); } @Override public void log(java.lang.System.Logger.Level level, ResourceBundle bundle, String key, Throwable thrown) { if (isLoggable(level)) { records.add(new CustomLogRecord(this, customLevelMap[level.ordinal()], key, bundle, thrown)); } } @Override public void log(java.lang.System.Logger.Level level, ResourceBundle bundle, String format, Object... params) { if (isLoggable(level)) { records.add(new CustomLogRecord(this, customLevelMap[level.ordinal()], format, bundle, null, params)); } } } final Map<String, java.lang.System.Logger> applicationLoggers = Collections.synchronizedMap(new HashMap<>()); final Map<String, java.lang.System.Logger> systemLoggers = Collections.synchronizedMap(new HashMap<>()); @Override public java.lang.System.Logger getLogger(String name, Module caller) { ClassLoader callerLoader = caller.getClassLoader(); if (callerLoader == null) { systemLoggers.putIfAbsent(name, new CustomLogger(name)); return systemLoggers.get(name); } else { applicationLoggers.putIfAbsent(name, new CustomLogger(name)); return applicationLoggers.get(name); } } CustomLevel fromJul(Level level) { if (level.intValue() == Level.OFF.intValue()) { return CustomLevel.OFF; } else if (level.intValue() > Level.SEVERE.intValue()) { return CustomLevel.ERROR; } else if (level.intValue() > Level.WARNING.intValue()) { return CustomLevel.ERROR; } else if (level.intValue() > Level.INFO.intValue()) { return CustomLevel.WARN; } else if (level.intValue() > Level.CONFIG.intValue()) { return CustomLevel.INFO; } else if (level.intValue() > Level.FINER.intValue()) { return CustomLevel.DEBUG; } else if (level.intValue() > Level.FINEST.intValue()) { return CustomLevel.TRACE; } else if (level.intValue() == Level.ALL.intValue()) { return CustomLevel.ALL; } else { return CustomLevel.TRACE; } } Level toJul(CustomLevel level) { switch(level) { case OFF: return Level.OFF; case FATAL: return Level.SEVERE; case ERROR: return Level.SEVERE; case WARN: return Level.WARNING; case INFO: return Level.INFO; case DEBUG: return Level.FINE; case TRACE: return Level.FINER; case ALL: return Level.ALL; default: throw new InternalError("No such level: "+level); } } } public static class CustomBackendTester extends BackendTester<CustomLoggerFinder.CustomLogRecord> { public final CustomLoggerFinder provider; public CustomBackendTester(boolean isSystem) { this(isSystem, null, null); } public CustomBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo) { this(isSystem, restrictedTo, null); } public CustomBackendTester(boolean isSystem, ResourceBundle localized) { this(isSystem, null, localized); } public CustomBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo, ResourceBundle localized) { super(isSystem, restrictedTo, localized); provider = (CustomLoggerFinder)java.lang.System.LoggerFinder.getLoggerFinder(); } @Override public java.lang.System.Logger convert(java.lang.System.Logger logger) { if (restrictedTo != null && restrictedTo.isInstance(logger)) { return logger; } else if (restrictedTo == jdkLoggerClass) { return logger; } else { return java.lang.System.Logger.class.cast( sun.util.logging.PlatformLogger.Bridge.convert(logger)); } } class CustomBackendAdaptor extends BackendAdaptor { @Override public String getLoggerName(CustomLoggerFinder.CustomLogRecord res) { return res.logger.getName(); } @Override public CustomLoggerFinder.CustomLevel getLevel(CustomLoggerFinder.CustomLogRecord res) { return res.logLevel; } @Override public String getMessage(CustomLoggerFinder.CustomLogRecord res) { return res.msg; } @Override // we don't support source class name in our custom provider implementation public String getSourceClassName(CustomLoggerFinder.CustomLogRecord res) { return null; } @Override // we don't support source method name in our custom provider implementation public String getSourceMethodName(CustomLoggerFinder.CustomLogRecord res) { return null; } @Override public Throwable getThrown(CustomLoggerFinder.CustomLogRecord res) { return res.thrown; } @Override public ResourceBundle getResourceBundle(CustomLoggerFinder.CustomLogRecord res) { return res.bundle; } @Override public void setLevel(java.lang.System.Logger logger, Level level) { final CustomLoggerFinder.CustomLogger l = (CustomLoggerFinder.CustomLogger) (isSystem ? provider.getLogger(logger.getName(), Thread.class.getModule()) : provider.getLogger(logger.getName(), LoggerFinderBackendTest.class.getModule())); l.setLevel(provider.fromJul(level)); } @Override public void setLevel(java.lang.System.Logger logger, java.lang.System.Logger.Level level) { setLevel(logger, toJUL(level)); } CustomLoggerFinder.CustomLevel getLevel(java.lang.System.Logger logger) { final CustomLoggerFinder.CustomLogger l = (CustomLoggerFinder.CustomLogger) (isSystem ? provider.getLogger(logger.getName(), Thread.class.getModule()) : provider.getLogger(logger.getName(), LoggerFinderBackendTest.class.getModule())); return l.level; } @Override public List<CustomLoggerFinder.CustomLogRecord> getBackendRecords() { return CustomLoggerFinder.records; } @Override public void resetBackendRecords() { CustomLoggerFinder.records.clear(); } @Override public boolean shouldBeLoggable(Levels level, Level loggerLevel) { return loggerLevel != Level.OFF && fromLevels(level).ordinal() <= provider.fromJul(loggerLevel).ordinal(); } @Override public boolean isLoggable(java.lang.System.Logger logger, Level l) { return super.isLoggable(logger, l); } @Override public boolean shouldBeLoggable(Level logLevel, Level loggerLevel) { return loggerLevel != Level.OFF && provider.fromJul(logLevel).ordinal() <= provider.fromJul(loggerLevel).ordinal(); } @Override // we don't support source class name in our custom provider implementation public String getCallerClassName(Levels level, String clazz) { return null; } @Override // we don't support source method name in our custom provider implementation public String getCallerMethodName(Levels level, String method) { return null; } @Override // we don't support source class name in our custom provider implementation public String getCallerClassName(MethodInvoker<?,?> logMethod, String clazz) { return null; } @Override // we don't support source method name in our custom provider implementation public String getCallerMethodName(MethodInvoker<?,?> logMethod, String method) { return null; } @Override public CustomLoggerFinder.CustomLevel getMappedLevel(Object level) { if (level instanceof java.lang.System.Logger.Level) { final int index = ((java.lang.System.Logger.Level)level).ordinal(); return CustomLoggerFinder.customLevelMap[index]; } else if (level instanceof Level) { return provider.fromJul((Level)level); } return (CustomLoggerFinder.CustomLevel) level; } CustomLoggerFinder.CustomLevel fromLevels(Levels level) { switch(level) { case SEVERE: return CustomLoggerFinder.CustomLevel.ERROR; case WARNING: return CustomLoggerFinder.CustomLevel.WARN; case INFO: return CustomLoggerFinder.CustomLevel.INFO; case CONFIG: case FINE: return CustomLoggerFinder.CustomLevel.DEBUG; case FINER: case FINEST: return CustomLoggerFinder.CustomLevel.TRACE; } throw new InternalError("No such level "+level); } } @Override BackendAdaptor adaptor() { return new CustomBackendAdaptor(); } } public static class CustomBackendTesterFactory extends BackendTesterFactory { @Override public BackendTester createBackendTester(boolean isSystem) { return new CustomBackendTester(isSystem); } @Override public BackendTester createBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo) { return new CustomBackendTester(isSystem, restrictedTo); } @Override public BackendTester createBackendTester(boolean isSystem, Class<? extends java.lang.System.Logger> restrictedTo, ResourceBundle bundle) { return new CustomBackendTester(isSystem, restrictedTo, bundle); } @Override public BackendTester createBackendTester(boolean isSystem, ResourceBundle bundle) { return new CustomBackendTester(isSystem, bundle); } } static final Method getLazyLogger; static final Method accessLoggerFinder; static { // jdk.internal.logger.LazyLoggers.getLazyLogger(name, caller); try { Class<?> lazyLoggers = jdk.internal.logger.LazyLoggers.class; getLazyLogger = lazyLoggers.getMethod("getLazyLogger", String.class, Module.class); getLazyLogger.setAccessible(true); Class<?> loggerFinderLoader = Class.forName("java.lang.System$LoggerFinder"); accessLoggerFinder = loggerFinderLoader.getDeclaredMethod("accessProvider"); accessLoggerFinder.setAccessible(true); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } static java.lang.System.Logger getSystemLogger(String name, Module caller) throws Exception { try { return java.lang.System.Logger.class.cast(getLazyLogger.invoke(null, name, caller)); } catch (InvocationTargetException x) { Throwable t = x.getTargetException(); if (t instanceof Exception) { throw (Exception)t; } else { throw (Error)t; } } } static java.lang.System.Logger getSystemLogger(String name, ResourceBundle bundle, Module caller) throws Exception { try { LoggerFinder provider = LoggerFinder.class.cast(accessLoggerFinder.invoke(null)); return provider.getLocalizedLogger(name, bundle, caller); } catch (InvocationTargetException x) { Throwable t = x.getTargetException(); if (t instanceof Exception) { throw (Exception)t; } else { throw (Error)t; } } } // Change this to 'true' to get more traces... public static boolean verbose = false; public static void main(String[] argv) throws Exception { final AtomicInteger nb = new AtomicInteger(0); final boolean hidesProvider = Boolean.getBoolean("test.logger.hidesProvider"); System.out.println(ClassLoader.getSystemClassLoader()); final BackendTesterFactory factory; if (java.lang.System.LoggerFinder.getLoggerFinder() instanceof CustomLoggerFinder) { if (hidesProvider) { System.err.println("Custom backend " + java.lang.System.LoggerFinder.getLoggerFinder() + " should have been hidden!"); throw new RuntimeException( "Custom backend should have been hidden: " + "check value of java.system.class.loader property"); } System.out.println("Using custom backend"); factory = new CustomBackendTesterFactory(); } else { if (!hidesProvider) { System.err.println("Default JUL backend " + java.lang.System.LoggerFinder.getLoggerFinder() + " should have been hidden!"); throw new RuntimeException( "Default JUL backend should have been hidden: " + "check value of java.system.class.loader property"); } System.out.println("Using JUL backend"); factory = new JULBackendTesterFactory(); } testBackend(nb, factory); } public static void testBackend(AtomicInteger nb, BackendTesterFactory factory) throws Exception { // Tests all level specifics methods with loggers configured with // all possible levels and loggers obtained with all possible // entry points from LoggerFactory and JdkLoggerFactory, with // JUL as backend. // Test a simple application logger with JUL backend final BackendTester tester = factory.createBackendTester(false); final java.lang.System.Logger logger = java.lang.System.LoggerFinder.getLoggerFinder() .getLogger("foo", LoggerFinderBackendTest.class.getModule()); testLogger(tester, logger, nb); // Test a simple system logger with JUL backend final java.lang.System.Logger system = java.lang.System.LoggerFinder.getLoggerFinder() .getLogger("bar", Thread.class.getModule()); final BackendTester systemTester = factory.createBackendTester(true); testLogger(systemTester, system, nb); // Test a localized application logger with null resource bundle and // JUL backend final java.lang.System.Logger noBundleLogger = java.lang.System.LoggerFinder.getLoggerFinder() .getLocalizedLogger("baz", null, LoggerFinderBackendTest.class.getModule()); final BackendTester noBundleTester = factory.createBackendTester(false, spiLoggerClass); testLogger(noBundleTester, noBundleLogger, nb); // Test a localized system logger with null resource bundle and JUL // backend final java.lang.System.Logger noBundleSysLogger = java.lang.System.LoggerFinder.getLoggerFinder() .getLocalizedLogger("oof", null, Thread.class.getModule()); final BackendTester noBundleSysTester = factory.createBackendTester(true, spiLoggerClass); testLogger(noBundleSysTester, noBundleSysLogger, nb); // Test a localized application logger with null resource bundle and // JUL backend try { System.getLogger("baz", null); throw new RuntimeException("Expected NullPointerException not thrown"); } catch (NullPointerException x) { System.out.println("System.Loggers.getLogger(\"baz\", null): got expected " + x); } final java.lang.System.Logger noBundleExtensionLogger = getSystemLogger("baz", null, LoggerFinderBackendTest.class.getModule()); final BackendTester noBundleExtensionTester = factory.createBackendTester(false, jdkLoggerClass); testLogger(noBundleExtensionTester, noBundleExtensionLogger, nb); // Test a simple system logger with JUL backend final java.lang.System.Logger sysExtensionLogger = getSystemLogger("oof", Thread.class.getModule()); final BackendTester sysExtensionTester = factory.createBackendTester(true, jdkLoggerClass); testLogger(sysExtensionTester, sysExtensionLogger, nb); // Test a localized system logger with null resource bundle and JUL // backend final java.lang.System.Logger noBundleSysExtensionLogger = getSystemLogger("oof", null, Thread.class.getModule()); final BackendTester noBundleSysExtensionTester = factory.createBackendTester(true, jdkLoggerClass); testLogger(noBundleSysExtensionTester, noBundleSysExtensionLogger, nb); // Test a localized application logger converted to JDK with null // resource bundle and JUL backend final java.lang.System.Logger noBundleConvertedLogger = (java.lang.System.Logger) sun.util.logging.PlatformLogger.Bridge.convert(noBundleLogger); final BackendTester noBundleJdkTester = factory.createBackendTester(false); testLogger(noBundleJdkTester, noBundleConvertedLogger, nb); // Test a localized system logger converted to JDK with null resource // bundle and JUL backend final java.lang.System.Logger noBundleConvertedSysLogger = (java.lang.System.Logger) sun.util.logging.PlatformLogger.Bridge.convert(noBundleSysLogger); final BackendTester noBundleJdkSysTester = factory.createBackendTester(true); testLogger(noBundleJdkSysTester, noBundleConvertedSysLogger, nb); // Test a localized application logger with resource bundle and JUL // backend final ResourceBundle bundle = ResourceBundle.getBundle(ResourceBundeLocalized.class.getName()); final java.lang.System.Logger bundleLogger = java.lang.System.LoggerFinder.getLoggerFinder() .getLocalizedLogger("toto", bundle, LoggerFinderBackendTest.class.getModule()); final BackendTester bundleTester = factory.createBackendTester(false, spiLoggerClass, bundle); testLogger(bundleTester, bundleLogger, nb); // Test a localized system logger with resource bundle and JUL backend final java.lang.System.Logger bundleSysLogger = java.lang.System.LoggerFinder.getLoggerFinder() .getLocalizedLogger("titi", bundle, Thread.class.getModule()); final BackendTester bundleSysTester = factory.createBackendTester(true, spiLoggerClass, bundle); testLogger(bundleSysTester, bundleSysLogger, nb); // Test a localized Jdk application logger with resource bundle and JUL // backend final java.lang.System.Logger bundleExtensionLogger = System.getLogger("tita", bundle); final BackendTester bundleExtensionTester = factory.createBackendTester(false, jdkLoggerClass, bundle); testLogger(bundleExtensionTester, bundleExtensionLogger, nb); // Test a localized Jdk system logger with resource bundle and JUL // backend final java.lang.System.Logger bundleExtensionSysLogger = getSystemLogger("titu", bundle, Thread.class.getModule()); final BackendTester bundleExtensionSysTester = factory.createBackendTester(true, jdkLoggerClass, bundle); testLogger(bundleExtensionSysTester, bundleExtensionSysLogger, nb); // Test a localized application logger converted to JDK with resource // bundle and JUL backend final BackendTester bundleJdkTester = factory.createBackendTester(false, bundle); final java.lang.System.Logger bundleConvertedLogger = (java.lang.System.Logger) sun.util.logging.PlatformLogger.Bridge.convert(bundleLogger); testLogger(bundleJdkTester, bundleConvertedLogger, nb); // Test a localized Jdk system logger converted to JDK with resource // bundle and JUL backend final BackendTester bundleJdkSysTester = factory.createBackendTester(true, bundle); final java.lang.System.Logger bundleConvertedSysLogger = (java.lang.System.Logger) sun.util.logging.PlatformLogger.Bridge.convert(bundleSysLogger); testLogger(bundleJdkSysTester, bundleConvertedSysLogger, nb); // Now need to add tests for all the log/logp/logrb methods... } private static class FooObj { final String s; FooObj(String s) { this.s = s; } @Override public String toString() { return super.toString() +": "+s; } } public static void testLogger(BackendTester tester, java.lang.System.Logger spiLogger, AtomicInteger nb) { // Test all level-specific method forms: // fatal(...) error(...) severe(...) etc... java.lang.System.Logger jdkLogger = tester.convert(spiLogger); for (Levels l : Levels.values()) { java.lang.System.Logger logger = l.definingClass.equals(spiLoggerClass) ? spiLogger : jdkLogger; tester.testLevel(l, logger, l.method + "[" + logger.getName()+ "]-" + nb.incrementAndGet()); tester.testLevel(l, logger, l.method + "[" + logger.getName()+ "]-" + nb.incrementAndGet(), bundleParam); final int nbb = nb.incrementAndGet(); tester.testLevel(l, logger, () -> l.method + "[" + logger.getName() + "]-" + nbb); } for (Levels l : Levels.values()) { java.lang.System.Logger logger = l.definingClass.equals(spiLoggerClass) ? spiLogger : jdkLogger; tester.testLevel(l, logger, l.method + "[" + logger.getName()+ "]({0},{1})-" + nb.incrementAndGet(), "One", "Two"); tester.testLevel(l, logger, l.method + "[" + logger.getName()+ "]({0},{1})-" + nb.incrementAndGet(), bundleParam, "One", "Two"); } final Throwable thrown = new RuntimeException("Test"); for (Levels l : Levels.values()) { java.lang.System.Logger logger = l.definingClass.equals(spiLoggerClass) ? spiLogger : jdkLogger; tester.testLevel(l, logger, l.method + "[" + logger.getName()+ "]-" + nb.incrementAndGet(), thrown); tester.testLevel(l, logger, l.method + "[" + logger.getName()+ "]-" + nb.incrementAndGet(), bundleParam, thrown); final int nbb = nb.incrementAndGet(); tester.testLevel(l, logger, ()->l.method + "[" + logger.getName()+ "]-" + nbb, thrown); } java.lang.System.Logger logger = jdkLogger; // test System.Logger methods tester.testSpiLog(logger, "[" + logger.getName()+ "]-" + nb.incrementAndGet()); tester.testSpiLog(logger, bundleParam, "[" + logger.getName()+ "]-" + nb.incrementAndGet()); tester.testSpiLog(logger, "[" + logger.getName()+ "]-({0},{1})" + nb.incrementAndGet(), "One", "Two"); tester.testSpiLog(logger, bundleParam, "[" + logger.getName()+ "]-({0},{1})" + nb.incrementAndGet(), "One", "Two"); tester.testSpiLog(logger, "[" + logger.getName()+ "]-" + nb.incrementAndGet(), thrown); tester.testSpiLog(logger, bundleParam, "[" + logger.getName()+ "]-" + nb.incrementAndGet(), thrown); final int nbb01 = nb.incrementAndGet(); tester.testSpiLog(logger, () -> "[" + logger.getName()+ "]-" + nbb01); final int nbb02 = nb.incrementAndGet(); tester.testSpiLog(logger, thrown, () -> "[" + logger.getName()+ "]-" + nbb02); final int nbb03 = nb.incrementAndGet(); tester.testSpiLog(logger, new FooObj("[" + logger.getName()+ "]-" + nbb03)); // Test all log method forms: // jdk.internal.logging.Logger.log(...) tester.testLog(logger, "[" + logger.getName()+ "]-" + nb.incrementAndGet()); tester.testLogrb(logger, bundleParam, "[" + logger.getName()+ "]-" + nb.incrementAndGet()); tester.testLog(logger, "[" + logger.getName()+ "]-({0},{1})" + nb.incrementAndGet(), "One", "Two"); tester.testLogrb(logger, bundleParam, "[" + logger.getName()+ "]-({0},{1})" + nb.incrementAndGet(), "One", "Two"); tester.testLog(logger, "[" + logger.getName()+ "]-" + nb.incrementAndGet(), thrown); tester.testLogrb(logger, bundleParam, "[" + logger.getName()+ "]-" + nb.incrementAndGet(), thrown); final int nbb1 = nb.incrementAndGet(); tester.testLog(logger, () -> "[" + logger.getName()+ "]-" + nbb1); final int nbb2 = nb.incrementAndGet(); tester.testLog(logger, thrown, () -> "[" + logger.getName()+ "]-" + nbb2); // Test all logp method forms // jdk.internal.logging.Logger.logp(...) tester.testLogp(logger, "clazz" + nb.incrementAndGet(), "method" + nb.incrementAndGet(), "[" + logger.getName()+ "]-" + nb.incrementAndGet()); tester.testLogrb(logger, "clazz" + nb.incrementAndGet(), "method" + nb.incrementAndGet(), bundleParam, "[" + logger.getName()+ "]-" + nb.incrementAndGet()); tester.testLogp(logger, "clazz" + nb.incrementAndGet(), "method" + nb.incrementAndGet(), "[" + logger.getName()+ "]-({0},{1})" + nb.incrementAndGet(), "One", "Two"); tester.testLogrb(logger, "clazz" + nb.incrementAndGet(), "method" + nb.incrementAndGet(), bundleParam, "[" + logger.getName()+ "]-({0},{1})" + nb.incrementAndGet(), "One", "Two"); tester.testLogp(logger, "clazz" + nb.incrementAndGet(), "method" + nb.incrementAndGet(), "[" + logger.getName()+ "]-" + nb.incrementAndGet(), thrown); tester.testLogrb(logger, "clazz" + nb.incrementAndGet(), "method" + nb.incrementAndGet(), bundleParam, "[" + logger.getName()+ "]-" + nb.incrementAndGet(), thrown); final int nbb3 = nb.incrementAndGet(); tester.testLogp(logger, "clazz" + nb.incrementAndGet(), "method" + nb.incrementAndGet(), () -> "[" + logger.getName()+ "]-" + nbb3); final int nbb4 = nb.incrementAndGet(); tester.testLogp(logger, "clazz" + nb.incrementAndGet(), "method" + nb.incrementAndGet(), thrown, () -> "[" + logger.getName()+ "]-" + nbb4); } }