1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic.html;
15
16 import java.io.ByteArrayInputStream;
17 import java.util.List;
18
19 import org.dom4j.Document;
20 import org.dom4j.Element;
21 import org.dom4j.io.SAXReader;
22 import org.junit.jupiter.api.AfterEach;
23 import org.junit.jupiter.api.BeforeEach;
24 import org.junit.jupiter.api.Disabled;
25 import org.junit.jupiter.api.Test;
26 import org.xml.sax.EntityResolver;
27
28 import ch.qos.logback.classic.ClassicTestConstants;
29 import ch.qos.logback.classic.Level;
30 import ch.qos.logback.classic.Logger;
31 import ch.qos.logback.classic.LoggerContext;
32 import ch.qos.logback.classic.joran.JoranConfigurator;
33 import ch.qos.logback.classic.spi.PubThrowableProxy;
34 import ch.qos.logback.classic.spi.ILoggingEvent;
35 import ch.qos.logback.classic.spi.LoggingEvent;
36 import ch.qos.logback.classic.spi.StackTraceElementProxy;
37 import ch.qos.logback.classic.spi.ThrowableProxy;
38 import ch.qos.logback.core.CoreConstants;
39 import ch.qos.logback.core.joran.spi.JoranException;
40 import ch.qos.logback.core.testUtil.StringListAppender;
41 import ch.qos.logback.core.util.StatusPrinter;
42
43 import static org.junit.jupiter.api.Assertions.assertEquals;
44 import static org.junit.jupiter.api.Assertions.assertFalse;
45 import static org.junit.jupiter.api.Assertions.assertNotNull;
46 import static org.junit.jupiter.api.Assertions.assertTrue;
47
48 public class HTMLLayoutTest {
49
50 LoggerContext lc;
51 Logger root;
52 HTMLLayout layout;
53
54 @BeforeEach
55 public void setUp() throws Exception {
56 lc = new LoggerContext();
57 lc.setName("default");
58
59 layout = new HTMLLayout();
60 layout.setThrowableRenderer(new DefaultThrowableRenderer());
61 layout.setContext(lc);
62 layout.setPattern("%level%thread%msg");
63 layout.start();
64
65 root = lc.getLogger(Logger.ROOT_LOGGER_NAME);
66
67 }
68
69 @AfterEach
70 public void tearDown() throws Exception {
71 lc = null;
72 layout = null;
73 }
74
75 @Test
76 public void testHeader() throws Exception {
77 String header = layout.getFileHeader();
78
79
80 Document doc = parseOutput(header + "</body></html>");
81 Element rootElement = doc.getRootElement();
82 assertNotNull(rootElement.element("body"));
83
84 }
85
86 @Test
87 public void testPresentationHeader() throws Exception {
88 String header = layout.getFileHeader();
89 String presentationHeader = layout.getPresentationHeader();
90 header = header + presentationHeader;
91
92
93 Document doc = parseOutput(header + "</table></body></html>");
94 Element rootElement = doc.getRootElement();
95 Element bodyElement = rootElement.element("body");
96 Element tableElement = bodyElement.element("table");
97 Element trElement = tableElement.element("tr");
98 List<Element> elementList = trElement.elements();
99 assertEquals("Level", elementList.get(0).getText());
100 assertEquals("Thread", elementList.get(1).getText());
101 assertEquals("Message", elementList.get(2).getText());
102 }
103
104 @Test
105 public void testAppendThrowable() throws Exception {
106 StringBuilder buf = new StringBuilder();
107 PubThrowableProxy tp = new PubThrowableProxy();
108 tp.setClassName("test1");
109 tp.setMessage("msg1");
110
111 StackTraceElement ste1 = new StackTraceElement("c1", "m1", "f1", 1);
112 StackTraceElement ste2 = new StackTraceElement("c2", "m2", "f2", 2);
113
114 StackTraceElementProxy[] stepArray = { new StackTraceElementProxy(ste1), new StackTraceElementProxy(ste2) };
115 tp.setStackTraceElementProxyArray(stepArray);
116 DefaultThrowableRenderer renderer = (DefaultThrowableRenderer) layout.getThrowableRenderer();
117
118 renderer.render(buf, tp);
119 System.out.println(buf.toString());
120 String[] result = buf.toString().split(CoreConstants.LINE_SEPARATOR);
121 System.out.println(result[0]);
122 assertEquals("test1: msg1", result[0]);
123 assertEquals(DefaultThrowableRenderer.TRACE_PREFIX + "at c1.m1(f1:1)", result[1]);
124 }
125
126 @Test
127 public void testDoLayout() throws Exception {
128 ILoggingEvent le = createLoggingEvent();
129
130 String result = layout.getFileHeader();
131 result += layout.getPresentationHeader();
132 result += layout.doLayout(le);
133 result += layout.getPresentationFooter();
134 result += layout.getFileFooter();
135
136 Document doc = parseOutput(result);
137 Element rootElement = doc.getRootElement();
138 rootElement.toString();
139
140
141
142
143
144
145
146
147 assertEquals(2, rootElement.elements().size());
148 Element bodyElement = (Element) rootElement.elements().get(1);
149 Element tableElement = (Element) bodyElement.elements().get(3);
150 assertEquals("table", tableElement.getName());
151 Element trElement = (Element) tableElement.elements().get(1);
152 {
153 Element tdElement = (Element) trElement.elements().get(0);
154 assertEquals("DEBUG", tdElement.getText());
155 }
156 {
157 Element tdElement = (Element) trElement.elements().get(1);
158 String regex = ClassicTestConstants.NAKED_MAIN_REGEX;
159 System.out.println(tdElement.getText());
160 assertTrue(tdElement.getText().matches(regex));
161 }
162 {
163 Element tdElement = (Element) trElement.elements().get(2);
164 assertEquals("test message", tdElement.getText());
165 }
166 }
167
168 @Test
169 public void layoutWithException() throws Exception {
170 layout.setPattern("%level %thread %msg %ex");
171 LoggingEvent le = createLoggingEvent();
172 le.setThrowableProxy(new ThrowableProxy(new Exception("test Exception")));
173 String result = layout.doLayout(le);
174
175 String stringToParse = layout.getFileHeader();
176 stringToParse = stringToParse + layout.getPresentationHeader();
177 stringToParse += result;
178 stringToParse += "</table></body></html>";
179
180
181
182 Document doc = parseOutput(stringToParse);
183 Element rootElement = doc.getRootElement();
184 Element bodyElement = rootElement.element("body");
185 Element tableElement = bodyElement.element("table");
186 List<Element> trElementList = tableElement.elements();
187 Element exceptionRowElement = trElementList.get(2);
188 Element exceptionElement = exceptionRowElement.element("td");
189
190 assertEquals(3, tableElement.elements().size());
191 assertTrue(exceptionElement.getText().contains("java.lang.Exception: test Exception"));
192 }
193
194 @Test
195 @Disabled
196 public void rawLimit() throws Exception {
197 StringBuilder sb = new StringBuilder();
198 String header = layout.getFileHeader();
199 assertTrue(header.startsWith(
200 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"));
201 sb.append(header);
202 sb.append(layout.getPresentationHeader());
203 for (int i = 0; i < CoreConstants.TABLE_ROW_LIMIT * 3; i++) {
204 sb.append(layout.doLayout(
205 new LoggingEvent(this.getClass().getName(), root, Level.DEBUG, "test message" + i, null, null)));
206 }
207 sb.append(layout.getPresentationFooter());
208 sb.append(layout.getFileFooter());
209
210 parseOutput(sb.toString());
211 }
212
213 private LoggingEvent createLoggingEvent() {
214 return new LoggingEvent(this.getClass().getName(), root, Level.DEBUG, "test message", null, null);
215 }
216
217 Document parseOutput(String output) throws Exception {
218 EntityResolver resolver = new XHTMLEntityResolver();
219 SAXReader reader = new SAXReader();
220 reader.setValidation(true);
221 reader.setEntityResolver(resolver);
222 return reader.read(new ByteArrayInputStream(output.getBytes()));
223 }
224
225 void configure(String file) throws JoranException {
226 JoranConfigurator jc = new JoranConfigurator();
227 jc.setContext(lc);
228 jc.doConfigure(file);
229 }
230
231 @Test
232 public void testConversionRuleSupportInHtmlLayout() throws JoranException {
233 configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "conversionRule/htmlLayout0.xml");
234
235 root.getAppender("LIST");
236 String msg = "Simon says";
237 root.debug(msg);
238 StringListAppender<ILoggingEvent> sla = (StringListAppender<ILoggingEvent>) root.getAppender("LIST");
239 assertNotNull(sla);
240 StatusPrinter.print(lc);
241 assertEquals(1, sla.strList.size());
242 assertFalse(sla.strList.get(0).contains("PARSER_ERROR"));
243 }
244 }