001// Generated by delombok at Fri Mar 03 17:40:07 UTC 2023
002package de.cuioss.test.juli;
003
004import static de.cuioss.tools.string.MoreStrings.isEmpty;
005import static org.junit.jupiter.api.Assertions.assertFalse;
006import static org.junit.jupiter.api.Assertions.assertNotNull;
007import java.util.ArrayList;
008import java.util.Collections;
009import java.util.Comparator;
010import java.util.List;
011import java.util.logging.Handler;
012import java.util.logging.LogRecord;
013import java.util.stream.Collectors;
014
015/**
016 * Handler for storing and querying {@link LogRecord}s
017 *
018 * @author Oliver Wolff
019 */
020public class TestLogHandler extends Handler {
021    private static final String TEST_LOG_LEVEL_MUST_NOT_BE_NULL = "TestLogLevel must not be null";
022    private static final String LOGGER_MUST_NOT_BE_NULL = "Logger must not be null";
023    private static final String MESSAGE_MUST_NOT_BE_NULL = "Message must not be null";
024    private static final String THROWABLE_CLASS_MUST_NOT_BE_NULL = "ThrowableClass must not be null";
025    private static final String THROWABLE_MUST_NOT_BE_NULL = "Throwable must not be null";
026    private final List<LogRecord> records = Collections.synchronizedList(new ArrayList<>());
027
028    @Override
029    public void publish(LogRecord logRecord) {
030        // Silently ignore null records.
031        if (logRecord == null) {
032            return;
033        }
034        records.add(logRecord);
035    }
036
037    @Override
038    public void close() {
039        // There is no need to close
040    }
041
042    @Override
043    public void flush() {
044        // There is no need to flush
045    }
046
047    /**
048     * @param level to be checked for message, must not be null
049     * @param message to be checked, must not be null
050     * @param throwableClass to be checked, must not be null
051     * @return a {@link List} of found {@link LogRecord}s
052     */
053    public List<LogRecord> resolveLogMessages(TestLogLevel level, String message, Class<? extends Throwable> throwableClass) {
054        assertNotNull(throwableClass, THROWABLE_CLASS_MUST_NOT_BE_NULL);
055        return resolveLogMessages(level, message).stream().filter(r -> logRecordContains(r, throwableClass)).collect(Collectors.toList());
056    }
057
058    /**
059     * @param level to be checked for message, must not be null
060     * @param message to be checked, must not be null
061     * @param throwable to be checked, must not be null
062     * @return a {@link List} of found {@link LogRecord}s
063     */
064    public List<LogRecord> resolveLogMessages(TestLogLevel level, String message, Throwable throwable) {
065        assertNotNull(throwable, THROWABLE_MUST_NOT_BE_NULL);
066        return resolveLogMessages(level, message).stream().filter(r -> logRecordContains(r, throwable)).collect(Collectors.toList());
067    }
068
069    /**
070     * @param level to be checked for message, must not be null
071     * @param message to be checked, must not be null
072     * @return a {@link List} of found {@link LogRecord}s
073     */
074    public List<LogRecord> resolveLogMessages(TestLogLevel level, String message) {
075        assertNotNull(message, MESSAGE_MUST_NOT_BE_NULL);
076        return resolveLogMessages(level).stream().filter(r -> message.equals(r.getMessage())).collect(Collectors.toList());
077    }
078
079    /**
080     * @param logger to be checked, must not be null
081     * @return a {@link List} of found {@link LogRecord}s
082     */
083    public List<LogRecord> resolveLogMessagesForLogger(String logger) {
084        assertFalse(isEmpty(logger), LOGGER_MUST_NOT_BE_NULL);
085        return records.stream().filter(r -> logger.equalsIgnoreCase(r.getLoggerName())).collect(Collectors.toList());
086    }
087
088    /**
089     * @param level to be checked for message, must not be null
090     * @param logger to be checked, must not be null
091     * @return a {@link List} of found {@link LogRecord}s
092     */
093    public List<LogRecord> resolveLogMessagesForLogger(TestLogLevel level, String logger) {
094        assertNotNull(level, TEST_LOG_LEVEL_MUST_NOT_BE_NULL);
095        return resolveLogMessagesForLogger(logger).stream().filter(r -> level.getJuliLevel().equals(r.getLevel())).collect(Collectors.toList());
096    }
097
098    /**
099     * @param level to be checked for message, must not be null
100     * @param logger to be checked, must not be null
101     * @return a {@link List} of found {@link LogRecord}s
102     */
103    public List<LogRecord> resolveLogMessagesForLogger(TestLogLevel level, Class<?> logger) {
104        assertNotNull(level, TEST_LOG_LEVEL_MUST_NOT_BE_NULL);
105        assertNotNull(logger, LOGGER_MUST_NOT_BE_NULL);
106        return resolveLogMessagesForLogger(level, logger.getName());
107    }
108
109    /**
110     * @param logger to be checked, must not be null
111     * @return a {@link List} of found {@link LogRecord}s
112     */
113    public List<LogRecord> resolveLogMessagesForLogger(Class<?> logger) {
114        assertNotNull(logger, LOGGER_MUST_NOT_BE_NULL);
115        return resolveLogMessagesForLogger(logger.getName());
116    }
117
118    /**
119     * @param level to be checked for message, must not be null
120     * @param messagePart to be checked, must not be null. Compared to
121     *            {@link TestLogHandler#resolveLogMessages(TestLogLevel, String)} this method check
122     *            whether the given text is contained within a {@link LogRecord}
123     * @return a {@link List} of found {@link LogRecord}s
124     */
125    public List<LogRecord> resolveLogMessagesContaining(TestLogLevel level, String messagePart) {
126        assertNotNull(messagePart, MESSAGE_MUST_NOT_BE_NULL);
127        return resolveLogMessages(level).stream().filter(r -> logRecordContains(r, messagePart)).collect(Collectors.toList());
128    }
129
130    /**
131     * @param level to be checked for message, must not be null
132     * @param messagePart to be checked, must not be null. Compared to
133     *            {@link TestLogHandler#resolveLogMessages(TestLogLevel, String)} this method check
134     *            whether the given text is contained within a {@link LogRecord}
135     * @param throwable to be looked for
136     * @return a {@link List} of found {@link LogRecord}s
137     */
138    public List<LogRecord> resolveLogMessagesContaining(TestLogLevel level, String messagePart, Throwable throwable) {
139        assertNotNull(throwable, THROWABLE_MUST_NOT_BE_NULL);
140        return resolveLogMessagesContaining(level, messagePart).stream().filter(r -> logRecordContains(r, throwable)).collect(Collectors.toList());
141    }
142
143    /**
144     * @param level to be checked for message, must not be null
145     * @param messagePart to be checked, must not be null. Compared to
146     *            {@link TestLogHandler#resolveLogMessages(TestLogLevel, String)} this method check
147     *            whether the given text is contained within a {@link LogRecord}
148     * @param throwableClass to be looked for
149     * @return a {@link List} of found {@link LogRecord}s
150     */
151    public List<LogRecord> resolveLogMessagesContaining(TestLogLevel level, String messagePart, Class<? extends Throwable> throwableClass) {
152        assertNotNull(throwableClass, THROWABLE_CLASS_MUST_NOT_BE_NULL);
153        return resolveLogMessagesContaining(level, messagePart).stream().filter(r -> logRecordContains(r, throwableClass)).collect(Collectors.toList());
154    }
155
156    /**
157     * @param level to be checked for message, must not be null
158     * @return a {@link List} of found {@link LogRecord}s
159     */
160    public List<LogRecord> resolveLogMessages(TestLogLevel level) {
161        assertNotNull(level, TEST_LOG_LEVEL_MUST_NOT_BE_NULL);
162        synchronized (records) {
163            return records.stream().filter(r -> logRecordContains(r, level)).collect(Collectors.toList());
164        }
165    }
166
167    /**
168     * Clears the contained records
169     */
170    public void clearRecords() {
171        records.clear();
172    }
173
174    private static boolean logRecordContains(LogRecord logRecord, String messagePart) {
175        final var msg = logRecord.getMessage();
176        return null != msg && msg.contains(messagePart);
177    }
178
179    private static boolean logRecordContains(LogRecord logRecord, Class<? extends Throwable> throwableClass) {
180        var thrown = logRecord.getThrown();
181        return null != thrown && thrown.getClass().equals(throwableClass);
182    }
183
184    private static boolean logRecordContains(LogRecord logRecord, Throwable throwable) {
185        var thrown = logRecord.getThrown();
186        return null != thrown && thrown.equals(throwable);
187    }
188
189    private static boolean logRecordContains(LogRecord logRecord, TestLogLevel level) {
190        var loggedLevel = logRecord.getLevel();
191        return null != loggedLevel && loggedLevel.equals(level.getJuliLevel());
192    }
193
194    @Override
195    public String toString() {
196        return getClass().getName() + " with " + getRecords().size() + " entries";
197    }
198
199    /**
200     * @return String representation of the records within this handler.
201     */
202    public String getRecordsAsString() {
203        if (records.isEmpty()) {
204            return "No log messages available";
205        }
206        List<LogRecord> all = new ArrayList<>(records);
207        all.sort(Comparator.comparing(l -> l.getLevel().intValue()));
208        List<String> elements = new ArrayList<>();
209        all.forEach(l -> elements.add(TestLogLevel.parse(l.getLevel()) + ": " + l.getLoggerName() + "-" + l.getMessage()));
210        var builder = new StringBuilder();
211        builder.append("Available Messages:");
212        for (String element : elements) {
213            builder.append("\n").append(element);
214        }
215        return builder.toString();
216    }
217
218    @java.lang.SuppressWarnings("all")
219    @lombok.Generated
220    public List<LogRecord> getRecords() {
221        return this.records;
222    }
223}