From 67a5ab77c6efbcd6136ce332f975f4a1ff572835 Mon Sep 17 00:00:00 2001 From: Henry Kupty Date: Mon, 9 Oct 2023 21:48:09 +0200 Subject: [PATCH] test: Add new acceptance test project Signed-off-by: Henry Kupty --- pom.xml | 1 + slf4j-simple/pom.xml | 8 + .../java/org/slf4j/simple/AcceptanceTest.java | 49 ++++ slf4j-test/pom.xml | 39 +++ .../java/org/slf4j/test/LoggerTestSuite.java | 232 ++++++++++++++++++ slf4j-test/src/main/java9/module-info.java | 4 + 6 files changed, 333 insertions(+) create mode 100644 slf4j-simple/src/test/java/org/slf4j/simple/AcceptanceTest.java create mode 100644 slf4j-test/pom.xml create mode 100644 slf4j-test/src/main/java/org/slf4j/test/LoggerTestSuite.java create mode 100755 slf4j-test/src/main/java9/module-info.java diff --git a/pom.xml b/pom.xml index 06a0ce509..c9c4b5179 100755 --- a/pom.xml +++ b/pom.xml @@ -46,6 +46,7 @@ osgi-over-slf4j integration slf4j-migrator + slf4j-test diff --git a/slf4j-simple/pom.xml b/slf4j-simple/pom.xml index c57e09985..1c5527951 100755 --- a/slf4j-simple/pom.xml +++ b/slf4j-simple/pom.xml @@ -36,6 +36,14 @@ ${project.version} test + + + org.slf4j + slf4j-test + jar + ${project.version} + test + diff --git a/slf4j-simple/src/test/java/org/slf4j/simple/AcceptanceTest.java b/slf4j-simple/src/test/java/org/slf4j/simple/AcceptanceTest.java new file mode 100644 index 000000000..e57dc8166 --- /dev/null +++ b/slf4j-simple/src/test/java/org/slf4j/simple/AcceptanceTest.java @@ -0,0 +1,49 @@ +package org.slf4j.simple; + +import org.slf4j.Logger; +import org.slf4j.event.Level; +import org.slf4j.test.LoggerTestSuite; + +import java.io.PrintStream; + +public class AcceptanceTest extends LoggerTestSuite { + + @Override + public Logger createLogger(ListAppendingOutputStream outputStream, Level level) { + SimpleLogger.CONFIG_PARAMS.outputChoice = new OutputChoice(new PrintStream(outputStream)); + + SimpleLogger logger = new SimpleLogger("TestSuiteLogger"); + logger.currentLogLevel = SimpleLoggerConfiguration.stringToLevel(level.toString()); + return logger; + } + + @Override + public String extractMessage(String message) { + return message + .split("\n")[0] + .split("- ")[1]; + } + + @Override + public String extractExceptionMessage(String message) { + String[] logLines = message.split("\n"); + + if (logLines.length < 2) { + return null; + } + String exceptionLine = logLines[1]; + return exceptionLine.split(": ")[1]; + } + + @Override + public String extractExceptionType(String message) { + String[] logLines = message.split("\n"); + + if (logLines.length < 2) { + return null; + } + String exceptionLine = logLines[1]; + return exceptionLine.split(": ")[0]; + } + +} diff --git a/slf4j-test/pom.xml b/slf4j-test/pom.xml new file mode 100644 index 000000000..1fe009785 --- /dev/null +++ b/slf4j-test/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + + org.slf4j + slf4j-parent + 2.0.10-SNAPSHOT + ../parent/pom.xml + + + slf4j-test + + jar + SLF4J Tests + SLF4J Implementation Acceptance Tests + http://www.slf4j.org + + + org.slf4j.test + + + + + org.slf4j + slf4j-api + + + + junit + junit + ${junit.version} + + + + + \ No newline at end of file diff --git a/slf4j-test/src/main/java/org/slf4j/test/LoggerTestSuite.java b/slf4j-test/src/main/java/org/slf4j/test/LoggerTestSuite.java new file mode 100644 index 000000000..b2ffee0e2 --- /dev/null +++ b/slf4j-test/src/main/java/org/slf4j/test/LoggerTestSuite.java @@ -0,0 +1,232 @@ +package org.slf4j.test; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.event.Level; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + + +public abstract class LoggerTestSuite { + + public static class ListAppendingOutputStream extends OutputStream { + private final StringBuilder word = new StringBuilder(); + private final List list; + + private ListAppendingOutputStream(List list) {this.list = list;} + + + @Override + public void write(int b) throws IOException { + word.append((char) b); + } + + @Override + public void flush() { + list.add(word.toString()); + // Resets the string builder for a next log message + word.delete(0, word.length()); + } + } + + private ListAppendingOutputStream prepareSink(List source) { + return new ListAppendingOutputStream(source); + + } + + @Test + public void testTrace() { + ArrayList loggingEvents = new ArrayList<>(); + Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.TRACE); + + assertTrue("Trace level should be enabled for this test", configuredLogger.isTraceEnabled()); + configuredLogger.trace("Simple trace message"); + + assertEquals("Trace message should've been captured", 1, loggingEvents.size()); + assertTrue("Message should be logged in trace level", isLevel(loggingEvents.get(0), Level.TRACE)); + assertEquals("Supplied trace message wasn't found in the log", + "Simple trace message", + extractMessage(loggingEvents.get(0))); + + loggingEvents.clear(); + + configuredLogger.debug("Simple debug message"); + configuredLogger.info("Simple info message"); + configuredLogger.warn("Simple warn message"); + configuredLogger.error("Simple error message"); + assertEquals("The other levels should have been captured", 4, loggingEvents.size()); + + } + + @Test + public void testDebug() { + ArrayList loggingEvents = new ArrayList<>(); + Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.DEBUG); + + configuredLogger.trace("Simple trace message"); + assertEquals("Lower levels should have been ignored", 0, loggingEvents.size()); + + assertTrue("Debug level should be enabled for this test", configuredLogger.isDebugEnabled()); + configuredLogger.debug("Simple debug message"); + + assertEquals("Debug message should've been captured", 1, loggingEvents.size()); + assertTrue("Message should be logged in debug level", isLevel(loggingEvents.get(0), Level.DEBUG)); + assertEquals("Supplied debug message wasn't found in the log", + "Simple debug message", + extractMessage(loggingEvents.get(0))); + + loggingEvents.clear(); + + configuredLogger.info("Simple info message"); + configuredLogger.warn("Simple warn message"); + configuredLogger.error("Simple error message"); + assertEquals("The other levels should have been captured", 3, loggingEvents.size()); + } + + + @Test + public void testInfo() { + ArrayList loggingEvents = new ArrayList<>(); + Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.INFO); + + configuredLogger.trace("Simple trace message"); + configuredLogger.debug("Simple debug message"); + assertEquals("Lower levels should have been ignored", 0, loggingEvents.size()); + + assertTrue("Info level should be enabled for this test", configuredLogger.isInfoEnabled()); + configuredLogger.info("Simple info message"); + + assertEquals("Info message should've been captured", 1, loggingEvents.size()); + assertTrue("Message should be logged in debug level", isLevel(loggingEvents.get(0), Level.INFO)); + assertEquals("Supplied info message wasn't found in the log", + "Simple info message", + extractMessage(loggingEvents.get(0))); + + loggingEvents.clear(); + + configuredLogger.warn("Simple warn message"); + configuredLogger.error("Simple error message"); + assertEquals("The other levels should have been captured", 2, loggingEvents.size()); + } + + @Test + public void testWarn() { + ArrayList loggingEvents = new ArrayList<>(); + Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.WARN); + + configuredLogger.trace("Simple trace message"); + configuredLogger.debug("Simple debug message"); + configuredLogger.info("Simple info message"); + assertEquals("Lower levels should have been ignored", 0, loggingEvents.size()); + + assertTrue("Warn level should be enabled for this test", configuredLogger.isWarnEnabled()); + configuredLogger.warn("Simple warn message"); + + assertEquals("Warn message should've been captured", 1, loggingEvents.size()); + assertTrue("Message should be logged in warn level", isLevel(loggingEvents.get(0), Level.WARN)); + assertEquals("Supplied warn message wasn't found in the log", + "Simple warn message", + extractMessage(loggingEvents.get(0))); + + loggingEvents.clear(); + + configuredLogger.error("Simple error message"); + assertEquals("The other levels should have been captured", 1, loggingEvents.size()); + } + + @Test + public void testError() { + ArrayList loggingEvents = new ArrayList<>(); + Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.ERROR); + + configuredLogger.trace("Simple trace message"); + configuredLogger.debug("Simple debug message"); + configuredLogger.info("Simple info message"); + configuredLogger.warn("Simple warn message"); + assertEquals("Lower levels should have been ignored", 0, loggingEvents.size()); + + assertTrue("Error level should be enabled for this test", configuredLogger.isErrorEnabled()); + configuredLogger.error("Simple error message"); + + assertEquals("Error message should've been captured", 1, loggingEvents.size()); + assertTrue("Message should be logged in error level", isLevel(loggingEvents.get(0), Level.ERROR)); + assertEquals("Supplied error message wasn't found in the log", + "Simple error message", + extractMessage(loggingEvents.get(0))); + } + + @Test + public void testFormatting() { + ArrayList loggingEvents = new ArrayList<>(); + Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.INFO); + + configuredLogger.info("Some {} string", "formatted"); + assertEquals("The formatted message should've been captured", 1, loggingEvents.size()); + assertEquals("Message should've been formatted", "Some formatted string", extractMessage(loggingEvents.get(0))); + } + + @Test + public void testException() { + ArrayList loggingEvents = new ArrayList<>(); + Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.INFO); + + Exception exception = new RuntimeException("My error"); + + configuredLogger.info("Logging with an exception", exception); + assertEquals("The formatted message should've been captured", 1, loggingEvents.size()); + assertEquals("Message should've been formatted", + "My error", + extractExceptionMessage(loggingEvents.get(0))); + + assertEquals("Message should've been formatted", + "java.lang.RuntimeException", + extractExceptionType(loggingEvents.get(0))); + } + + /** + * Allows tests to check whether the logged message corresponds to the supplied level. + * Override if needed. + * @param message String containing the full log message + * @param level {@link Level} the message is expected to be in + * @return returns true if the level matches + */ + protected boolean isLevel(String message, Level level) { + return message.toUpperCase().contains(level.toString()); + } + + /** + * Extracts only the part of the log string that should represent the `message` string. + * @param message the full log message + * @return only the supplied message + */ + public abstract String extractMessage(String message); + + /** + * Extracts only the part of the log string that should represent the supplied exception message, if any. + * @param message the full log message + * @return only the supplied exception message + */ + public abstract String extractExceptionMessage(String message); + + /** + * Extracts only the part of the log string that should represent the supplied exception type. + * @param message the full log message + * @return only the supplied exception type name + */ + public abstract String extractExceptionType(String message); + + /** + * Configures the logger for running the tests. + * @param outputStream The output stream for logs to be written to + * @param level The expected level the tests will run for this logger + * @return a configured logger able to run the tests + */ + public abstract Logger createLogger(ListAppendingOutputStream outputStream, Level level); + +} \ No newline at end of file diff --git a/slf4j-test/src/main/java9/module-info.java b/slf4j-test/src/main/java9/module-info.java new file mode 100755 index 000000000..520c2f9ba --- /dev/null +++ b/slf4j-test/src/main/java9/module-info.java @@ -0,0 +1,4 @@ +module org.slf4j.test { + requires org.slf4j; + exports org.slf4j.test; +}