View Javadoc
1   package emissary.test.core.junit5;
2   
3   import ch.qos.logback.classic.Level;
4   import ch.qos.logback.classic.Logger;
5   import ch.qos.logback.classic.spi.ILoggingEvent;
6   import ch.qos.logback.classic.spi.IThrowableProxy;
7   import ch.qos.logback.core.read.ListAppender;
8   import org.apache.commons.lang3.Validate;
9   import org.slf4j.LoggerFactory;
10  
11  import java.io.Closeable;
12  import java.io.IOException;
13  import java.util.ArrayList;
14  import java.util.List;
15  import java.util.Objects;
16  import javax.annotation.Nullable;
17  
18  import static org.junit.jupiter.api.Assertions.assertEquals;
19  import static org.junit.jupiter.api.Assertions.assertNotNull;
20  import static org.junit.jupiter.api.Assertions.assertNull;
21  
22  public class LogbackTester implements Closeable {
23      public final String name;
24      public final Logger logger;
25      public final ListAppender<ILoggingEvent> appender;
26  
27      public LogbackTester(final String name) {
28          Validate.notNull(name, "Required: name != null");
29  
30          this.name = name;
31          logger = (Logger) LoggerFactory.getLogger(name);
32          appender = new ListAppender<>();
33  
34          appender.setContext(logger.getLoggerContext());
35          appender.start();
36          logger.addAppender(appender);
37          logger.setAdditive(false);
38      }
39  
40      public void checkLogList(List<SimplifiedLogEvent> events) {
41          Validate.notNull(events, "Required: events != null");
42  
43          assertEquals(events.size(), appender.list.size(), "Expected event count does not match actual event count");
44  
45          for (int i = 0; i < appender.list.size(); i++) {
46              final ILoggingEvent item = appender.list.get(i);
47              final SimplifiedLogEvent event = events.get(i);
48              assertEquals(event.level, item.getLevel(), "Levels not equal for element " + i);
49              assertEquals(event.message, item.getFormattedMessage(), "Messages not equal for element " + i);
50              if (event.throwableClassName == null) {
51                  assertNull(item.getThrowableProxy(), "Expected no exception for element " + i);
52              } else {
53                  assertNotNull(item.getThrowableProxy(), "Expected an exception for element " + i);
54                  IThrowableProxy proxy = item.getThrowableProxy();
55                  assertEquals(event.throwableClassName, proxy.getClassName(), "Exception class name not equal for element " + i);
56                  assertEquals(event.throwableMessage, proxy.getMessage(), "Exception message not equal for element " + i);
57              }
58          }
59      }
60  
61      public List<SimplifiedLogEvent> getSimplifiedLogEvents() {
62          final List<SimplifiedLogEvent> simplifiedLogEvents = new ArrayList<>();
63  
64          for (int i = 0; i < appender.list.size(); i++) {
65              final ILoggingEvent event = appender.list.get(i);
66  
67              if (event.getThrowableProxy() == null) {
68                  simplifiedLogEvents.add(new SimplifiedLogEvent(event.getLevel(), event.getFormattedMessage(),
69                          null, null));
70              } else {
71                  simplifiedLogEvents.add(new SimplifiedLogEvent(event.getLevel(), event.getFormattedMessage(),
72                          event.getThrowableProxy().getClassName(), event.getThrowableProxy().getMessage()));
73              }
74          }
75  
76          return simplifiedLogEvents;
77      }
78  
79      @Override
80      public void close() throws IOException {
81          logger.detachAndStopAllAppenders();
82      }
83  
84      public static class SimplifiedLogEvent {
85          public final Level level;
86          public final String message;
87          @Nullable
88          public final String throwableClassName;
89          @Nullable
90          public final String throwableMessage;
91  
92          public SimplifiedLogEvent(Level level, String message, @Nullable Throwable throwable) {
93              this(level, message,
94                      throwable == null ? null : throwable.getClass().getName(),
95                      throwable == null ? null : throwable.getLocalizedMessage());
96          }
97  
98          public SimplifiedLogEvent(Level level, String message, @Nullable String throwableClassName, @Nullable String throwableMessage) {
99              Validate.notNull(level, "Required: level != null!");
100             Validate.notNull(message, "Required: message != null!");
101 
102             this.level = level;
103             this.message = message;
104             this.throwableClassName = throwableClassName;
105             this.throwableMessage = throwableMessage;
106         }
107 
108         @Override
109         public int hashCode() {
110             return Objects.hash(level, message, throwableClassName, throwableMessage);
111         }
112 
113         @Override
114         public boolean equals(Object obj) {
115             if (this == obj) {
116                 return true;
117             }
118 
119             if (!(obj instanceof SimplifiedLogEvent)) {
120                 return false;
121             }
122             SimplifiedLogEvent other = (SimplifiedLogEvent) obj;
123 
124             return Objects.equals(level, other.level) &&
125                     Objects.equals(message, other.message) &&
126                     Objects.equals(throwableClassName, other.throwableClassName) &&
127                     Objects.equals(throwableMessage, other.throwableMessage);
128         }
129 
130         @Override
131         public String toString() {
132             return super.toString() + " [level=" + level + ", message=" + message + ", throwableClassName="
133                     + throwableClassName + ", throwableMessage=" + throwableMessage + "]";
134         }
135     }
136 }