001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.classic.net; 015 016import static org.junit.Assert.assertEquals; 017import static org.junit.Assert.assertTrue; 018 019import org.junit.After; 020import org.junit.Before; 021import org.junit.Ignore; 022import org.junit.Test; 023import org.slf4j.LoggerFactory; 024 025import ch.qos.logback.classic.ClassicTestConstants; 026import ch.qos.logback.classic.Logger; 027import ch.qos.logback.classic.LoggerContext; 028import ch.qos.logback.classic.joran.JoranConfigurator; 029import ch.qos.logback.classic.net.mock.MockSyslogServer; 030import ch.qos.logback.core.CoreConstants; 031import ch.qos.logback.core.joran.spi.JoranException; 032import ch.qos.logback.core.net.SyslogConstants; 033import ch.qos.logback.core.recovery.RecoveryCoordinator; 034import ch.qos.logback.core.testUtil.RandomUtil; 035import ch.qos.logback.core.util.StatusPrinter; 036 037import java.nio.charset.Charset; 038@Ignore 039public class SyslogAppenderTest { 040 041 private static final String SYSLOG_PREFIX_REGEX = "<\\d{2}>\\w{3} [\\d ]\\d \\d{2}(:\\d{2}){2} [\\w.-]* "; 042 043 LoggerContext lc = new LoggerContext(); 044 SyslogAppender sa = new SyslogAppender(); 045 MockSyslogServer mockServer; 046 String loggerName = this.getClass().getName(); 047 Logger logger = lc.getLogger(loggerName); 048 049 @Before 050 public void setUp() throws Exception { 051 lc.setName("test"); 052 sa.setContext(lc); 053 } 054 055 @After 056 public void tearDown() throws Exception { 057 } 058 059 public void setMockServerAndConfigure(int expectedCount, String suffixPattern) throws InterruptedException { 060 int port = RandomUtil.getRandomServerPort(); 061 062 mockServer = new MockSyslogServer(expectedCount, port); 063 mockServer.start(); 064 // give MockSyslogServer head start 065 066 Thread.sleep(100); 067 068 sa.setSyslogHost("localhost"); 069 sa.setFacility("MAIL"); 070 sa.setPort(port); 071 sa.setSuffixPattern(suffixPattern); 072 sa.setStackTracePattern("[%thread] foo " + CoreConstants.TAB); 073 sa.start(); 074 assertTrue(sa.isStarted()); 075 076 String loggerName = this.getClass().getName(); 077 Logger logger = lc.getLogger(loggerName); 078 logger.addAppender(sa); 079 080 } 081 082 public void setMockServerAndConfigure(int expectedCount) throws InterruptedException { 083 this.setMockServerAndConfigure(expectedCount, "[%thread] %logger %msg"); 084 } 085 086 @Test 087 public void basic() throws InterruptedException { 088 089 setMockServerAndConfigure(1); 090 String logMsg = "hello"; 091 logger.debug(logMsg); 092 093 // wait max 2 seconds for mock server to finish. However, it should 094 // much sooner than that. 095 mockServer.join(8000); 096 097 assertTrue(mockServer.isFinished()); 098 assertEquals(1, mockServer.getMessageList().size()); 099 String msg = new String(mockServer.getMessageList().get(0)); 100 101 String threadName = Thread.currentThread().getName(); 102 103 String expected = "<" + (SyslogConstants.LOG_MAIL + SyslogConstants.DEBUG_SEVERITY) + ">"; 104 assertTrue(msg.startsWith(expected)); 105 106 checkRegexMatch(msg, SYSLOG_PREFIX_REGEX + "\\[" + threadName + "\\] " + loggerName + " " + logMsg); 107 108 } 109 110 @Test 111 public void suffixPatternWithTag() throws InterruptedException { 112 setMockServerAndConfigure(1, "test/something [%thread] %logger %msg"); 113 String logMsg = "hello"; 114 logger.debug(logMsg); 115 116 // wait max 2 seconds for mock server to finish. However, it should 117 // much sooner than that. 118 mockServer.join(8000); 119 120 assertTrue(mockServer.isFinished()); 121 assertEquals(1, mockServer.getMessageList().size()); 122 String msg = new String(mockServer.getMessageList().get(0)); 123 124 String threadName = Thread.currentThread().getName(); 125 126 String expected = "<" + (SyslogConstants.LOG_MAIL + SyslogConstants.DEBUG_SEVERITY) + ">"; 127 assertTrue(msg.startsWith(expected)); 128 129 checkRegexMatch(msg, SYSLOG_PREFIX_REGEX + "test/something \\[" + threadName + "\\] " + loggerName + " " + logMsg); 130 131 } 132 133 @Test 134 public void tException() throws InterruptedException { 135 setMockServerAndConfigure(21); 136 137 String logMsg = "hello"; 138 String exMsg = "just testing"; 139 Exception ex = new Exception(exMsg); 140 logger.debug(logMsg, ex); 141 StatusPrinter.print(lc); 142 143 // wait max 2 seconds for mock server to finish. However, it should 144 // much sooner than that. 145 mockServer.join(8000); 146 assertTrue(mockServer.isFinished()); 147 148 // message + 20 lines of stacktrace 149 assertEquals(21, mockServer.getMessageList().size()); 150 // int i = 0; 151 // for (String line: mockServer.msgList) { 152 // System.out.println(i++ + ": " + line); 153 // } 154 155 String msg = new String(mockServer.getMessageList().get(0)); 156 String expected = "<" + (SyslogConstants.LOG_MAIL + SyslogConstants.DEBUG_SEVERITY) + ">"; 157 assertTrue(msg.startsWith(expected)); 158 159 String threadName = Thread.currentThread().getName(); 160 String regex = SYSLOG_PREFIX_REGEX + "\\[" + threadName + "\\] " + loggerName + " " + logMsg; 161 checkRegexMatch(msg, regex); 162 163 msg = new String(mockServer.getMessageList().get(1)); 164 assertTrue(msg.contains(ex.getClass().getName())); 165 assertTrue(msg.contains(ex.getMessage())); 166 167 msg = new String(mockServer.getMessageList().get(2)); 168 assertTrue(msg.startsWith(expected)); 169 regex = SYSLOG_PREFIX_REGEX + "\\[" + threadName + "\\] " + "foo " + CoreConstants.TAB + "at ch\\.qos.*"; 170 checkRegexMatch(msg, regex); 171 } 172 173 private void checkRegexMatch(String s, String regex) { 174 assertTrue("The string [" + s + "] did not match regex [" + regex + "]", s.matches(regex)); 175 } 176 177 @Test 178 public void large() throws Exception { 179 setMockServerAndConfigure(2); 180 StringBuilder largeBuf = new StringBuilder(); 181 for (int i = 0; i < 2 * 1024 * 1024; i++) { 182 largeBuf.append('a'); 183 } 184 logger.debug(largeBuf.toString()); 185 186 String logMsg = "hello"; 187 logger.debug(logMsg); 188 Thread.sleep(RecoveryCoordinator.BACKOFF_COEFFICIENT_MIN + 10); 189 logger.debug(logMsg); 190 191 mockServer.join(8000); 192 assertTrue(mockServer.isFinished()); 193 194 // both messages received 195 assertEquals(2, mockServer.getMessageList().size()); 196 197 String expected = "<" + (SyslogConstants.LOG_MAIL + SyslogConstants.DEBUG_SEVERITY) + ">"; 198 String threadName = Thread.currentThread().getName(); 199 200 // large message is truncated 201 final int maxMessageSize = sa.getMaxMessageSize(); 202 String largeMsg = new String(mockServer.getMessageList().get(0)); 203 assertTrue(largeMsg.startsWith(expected)); 204 String largeRegex = SYSLOG_PREFIX_REGEX + "\\[" + threadName + "\\] " + loggerName + " " + "a{" + (maxMessageSize - 2000) + "," + maxMessageSize + "}"; 205 checkRegexMatch(largeMsg, largeRegex); 206 207 String msg = new String(mockServer.getMessageList().get(1)); 208 assertTrue(msg.startsWith(expected)); 209 String regex = SYSLOG_PREFIX_REGEX + "\\[" + threadName + "\\] " + loggerName + " " + logMsg; 210 checkRegexMatch(msg, regex); 211 } 212 213 @Test 214 public void LBCLASSIC_50() throws JoranException { 215 216 LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); 217 218 JoranConfigurator configurator = new JoranConfigurator(); 219 configurator.setContext(lc); 220 lc.reset(); 221 configurator.doConfigure(ClassicTestConstants.JORAN_INPUT_PREFIX + "syslog_LBCLASSIC_50.xml"); 222 223 org.slf4j.Logger logger = LoggerFactory.getLogger(this.getClass()); 224 logger.info("hello"); 225 } 226 227 @Test 228 public void unknownHostShouldNotCauseStopToFail() { 229 // See LOGBACK-960 230 sa.setSyslogHost("unknown.host"); 231 sa.setFacility("MAIL"); 232 sa.start(); 233 sa.stop(); 234 } 235 236 @Test 237 public void nonAsciiMessageEncoding() throws Exception { 238 // See LOGBACK-732 239 setMockServerAndConfigure(1); 240 241 // Use a string that can be encoded in a somewhat odd encoding (ISO-8859-4) to minimize 242 // the probability of the encoding test to work by accident 243 String logMsg = "R\u0129ga"; // Riga spelled with the i having a tilda on top 244 245 Charset ISO_8859_4 = Charset.forName("ISO-8859-4"); 246 sa.setCharset(ISO_8859_4); 247 logger.debug(logMsg); 248 249 // wait max 8 seconds for mock server to finish. However, it should 250 // be done much sooner than that. 251 mockServer.join(8000); 252 253 assertTrue(mockServer.isFinished()); 254 assertEquals(1, mockServer.getMessageList().size()); 255 String msg = new String(mockServer.getMessageList().get(0), ISO_8859_4); 256 String threadName = Thread.currentThread().getName(); 257 258 String expected = "<" + (SyslogConstants.LOG_MAIL + SyslogConstants.DEBUG_SEVERITY) + ">"; 259 assertTrue(msg.startsWith(expected)); 260 261 System.out.println(logMsg); 262 checkRegexMatch(msg, SYSLOG_PREFIX_REGEX + "\\[" + threadName + "\\] " + loggerName + " " + logMsg); 263 264 } 265}