
org.elasticsearch.test.MockLogAppender Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of framework Show documentation
Show all versions of framework Show documentation
Elasticsearch subproject :test:framework
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.test;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractAppender;
import org.apache.logging.log4j.core.filter.RegexFilter;
import org.elasticsearch.common.regex.Regex;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* Test appender that can be used to verify that certain events were logged correctly
*/
public class MockLogAppender extends AbstractAppender {
private static final String COMMON_PREFIX = System.getProperty("es.logger.prefix", "org.elasticsearch.");
private List expectations;
public MockLogAppender() throws IllegalAccessException {
super("mock", RegexFilter.createFilter(".*(\n.*)*", new String[0], false, null, null), null, false);
/*
* We use a copy-on-write array list since log messages could be appended while we are setting up expectations. When that occurs,
* we would run into a concurrent modification exception from the iteration over the expectations in #append, concurrent with a
* modification from #addExpectation.
*/
expectations = new CopyOnWriteArrayList<>();
}
public void addExpectation(LoggingExpectation expectation) {
expectations.add(expectation);
}
@Override
public void append(LogEvent event) {
for (LoggingExpectation expectation : expectations) {
expectation.match(event);
}
}
public void assertAllExpectationsMatched() {
for (LoggingExpectation expectation : expectations) {
expectation.assertMatched();
}
}
public interface LoggingExpectation {
void match(LogEvent event);
void assertMatched();
}
public abstract static class AbstractEventExpectation implements LoggingExpectation {
protected final String name;
protected final String logger;
protected final Level level;
protected final String message;
volatile boolean saw;
public AbstractEventExpectation(String name, String logger, Level level, String message) {
this.name = name;
this.logger = getLoggerName(logger);
this.level = level;
this.message = message;
this.saw = false;
}
@Override
public void match(LogEvent event) {
if (event.getLevel().equals(level) && event.getLoggerName().equals(logger) && innerMatch(event)) {
if (Regex.isSimpleMatchPattern(message)) {
if (Regex.simpleMatch(message, event.getMessage().getFormattedMessage())) {
saw = true;
}
} else {
if (event.getMessage().getFormattedMessage().contains(message)) {
saw = true;
}
}
}
}
public boolean innerMatch(final LogEvent event) {
return true;
}
}
public static class UnseenEventExpectation extends AbstractEventExpectation {
public UnseenEventExpectation(String name, String logger, Level level, String message) {
super(name, logger, level, message);
}
@Override
public void assertMatched() {
assertThat("expected not to see " + name + " but did", saw, equalTo(false));
}
}
public static class SeenEventExpectation extends AbstractEventExpectation {
public SeenEventExpectation(String name, String logger, Level level, String message) {
super(name, logger, level, message);
}
@Override
public void assertMatched() {
assertThat("expected to see " + name + " but did not", saw, equalTo(true));
}
}
public static class EventuallySeenEventExpectation extends SeenEventExpectation {
private volatile boolean expectSeen = false;
public EventuallySeenEventExpectation(String name, String logger, Level level, String message) {
super(name, logger, level, message);
}
public void setExpectSeen() {
expectSeen = true;
}
@Override
public void assertMatched() {
if (expectSeen) {
super.assertMatched();
} else {
assertThat("expected not to see " + name + " yet but did", saw, equalTo(false));
}
}
}
public static class ExceptionSeenEventExpectation extends SeenEventExpectation {
private final Class extends Exception> clazz;
private final String exceptionMessage;
public ExceptionSeenEventExpectation(
final String name,
final String logger,
final Level level,
final String message,
final Class extends Exception> clazz,
final String exceptionMessage
) {
super(name, logger, level, message);
this.clazz = clazz;
this.exceptionMessage = exceptionMessage;
}
@Override
public boolean innerMatch(final LogEvent event) {
return event.getThrown() != null
&& event.getThrown().getClass() == clazz
&& event.getThrown().getMessage().equals(exceptionMessage);
}
}
public static class PatternSeenEventExpectation implements LoggingExpectation {
protected final String name;
protected final String logger;
protected final Level level;
protected final Pattern pattern;
volatile boolean saw;
public PatternSeenEventExpectation(String name, String logger, Level level, String pattern) {
this.name = name;
this.logger = logger;
this.level = level;
this.pattern = Pattern.compile(pattern);
}
@Override
public void match(LogEvent event) {
if (event.getLevel().equals(level) && event.getLoggerName().equals(logger)) {
if (pattern.matcher(event.getMessage().getFormattedMessage()).matches()) {
saw = true;
}
}
}
@Override
public void assertMatched() {
assertThat(name, saw, equalTo(true));
}
}
private static String getLoggerName(String name) {
if (name.startsWith("org.elasticsearch.")) {
name = name.substring("org.elasticsearch.".length());
}
return COMMON_PREFIX + name;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy