From e72bf1366f285f919556a5dd9b985151d19ad230 Mon Sep 17 00:00:00 2001 From: Krishnan Mahadevan Date: Tue, 28 Dec 2021 20:16:42 +0530 Subject: [PATCH] Streamline Logging Across TestNG Closes #2646 We now use sl4j apis for our logging. Internally TestNG makes use of SimpleLogger (Slf4j-simple) bindings for logging purposes. --- CHANGES.txt | 1 + .../src/test/java/test/ant/AntTest.java | 10 +- .../resources/ant/expected/ant-simple.test | 4 - .../java/org/testng/log4testng/Logger.java | 327 ++---------------- .../testng-core-api-build.gradle.kts | 2 + .../main/java/org/testng/internal/Graph.java | 8 +- .../org/testng/log4testng/LoggerTest.java | 236 ------------- .../test/resources/simplelogger.properties | 6 + versions.properties | 3 + 9 files changed, 46 insertions(+), 551 deletions(-) delete mode 100644 testng-ant/src/test/resources/ant/expected/ant-simple.test delete mode 100644 testng-core/src/test/java/org/testng/log4testng/LoggerTest.java create mode 100644 testng-core/src/test/resources/simplelogger.properties diff --git a/CHANGES.txt b/CHANGES.txt index 2fb0820394..97bd6df6b8 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ Current +Fixed: GITHUB-2646: Streamline Logging Across TestNG (Krishnan Mahadevan) Fixed: GITHUB-2658: Inheritance + dependsOnMethods (Krishnan Mahadevan) Fixed: GITHUB-2664: Order for DependsOnGroups has changed after TestNg 7.4.0 (Krishnan Mahadevan) Fixed: GITHUB-2501: TestNG 7.4.0 throws an exception "sun.net.www.protocol.file.FileURLConnection cannot be cast to java.net.HttpURLConnection" when xml file contain "ENTITY SYSTEM" grammer (Krishnan Mahadevan) diff --git a/testng-ant/src/test/java/test/ant/AntTest.java b/testng-ant/src/test/java/test/ant/AntTest.java index aab372f0d3..d096be9956 100644 --- a/testng-ant/src/test/java/test/ant/AntTest.java +++ b/testng-ant/src/test/java/test/ant/AntTest.java @@ -2,10 +2,8 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.io.File; -import java.io.IOException; +import java.util.regex.Pattern; import org.apache.tools.ant.BuildFileRule; -import org.apache.tools.ant.FileUtilities; import org.testng.annotations.Test; public class AntTest { @@ -13,11 +11,11 @@ public class AntTest { private final BuildFileRule rule = new BuildFileRule(); @Test - public void testSimple() throws IOException { + public void testSimple() { rule.configureProject("src/test/resources/ant/build-simple.xml"); rule.executeTarget("testng"); - File expected = rule.getProject().resolveFile("expected/ant-simple.test"); - assertThat(rule.getLog()).isEqualToIgnoringNewLines(FileUtilities.getFileContents(expected)); + String expectedText = "Total tests run: 1, Passes: 1, Failures: 0, Skips: 0"; + assertThat(rule.getLog()).containsPattern(Pattern.compile(expectedText)); } @Test diff --git a/testng-ant/src/test/resources/ant/expected/ant-simple.test b/testng-ant/src/test/resources/ant/expected/ant-simple.test deleted file mode 100644 index 8316518305..0000000000 --- a/testng-ant/src/test/resources/ant/expected/ant-simple.test +++ /dev/null @@ -1,4 +0,0 @@ -=============================================== -Ant suite -Total tests run: 1, Passes: 1, Failures: 0, Skips: 0 -=============================================== diff --git a/testng-core-api/src/main/java/org/testng/log4testng/Logger.java b/testng-core-api/src/main/java/org/testng/log4testng/Logger.java index c3d6ea3c27..7dad29acaa 100644 --- a/testng-core-api/src/main/java/org/testng/log4testng/Logger.java +++ b/testng-core-api/src/main/java/org/testng/log4testng/Logger.java @@ -1,134 +1,21 @@ package org.testng.log4testng; -import java.io.IOException; -import java.io.InputStream; -import java.io.PrintStream; -import java.util.Iterator; -import java.util.Locale; import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; +import org.slf4j.LoggerFactory; import org.testng.collections.Maps; /** - * TestNG support logging via a custom logging framework similar to Log4j. To control logging, add a resource named - * "log4testng.properties" to your classpath. The logging levels are TRACE, DEBUG, INFO, WARN, ERROR - * and FATAL. The Logging framework has the following characteristics: - * - * - * - * The property file contains lines in the following format: - * - *

- * # log4testng will log its own behavior (generally used for debugging this package only).
- * log4testng.debug=true
- *
- * # Specifies the root Loggers logging level. Will log DEBUG level and above
- * log4testng.rootLogger=DEBUG
- *
- * # The org.testng.reporters.EmailableReporter Logger will log TRACE level and above
- * log4testng.logger.org.testng.reporters.EmailableReporter=TRACE
- *
- * # All Logger in packages below org.testng will log WARN level and above
- * log4testng.logger.org.testng=WARN
- * 
- * - * In your source files you will typically instantiate and use loggers this ways: - * - *

- * import org.testng.log4testng.Logger;
- *
- * class ThisClass {
- *     private static final Logger LOGGER = Logger.getLogger(ThisClass.class);
- *
- *     ...
- *     LOGGER.debug("entering myMethod()");
- *     ...
- *     LOGGER.warn("unknown file: " + filename);
- *     ...
- *     LOGGER.error("Unexpected error", exception);
- * 
+ * TestNG logging now uses slf4j logging facade to satisfy the logging needs. To control TestNG + * logging, please refer to the SLF4J logging facade documentation. TestNG internally uses SimpleLogger for logging + * purposes. */ public class Logger { - // Attribute an hierarchical integer value to all levels. - private static int i = 0; - private static final int TRACE = i++; - private static final int DEBUG = i++; - private static final int INFO = i++; - static final int WARN = i++; - private static final int ERROR = i++; - private static final int FATAL = i++; - private static final int LEVEL_COUNT = i; - - /** Standard prefix of all property names in log4testng.properties. */ - private static final String PREFIX = "log4testng."; - - /** Standard prefix of all logger names in log4testng.properties. */ - private static final String LOGGER_PREFIX = PREFIX + "logger."; - - /** Root logger name in log4testng.properties. */ - private static final String ROOT_LOGGER = PREFIX + "rootLogger"; - - /** Debug property name in log4testng.properties. */ - private static final String DEBUG_PROPERTY = PREFIX + "debug"; - - /** The standard error stream (this is allways System.err except for unit tests) */ - static PrintStream err = System.err; - - /** The standard output stream (this is allways System.out except for unit tests) */ - static PrintStream out = System.out; - - /** An ordered list of level names. */ - private static final String[] levelNames = new String[LEVEL_COUNT]; - - static { - levelNames[TRACE] = "TRACE"; - levelNames[DEBUG] = "DEBUG"; - levelNames[INFO] = "INFO"; - levelNames[WARN] = "WARN"; - levelNames[ERROR] = "ERROR"; - levelNames[FATAL] = "FATAL"; - } - - /** A map from level name to level integer index (TRACE->0, DEBUG->1 ...) */ - private static final Map levelMap = Maps.newHashMap(); - - static { - for (i = 0; i < LEVEL_COUNT; ++i) { - levelMap.put(levelNames[i], i); - } - } - - /** true if the Logging system has been initialized. */ - static boolean initialized; - - /** Map from Logger names to level index (as specified in log4testng.properties) */ - private static final Map loggerLevels = Maps.newHashMap(); - /** Map of all known loggers. */ - static final Map loggers = Maps.newHashMap(); - - /** The logging level of the root logger (defaults to warn). */ - static int rootLoggerLevel = WARN; - - /** Should log4testng log what it is doing (defaults to false). */ - static boolean debug = false; - - /** The logger's level */ - private final int level; - - /** The logger's name. */ - private final Class klass; + private static final Map, Logger> loggers = Maps.newConcurrentMap(); - private final String m_className; + private final org.slf4j.Logger logger; /** * Retrieve a logger named according to the value of the pClass.getName() parameter. If the named @@ -139,17 +26,8 @@ public class Logger { * @param pClass The class' logger to retrieve. * @return a logger named according to the value of the pClass.getName(). */ - public static synchronized Logger getLogger(Class pClass) { - initialize(); - Logger logger = loggers.get(pClass); - if (logger != null) { - return logger; - } - int level = getLevel(pClass); - logger = new Logger(pClass, level); - loggers.put(pClass, logger); - - return logger; + public static Logger getLogger(Class pClass) { + return loggers.computeIfAbsent(pClass, clz -> new Logger(LoggerFactory.getLogger(clz))); } /** @@ -158,7 +36,7 @@ public static synchronized Logger getLogger(Class pClass) { * @return true if this logger is enabled for level TRACE, false otherwise. */ public boolean isTraceEnabled() { - return isLevelEnabled(TRACE); + return logger.isTraceEnabled(); } /** @@ -171,7 +49,7 @@ public boolean isTraceEnabled() { * @param message the message object to log. */ public void trace(Object message) { - log(TRACE, message, null); + logger.trace("{}", message); } /** @@ -182,7 +60,7 @@ public void trace(Object message) { * @param t the exception to log, including its stack trace. */ public void trace(Object message, Throwable t) { - log(TRACE, message, t); + logger.trace("{}", message, t); } /** @@ -191,7 +69,7 @@ public void trace(Object message, Throwable t) { * @return true if this logger is enabled for level DEBUG, false otherwise. */ public boolean isDebugEnabled() { - return isLevelEnabled(DEBUG); + return logger.isDebugEnabled(); } /** @@ -201,7 +79,7 @@ public boolean isDebugEnabled() { * @param message the message object to log. */ public void debug(Object message) { - log(DEBUG, message, null); + logger.debug("{}", message); } /** @@ -212,7 +90,7 @@ public void debug(Object message) { * @param t the exception to log, including its stack trace. */ public void debug(Object message, Throwable t) { - log(DEBUG, message, t); + logger.debug("{}", message, t); } /** @@ -221,7 +99,7 @@ public void debug(Object message, Throwable t) { * @return true if this logger is enabled for level INFO, false otherwise. */ public boolean isInfoEnabled() { - return isLevelEnabled(INFO); + return logger.isInfoEnabled(); } /** @@ -231,7 +109,7 @@ public boolean isInfoEnabled() { * @param message the message object to log. */ public void info(Object message) { - log(INFO, message, null); + logger.info("{}", message); } /** @@ -242,7 +120,7 @@ public void info(Object message) { * @param t the exception to log, including its stack trace. */ public void info(Object message, Throwable t) { - log(INFO, message, t); + logger.info("{}", message, t); } /** @@ -252,7 +130,7 @@ public void info(Object message, Throwable t) { * @param message the message object to log. */ public void warn(Object message) { - log(WARN, message, null); + logger.warn("{}", message); } /** @@ -263,7 +141,7 @@ public void warn(Object message) { * @param t the exception to log, including its stack trace. */ public void warn(Object message, Throwable t) { - log(WARN, message, t); + logger.warn("{}", message, t); } /** @@ -273,7 +151,7 @@ public void warn(Object message, Throwable t) { * @param message the message object to log. */ public void error(Object message) { - log(ERROR, message, null); + logger.error("{}", message); } /** @@ -284,7 +162,7 @@ public void error(Object message) { * @param t the exception to log, including its stack trace. */ public void error(Object message, Throwable t) { - log(ERROR, message, t); + logger.error("{}", message, t); } /** @@ -294,7 +172,7 @@ public void error(Object message, Throwable t) { * @param message the message object to log. */ public void fatal(Object message) { - log(FATAL, message, null); + logger.error("{}", message); } /** @@ -305,163 +183,10 @@ public void fatal(Object message) { * @param t the exception to log, including its stack trace. */ public void fatal(Object message, Throwable t) { - log(FATAL, message, t); - } - - private Logger(Class pClass, int pLevel) { - level = pLevel; - klass = pClass; - m_className = pClass.getName().substring(pClass.getName().lastIndexOf('.') + 1); + logger.error("{}", message, t); } - private static synchronized void initialize() { - if (initialized) { - return; - } - - // We flag as initialized right away because if anything goes wrong - // We still consider it initialized. TODO Is this OK? - initialized = true; - - InputStream is = - Thread.currentThread().getContextClassLoader().getResourceAsStream("log4testng.properties"); - if (is == null) { - return; - } - Properties properties = new Properties(); - try { - properties.load(is); - } catch (IOException e) { - throw new RuntimeException(e); - } - - checkProperties(properties); - } - - static void checkProperties(Properties pProperties) { - { - // See if we want to debug log4testng - String debugStr = pProperties.getProperty(DEBUG_PROPERTY); - if (debugStr != null) { - if (debugStr.equalsIgnoreCase("true")) { - debug = true; - } else if (debugStr.equalsIgnoreCase("false")) { - debug = false; - } else { - throw new IllegalArgumentException("Unknown " + DEBUG_PROPERTY + " value " + debugStr); - } - } - loglog4testng("log4testng.debug set to " + debug); - } - - { - // Set the value of the root logger (if any). - String rootLevelStr = pProperties.getProperty(ROOT_LOGGER); - if (rootLevelStr != null) { - Integer ilevel = levelMap.get(rootLevelStr.toUpperCase(Locale.ROOT)); - if (ilevel == null) { - throw new IllegalArgumentException( - "Unknown level for log4testng.rootLogger " - + rootLevelStr - + " in log4testng.properties"); - } - rootLoggerLevel = ilevel; - loglog4testng("Root level logger set to " + rootLevelStr + " level."); - } - } - - Iterator it = pProperties.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = (Entry) it.next(); - String logger = (String) entry.getKey(); - String level = (String) entry.getValue(); - - if (!logger.startsWith(PREFIX)) { - throw new IllegalArgumentException("Illegal property value: " + logger); - } - if (logger.equals(DEBUG_PROPERTY)) { - // Already handled - } else if (logger.equals(ROOT_LOGGER)) { - // Already handled - } else { - if (!logger.startsWith(LOGGER_PREFIX)) { - throw new IllegalArgumentException("Illegal property value: " + logger); - } - - Integer ilevel = levelMap.get(level.toUpperCase(Locale.ROOT)); - if (ilevel == null) { - throw new IllegalArgumentException( - "Unknown level " + level + " for logger " + logger + " in log4testng.properties"); - } - - loggerLevels.put(logger.substring(LOGGER_PREFIX.length()), ilevel); - loglog4testng("logger " + logger + " set to " + ilevel + " level."); - } - } - } - - /** - * Returns the level associated to the current class. The level is obtain by searching for a - * logger in the "testng-logging.properties" resource. For example, if class is - * "org.testng.TestNG" the the following loggers are searched in this order: - * - *
    - *
  1. "org.testng.TestNG" - *
  2. "org.testng" - *
  3. "org" - *
  4. The root level - *
- * - * @param pClass the class name used for logger name. - * @return the level associated to the current class. - */ - private static int getLevel(Class pClass) { - String name = pClass.getName(); - loglog4testng("Getting level for logger " + name); - while (true) { - Integer level = loggerLevels.get(name); - if (level != null) { - loglog4testng("Found level " + level + " for logger " + name); - - return level; - } - int dot = name.lastIndexOf('.'); - if (dot == -1) { - loglog4testng("Found level " + rootLoggerLevel + " for root logger"); - - // Logger name not found. Defaults to root logger level. - return rootLoggerLevel; - } - name = name.substring(0, dot); - } - } - - private boolean isLevelEnabled(int pLevel) { - return level <= pLevel; - } - - private void log(int pLevel, Object pMessage, Throwable pT) { - if (isLevelEnabled(pLevel)) { - PrintStream ps = (pLevel >= ERROR) ? err : out; - if (null != pT) { - synchronized (ps) { - ps.println("[" + m_className + "] [" + levelNames[pLevel] + "] " + pMessage); - pT.printStackTrace(ps); - } - } else { - ps.println("[" + m_className + "] [" + levelNames[pLevel] + "] " + pMessage); - } - } - } - - /** - * Logs the message to System.out of debug is on. - * - * @param pmessage the message to log to the console - */ - private static void loglog4testng(String pmessage) { - if (debug) { - out.println("[log4testng] [debug] " + pmessage); - } + private Logger(org.slf4j.Logger logger) { + this.logger = logger; } } diff --git a/testng-core-api/testng-core-api-build.gradle.kts b/testng-core-api/testng-core-api-build.gradle.kts index 81b6e3b679..3db3731792 100644 --- a/testng-core-api/testng-core-api-build.gradle.kts +++ b/testng-core-api/testng-core-api-build.gradle.kts @@ -15,4 +15,6 @@ dependencies { "guiceApi"("com.google.inject:guice") implementation(projects.testngReflectionUtils) + api("org.slf4j:slf4j-api:_") + testImplementation("org.slf4j:slf4j-simple:_") } diff --git a/testng-core/src/main/java/org/testng/internal/Graph.java b/testng-core/src/main/java/org/testng/internal/Graph.java index 658bf52d90..b8e85dfff7 100644 --- a/testng-core/src/main/java/org/testng/internal/Graph.java +++ b/testng-core/src/main/java/org/testng/internal/Graph.java @@ -21,7 +21,7 @@ * @author Cedric Beust, Aug 19, 2004 */ public class Graph { - private static final boolean m_verbose = false; + private static final boolean m_verbose = true; private final Map> m_nodes = Maps.newLinkedHashMap(); private List m_strictlySortedNodes = null; private final Comparator> comparator; @@ -154,11 +154,11 @@ private void initializeIndependentNodes() { } private void dumpSortedNodes() { - System.out.println("====== SORTED NODES"); + log("====== SORTED NODES"); for (T n : m_strictlySortedNodes) { - System.out.println(" " + n); + log(" " + n); } - System.out.println("====== END SORTED NODES"); + log("====== END SORTED NODES"); } /** diff --git a/testng-core/src/test/java/org/testng/log4testng/LoggerTest.java b/testng-core/src/test/java/org/testng/log4testng/LoggerTest.java deleted file mode 100644 index 8a28e6fc83..0000000000 --- a/testng-core/src/test/java/org/testng/log4testng/LoggerTest.java +++ /dev/null @@ -1,236 +0,0 @@ -package org.testng.log4testng; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.util.Properties; -import org.testng.Assert; -import org.testng.annotations.Test; - -public class LoggerTest { - /** - * This method is for debugging purpose only. - * - * @param pProperties a properties bundle initialised as log4testng property file would be. - * @param pOut the standard output stream to be used for logging. - * @param pErr the standard error stream to be used for logging. - */ - private static synchronized void testInitialize( - Properties pProperties, PrintStream pOut, PrintStream pErr) { - Logger.initialized = true; - Logger.loggers.clear(); - Logger.rootLoggerLevel = Logger.WARN; - Logger.debug = false; - Logger.out = pOut; - Logger.err = pErr; - Logger.checkProperties(pProperties); - } - - /** Makes sure the default debug value is false. */ - @Test - void testDebugDefault() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - props.put("log4testng.rootLogger", "WARN"); - testInitialize(props, out2, err2); - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - } - - /** Makes sure the debug value can be turned on and actualls logs something. */ - @Test - void testDebugOn() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - props.put("log4testng.debug", "true"); - props.put("log4testng.rootLogger", "WARN"); - testInitialize(props, out2, err2); - Assert.assertTrue(out1.toString().startsWith("[log4testng][debug]")); - Assert.assertEquals(err1.toString(), ""); - } - - /** Makes sure the debug value can be turned off and logs nothing. */ - @Test - void testDebugOff() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - props.put("log4testng.debug", "false"); - props.put("log4testng.rootLogger", "WARN"); - testInitialize(props, out2, err2); - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - } - - /** Makes sure an illegal debug value throws an exception. */ - @Test - void testDebugError() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - props.put("log4testng.debug", "unknown"); - props.put("log4testng.rootLogger", "WARN"); - try { - testInitialize(props, out2, err2); - throw new RuntimeException("failure"); - } catch (IllegalArgumentException pEx) { - - // Normal case - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - } - } - - /** - * Tests that the root logger's default level is WARN and that loggers do not log bellow this - * level and do log in the correct stream for levels equal to and above WARN. - */ - @Test - void testRootLoggerDefault() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - testInitialize(props, out2, err2); - - Logger strLogger = Logger.getLogger(String.class); - strLogger.trace("trace should not appear"); - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - strLogger.debug("debug should not appear"); - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - strLogger.info("info should not appear"); - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - strLogger.warn("warn should appear"); - int outlength = out1.toString().length(); - Assert.assertTrue(out1.toString().startsWith("[java.lang.String] [WARN] warn should appear")); - Assert.assertEquals(err1.toString(), ""); - strLogger.error("error should appear"); - Assert.assertEquals(out1.toString().length(), outlength); - Assert.assertTrue(err1.toString().startsWith("[java.lang.String] [ERROR] error should appear")); - strLogger.fatal("fatal should appear"); - Assert.assertEquals(out1.toString().length(), outlength); - Assert.assertTrue(err1.toString().contains("[java.lang.String] [FATAL] fatal should appear")); - } - - /** Test setting the root logger level */ - @Test - void testRootLoggerSet() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - props.put("log4testng.rootLogger", "DEBUG"); - testInitialize(props, out2, err2); - - Logger strLogger = Logger.getLogger(String.class); - strLogger.trace("trace should appear"); - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - strLogger.debug("debug should appear"); - Assert.assertTrue(out1.toString().startsWith("[java.lang.String] [DEBUG] debug should appear")); - Assert.assertEquals(err1.toString(), ""); - } - - /** Test setting the root logger to an illegal level value throws an exception. */ - @Test - void testRootLoggerSetError() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - props.put("log4testng.rootLogger", "unknown"); - try { - testInitialize(props, out2, err2); - throw new RuntimeException("failure"); - } catch (IllegalArgumentException pEx) { - - // Normal case - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - } - } - - /** Test setting a user logger level */ - @Test - void testUserLoggerSet() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - props.put("log4testng.logger.java.lang.String", "DEBUG"); - testInitialize(props, out2, err2); - - Logger strLogger = Logger.getLogger(String.class); - strLogger.trace("trace should not appear"); - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - strLogger.debug("debug should appear"); - int outLength = out1.toString().length(); - Assert.assertTrue(out1.toString().startsWith("[java.lang.String] [DEBUG] debug should appear")); - Assert.assertEquals(err1.toString(), ""); - - Logger classLogger = Logger.getLogger(Class.class); - classLogger.debug("debug should not appear"); - Assert.assertEquals(out1.toString().length(), outLength); - Assert.assertEquals(err1.toString(), ""); - classLogger.warn("warn should appear"); - Assert.assertTrue(out1.toString().contains("[java.lang.Class] [WARN] warn should appear")); - Assert.assertEquals(err1.toString(), ""); - } - - /** Test setting a user logger to an illegal level value throws an exception */ - @Test - void testUserLoggerSetError() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - props.put("log4testng.logger.java.lang.String", "unknown"); - try { - testInitialize(props, out2, err2); - throw new RuntimeException("failure"); - } catch (IllegalArgumentException pEx) { - - // Normal case - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - } - } - - /** Tests setting a partial logger name (a hierarchy scope) */ - @Test - void testUserLoggerSetHierarchy() { - Properties props = new Properties(); - ByteArrayOutputStream out1 = new ByteArrayOutputStream(); - ByteArrayOutputStream err1 = new ByteArrayOutputStream(); - PrintStream out2 = new PrintStream(out1); - PrintStream err2 = new PrintStream(err1); - props.put("log4testng.logger.java.lang", "DEBUG"); - testInitialize(props, out2, err2); - - Logger strLogger = Logger.getLogger(String.class); - strLogger.trace("trace should not appear"); - Assert.assertEquals(out1.toString(), ""); - Assert.assertEquals(err1.toString(), ""); - strLogger.debug("debug should appear"); - Assert.assertTrue(out1.toString().startsWith("[java.lang.String] [DEBUG] debug should appear")); - Assert.assertEquals(err1.toString(), ""); - } -} diff --git a/testng-core/src/test/resources/simplelogger.properties b/testng-core/src/test/resources/simplelogger.properties new file mode 100644 index 0000000000..60503197a7 --- /dev/null +++ b/testng-core/src/test/resources/simplelogger.properties @@ -0,0 +1,6 @@ +org.slf4j.simpleLogger.logFile=System.out +org.slf4j.simpleLogger.cacheOutputStream=true +org.slf4j.simpleLogger.defaultLogLevel=warn +org.slf4j.simpleLogger.showDateTime=true +org.slf4j.simpleLogger.showThreadName=true + diff --git a/versions.properties b/versions.properties index ba5f8e8459..1efdb74b7c 100644 --- a/versions.properties +++ b/versions.properties @@ -94,3 +94,6 @@ version.org.yaml..snakeyaml=1.21 ## # available=1.26 ## # available=1.27 ## # available=1.28 + +version.org.slf4j..slf4j-simple=1.7.32 +version.org.slf4j..slf4j-api=1.7.32