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.db; 015 016import ch.qos.logback.classic.LoggerContext; 017import ch.qos.logback.classic.joran.JoranConfigurator; 018import ch.qos.logback.core.db.DriverManagerConnectionSource; 019import ch.qos.logback.core.joran.spi.JoranException; 020import ch.qos.logback.core.testUtil.RandomUtil; 021import ch.qos.logback.core.testUtil.StatusChecker; 022import ch.qos.logback.core.util.EnvUtil; 023import ch.qos.logback.core.util.StatusPrinter; 024import org.junit.*; 025import org.slf4j.Logger; 026import org.slf4j.MDC; 027 028import java.net.InetAddress; 029import java.sql.Connection; 030import java.sql.ResultSet; 031import java.sql.SQLException; 032import java.sql.Statement; 033import java.util.HashMap; 034import java.util.Map; 035 036import static org.junit.Assert.*; 037 038public class DBAppenderIntegrationTest { 039 040 static String LOCAL_HOST_NAME; 041 static String[] CONFORMING_HOST_LIST = new String[] { "Orion" }; 042 static String[] POSTGRES_CONFORMING_HOST_LIST = new String[] { "haro" }; 043 static String[] MYSQL_CONFORMING_HOST_LIST = new String[] { "xharo" }; 044 static String[] ORACLE_CONFORMING_HOST_LIST = new String[] { "xharo" }; 045 046 int diff = RandomUtil.getPositiveInt(); 047 LoggerContext lc = new LoggerContext(); 048 049 @BeforeClass 050 public static void setUpBeforeClass() throws Exception { 051 InetAddress localhostIA = InetAddress.getLocalHost(); 052 LOCAL_HOST_NAME = localhostIA.getHostName(); 053 } 054 055 @AfterClass 056 public static void tearDownAfterClass() throws Exception { 057 } 058 059 @Before 060 public void setUp() throws Exception { 061 lc.setName("lc" + diff); 062 } 063 064 @After 065 public void tearDown() throws Exception { 066 // lc will never be used again 067 lc.stop(); 068 } 069 070 DriverManagerConnectionSource getConnectionSource() { 071 ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) lc.getLogger(Logger.ROOT_LOGGER_NAME); 072 073 DBAppender dbAppender = (DBAppender) root.getAppender("DB"); 074 assertNotNull(dbAppender); 075 return (DriverManagerConnectionSource) dbAppender.getConnectionSource(); 076 077 } 078 079 public void doTest(String configFile) throws JoranException, SQLException { 080 JoranConfigurator configurator = new JoranConfigurator(); 081 configurator.setContext(lc); 082 configurator.doConfigure(configFile); 083 084 Logger logger = lc.getLogger(DBAppenderIntegrationTest.class); 085 086 // the key userid is used in SiftingAppender test 087 // suffix with diff to avoid collision 088 MDC.put("userid" + diff, "user" + diff); 089 int runLength = 5; 090 for (int i = 1; i <= runLength; i++) { 091 logger.debug("This is a debug message. Message number: " + (diff + i)); 092 } 093 094 Exception e = new Exception("Just testing", getCause()); 095 logger.error("At last an error.", e); 096 097 StatusPrinter.printInCaseOfErrorsOrWarnings(lc); 098 099 long lastEventId = getLastEventId(); 100 verify(lastEventId); 101 102 // check that there were no errors 103 StatusChecker checker = new StatusChecker(lc); 104 checker.assertIsErrorFree(); 105 } 106 107 long getLastEventId() throws SQLException { 108 DriverManagerConnectionSource cs = getConnectionSource(); 109 110 Connection con = cs.getConnection(); 111 Statement statement = con.createStatement(); 112 statement.setMaxRows(1); 113 ResultSet rs = statement.executeQuery("select event_id from logging_event order by event_id desc"); 114 rs.next(); 115 long eventId = rs.getLong(1); 116 rs.close(); 117 statement.close(); 118 return eventId; 119 } 120 121 void verify(long lastEventId) throws SQLException { 122 verifyDebugMsg(lastEventId); 123 verifyException(lastEventId); 124 verifyProperty(lastEventId); 125 126 } 127 128 void verifyDebugMsg(long lastEventId) throws SQLException { 129 DriverManagerConnectionSource cs = getConnectionSource(); 130 Connection con = cs.getConnection(); 131 Statement statement = con.createStatement(); 132 ResultSet rs = statement.executeQuery("select formatted_message from logging_event where event_id='" + (lastEventId - 1) + "'"); 133 rs.next(); 134 String msg = rs.getString(1); 135 assertEquals("This is a debug message. Message number: " + (diff + 5), msg); 136 } 137 138 void verifyProperty(long lastEventId) throws SQLException { 139 DriverManagerConnectionSource cs = getConnectionSource(); 140 Connection con = cs.getConnection(); 141 Statement statement = con.createStatement(); 142 ResultSet rs = statement.executeQuery("select mapped_key, mapped_value from logging_event_property where event_id='" + (lastEventId - 1) + "'"); 143 144 Map<String, String> witness = lc.getCopyOfPropertyMap(); 145 witness.putAll(MDC.getCopyOfContextMap()); 146 147 Map<String, String> map = new HashMap<String, String>(); 148 while (rs.next()) { 149 String key = rs.getString(1); 150 String val = rs.getString(2); 151 map.put(key, val); 152 } 153 154 assertEquals(witness, map); 155 } 156 157 void verifyException(long lastEventId) throws SQLException { 158 DriverManagerConnectionSource cs = getConnectionSource(); 159 Connection con = cs.getConnection(); 160 Statement statement = con.createStatement(); 161 ResultSet rs = statement.executeQuery("select trace_line from logging_event_exception where event_id='" + (lastEventId) + "' AND I='0'"); 162 rs.next(); 163 String traceLine = rs.getString(1); 164 assertEquals("java.lang.Exception: Just testing", traceLine); 165 } 166 167 Throwable getCause() { 168 return new IllegalStateException("test cause"); 169 } 170 171 static boolean isConformingHostAndJDK16OrHigher(String[] conformingHostList) { 172 if (!EnvUtil.isJDK6OrHigher()) { 173 return false; 174 } 175 for (String conformingHost : conformingHostList) { 176 if (conformingHost.equalsIgnoreCase(LOCAL_HOST_NAME)) { 177 return true; 178 } 179 } 180 return false; 181 } 182 183 static boolean isConformingHostAndJDK16OrHigher() { 184 return isConformingHostAndJDK16OrHigher(CONFORMING_HOST_LIST); 185 } 186 187 @Test 188 public void sqlserver() throws Exception { 189 // perform test only on conforming hosts 190 if (!isConformingHostAndJDK16OrHigher()) { 191 return; 192 } 193 doTest("src/test/input/integration/db/sqlserver-with-driver.xml"); 194 } 195 196 @Test 197 public void oracle10g() throws Exception { 198 // perform test only on conforming hosts 199 if (!isConformingHostAndJDK16OrHigher(ORACLE_CONFORMING_HOST_LIST)) { 200 return; 201 } 202 doTest("src/test/input/integration/db/oracle10g-with-driver.xml"); 203 } 204 205 @Test 206 @Ignore 207 public void oracle11g() throws Exception { 208 // perform test only on conforming hosts 209 if (!isConformingHostAndJDK16OrHigher()) { 210 return; 211 } 212 doTest("src/test/input/integration/db/oracle11g-with-driver.xml"); 213 } 214 215 @Test 216 public void mysql() throws Exception { 217 // perform test only on conforming hosts 218 if (!isConformingHostAndJDK16OrHigher(MYSQL_CONFORMING_HOST_LIST)) { 219 return; 220 } 221 doTest("src/test/input/integration/db/mysql-with-driver.xml"); 222 } 223 224 @Test 225 public void postgres() throws Exception { 226 // perform test only on conforming hosts 227 if (!isConformingHostAndJDK16OrHigher(POSTGRES_CONFORMING_HOST_LIST)) { 228 return; 229 } 230 System.out.println("running postgres() test"); 231 doTest("src/test/input/integration/db/postgresql-with-driver.xml"); 232 } 233 234}