1 package org.slf4j.simple; 2 3 4 import org.junit.Test; 5 import org.slf4j.Logger; 6 import org.slf4j.event.Level; 7 8 import java.io.IOException; 9 import java.io.OutputStream; 10 import java.util.ArrayList; 11 import java.util.List; 12 13 import static org.junit.Assert.assertEquals; 14 import static org.junit.Assert.assertTrue; 15 16 17 public abstract class LoggerTestSuite { 18 19 public static class ListAppendingOutputStream extends OutputStream { 20 private final StringBuilder word = new StringBuilder(); 21 private int index = 0; 22 private final List<String> list; 23 ListAppendingOutputStream(List<String> list)24 private ListAppendingOutputStream(List<String> list) {this.list = list;} 25 26 27 @Override write(int b)28 public void write(int b) throws IOException { 29 word.append((char) b); 30 } 31 32 @Override flush()33 public void flush() { 34 list.add(word.toString()); 35 word.delete(0, word.length()); 36 index++; 37 } 38 } 39 prepareSink(List<String> source)40 private ListAppendingOutputStream prepareSink(List<String> source) { 41 return new ListAppendingOutputStream(source); 42 43 } 44 45 @Test testTrace()46 public void testTrace() { 47 ArrayList<String> loggingEvents = new ArrayList<>(); 48 Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.TRACE); 49 50 assertTrue("Trace level should be enabled for this test", configuredLogger.isTraceEnabled()); 51 configuredLogger.trace("Simple trace message"); 52 53 assertEquals("Trace message should've been captured", 1, loggingEvents.size()); 54 assertTrue("Message should be logged in trace level", isTraceMessage(loggingEvents.get(0))); 55 assertEquals("Supplied trace message wasn't found in the log", 56 "Simple trace message", 57 extractMessage(loggingEvents.get(0))); 58 59 loggingEvents.clear(); 60 61 configuredLogger.debug("Simple debug message"); 62 configuredLogger.info("Simple info message"); 63 configuredLogger.warn("Simple warn message"); 64 configuredLogger.error("Simple error message"); 65 assertEquals("The other levels should have been captured", 4, loggingEvents.size()); 66 67 } 68 69 @Test testDebug()70 public void testDebug() { 71 ArrayList<String> loggingEvents = new ArrayList<>(); 72 Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.DEBUG); 73 74 configuredLogger.trace("Simple trace message"); 75 assertEquals("Lower levels should have been ignored", 0, loggingEvents.size()); 76 77 assertTrue("Debug level should be enabled for this test", configuredLogger.isDebugEnabled()); 78 configuredLogger.debug("Simple debug message"); 79 80 assertEquals("Debug message should've been captured", 1, loggingEvents.size()); 81 assertTrue("Message should be logged in debug level", isDebugMessage(loggingEvents.get(0))); 82 assertEquals("Supplied debug message wasn't found in the log", 83 "Simple debug message", 84 extractMessage(loggingEvents.get(0))); 85 86 loggingEvents.clear(); 87 88 configuredLogger.info("Simple info message"); 89 configuredLogger.warn("Simple warn message"); 90 configuredLogger.error("Simple error message"); 91 assertEquals("The other levels should have been captured", 3, loggingEvents.size()); 92 } 93 94 95 @Test testInfo()96 public void testInfo() { 97 ArrayList<String> loggingEvents = new ArrayList<>(); 98 Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.INFO); 99 100 configuredLogger.trace("Simple trace message"); 101 configuredLogger.debug("Simple debug message"); 102 assertEquals("Lower levels should have been ignored", 0, loggingEvents.size()); 103 104 assertTrue("Info level should be enabled for this test", configuredLogger.isInfoEnabled()); 105 configuredLogger.info("Simple info message"); 106 107 assertEquals("Info message should've been captured", 1, loggingEvents.size()); 108 assertTrue("Message should be logged in debug level", isInfoMessage(loggingEvents.get(0))); 109 assertEquals("Supplied info message wasn't found in the log", 110 "Simple info message", 111 extractMessage(loggingEvents.get(0))); 112 113 loggingEvents.clear(); 114 115 configuredLogger.warn("Simple warn message"); 116 configuredLogger.error("Simple error message"); 117 assertEquals("The other levels should have been captured", 2, loggingEvents.size()); 118 } 119 120 @Test testWarn()121 public void testWarn() { 122 ArrayList<String> loggingEvents = new ArrayList<>(); 123 Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.WARN); 124 125 configuredLogger.trace("Simple trace message"); 126 configuredLogger.debug("Simple debug message"); 127 configuredLogger.info("Simple info message"); 128 assertEquals("Lower levels should have been ignored", 0, loggingEvents.size()); 129 130 assertTrue("Warn level should be enabled for this test", configuredLogger.isWarnEnabled()); 131 configuredLogger.warn("Simple warn message"); 132 133 assertEquals("Warn message should've been captured", 1, loggingEvents.size()); 134 assertTrue("Message should be logged in warn level", isWarnMessage(loggingEvents.get(0))); 135 assertEquals("Supplied warn message wasn't found in the log", 136 "Simple warn message", 137 extractMessage(loggingEvents.get(0))); 138 139 loggingEvents.clear(); 140 141 configuredLogger.error("Simple error message"); 142 assertEquals("The other levels should have been captured", 1, loggingEvents.size()); 143 } 144 145 @Test testError()146 public void testError() { 147 ArrayList<String> loggingEvents = new ArrayList<>(); 148 Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.ERROR); 149 150 configuredLogger.trace("Simple trace message"); 151 configuredLogger.debug("Simple debug message"); 152 configuredLogger.info("Simple info message"); 153 configuredLogger.warn("Simple warn message"); 154 assertEquals("Lower levels should have been ignored", 0, loggingEvents.size()); 155 156 assertTrue("Error level should be enabled for this test", configuredLogger.isErrorEnabled()); 157 configuredLogger.error("Simple error message"); 158 159 assertEquals("Error message should've been captured", 1, loggingEvents.size()); 160 assertTrue("Message should be logged in error level", isErrorMessage(loggingEvents.get(0))); 161 assertEquals("Supplied error message wasn't found in the log", 162 "Simple error message", 163 extractMessage(loggingEvents.get(0))); 164 } 165 166 @Test testFormatting()167 public void testFormatting() { 168 ArrayList<String> loggingEvents = new ArrayList<>(); 169 Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.INFO); 170 171 configuredLogger.info("Some {} string", "formatted"); 172 assertEquals("The formatted message should've been captured", 1, loggingEvents.size()); 173 assertEquals("Message should've been formatted", "Some formatted string", extractMessage(loggingEvents.get(0))); 174 } 175 176 @Test testException()177 public void testException() { 178 ArrayList<String> loggingEvents = new ArrayList<>(); 179 Logger configuredLogger = createLogger(prepareSink(loggingEvents), Level.INFO); 180 181 Exception exception = new RuntimeException("My error"); 182 183 configuredLogger.info("Logging with an exception", exception); 184 assertEquals("The formatted message should've been captured", 1, loggingEvents.size()); 185 assertEquals("Message should've been formatted", 186 "My error", 187 extractExceptionMessage(loggingEvents.get(0))); 188 189 assertEquals("Message should've been formatted", 190 "java.lang.RuntimeException", 191 extractExceptionType(loggingEvents.get(0))); 192 } 193 194 195 /** 196 * Allows tests to check whether the log message contains a trace message. 197 * Override if needed. 198 * @param message String containing the full log message 199 * @return whether it is a trace message or not 200 */ isTraceMessage(String message)201 protected boolean isTraceMessage(String message) { 202 return message.toLowerCase().contains("trace"); 203 } 204 205 /** 206 * Allows tests to check whether the log message contains a debug message. 207 * Override if needed. 208 * @param message String containing the full log message 209 * @return whether it is a debug message or not 210 */ isDebugMessage(String message)211 protected boolean isDebugMessage(String message) { 212 return message.toLowerCase().contains("debug"); 213 } 214 215 /** 216 * Allows tests to check whether the log message contains an info message. 217 * Override if needed. 218 * @param message String containing the full log message 219 * @return whether it is an info message or not 220 */ isInfoMessage(String message)221 protected boolean isInfoMessage(String message) { 222 return message.toLowerCase().contains("info"); 223 } 224 225 /** 226 * Allows tests to check whether the log message contains a warn message. 227 * Override if needed. 228 * @param message String containing the full log message 229 * @return whether it is a warn message or not 230 */ isWarnMessage(String message)231 protected boolean isWarnMessage(String message) { 232 return message.toLowerCase().contains("warn"); 233 } 234 235 /** 236 * Allows tests to check whether the log message contains an error message. 237 * Override if needed. 238 * @param message String containing the full log message 239 * @return whether it is an error message or not 240 */ isErrorMessage(String message)241 protected boolean isErrorMessage(String message) { 242 return message.toLowerCase().contains("error"); 243 } 244 245 /** 246 * Extracts only the part of the log string that should represent the `message` string. 247 * @param message the full log message 248 * @return only the supplied message 249 */ extractMessage(String message)250 public abstract String extractMessage(String message); 251 252 /** 253 * Extracts only the part of the log string that should represent the supplied exception message, if any. 254 * @param message the full log message 255 * @return only the supplied exception message 256 */ extractExceptionMessage(String message)257 public abstract String extractExceptionMessage(String message); 258 259 /** 260 * Extracts only the part of the log string that should represent the supplied exception type. 261 * @param message the full log message 262 * @return only the supplied exception type name 263 */ extractExceptionType(String message)264 public abstract String extractExceptionType(String message); 265 266 /** 267 * Configures the logger for running the tests. 268 * @param outputStream The output stream for logs to be written to 269 * @param level The expected level the tests will run for this logger 270 * @return a configured logger able to run the tests 271 */ createLogger(ListAppendingOutputStream outputStream, Level level)272 public abstract Logger createLogger(ListAppendingOutputStream outputStream, Level level); 273 274 }