Skip to content

Commit

Permalink
finished support for retrieving log messages by request
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesdbloom committed Dec 11, 2017
1 parent da2b2a3 commit d03a88a
Show file tree
Hide file tree
Showing 19 changed files with 590 additions and 246 deletions.
82 changes: 48 additions & 34 deletions mockserver-core/src/main/java/org/mockserver/filters/LogFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.EvictingQueue;
import com.google.common.collect.Lists;
import com.google.common.collect.Queues;
import org.mockserver.client.serialization.HttpRequestSerializer;
import org.mockserver.log.model.*;
Expand All @@ -18,38 +17,63 @@
import java.util.*;

import static org.mockserver.character.Character.NEW_LINE;
import static org.mockserver.model.HttpRequest.request;

/**
* @author jamesdbloom
*/
public class LogFilter {

public final static List<Class<? extends LogEntry>> REQUEST_LOG_TYPES = Arrays.asList(
private final static List<Class<? extends LogEntry>> MESSAGE_LOG_TYPES = Collections.<Class<? extends LogEntry>>singletonList(
MessageLogEntry.class
);
private final static List<Class<? extends LogEntry>> REQUEST_LOG_TYPES = Arrays.asList(
RequestLogEntry.class,
RequestResponseLogEntry.class,
ExpectationMatchLogEntry.class
);
public final static List<Class<? extends LogEntry>> EXPECTATION_LOG_TYPES = Arrays.<Class<? extends LogEntry>>asList(
private final static List<Class<? extends LogEntry>> EXPECTATION_LOG_TYPES = Arrays.<Class<? extends LogEntry>>asList(
RequestResponseLogEntry.class,
ExpectationMatchLogEntry.class
);
private final LoggingFormatter logFormatter;
private Queue<LogEntry> requestLog = Queues.synchronizedQueue(EvictingQueue.<LogEntry>create(100));
private MatcherBuilder matcherBuilder;
private HttpRequestSerializer httpRequestSerializer = new HttpRequestSerializer();

private Function<LogEntry, HttpRequest> logEntryToHttpRequestFunction = new Function<LogEntry, HttpRequest>() {
static Predicate<LogEntry> messageLogPredicate = new Predicate<LogEntry>() {
public boolean apply(LogEntry input) {
return MESSAGE_LOG_TYPES.contains(input.getClass());
}
};
private static Function<LogEntry, HttpRequest> logEntryToRequest = new Function<LogEntry, HttpRequest>() {
public HttpRequest apply(LogEntry logEntry) {
return logEntry.getHttpRequest();
}
};

private Predicate<LogEntry> notMessageLogEntryPredicate = new Predicate<LogEntry>() {
static Predicate<LogEntry> requestLogPredicate = new Predicate<LogEntry>() {
public boolean apply(LogEntry input) {
return REQUEST_LOG_TYPES.contains(input.getClass());
}
};
private static Function<LogEntry, Expectation> logEntryToExpectation = new Function<LogEntry, Expectation>() {
public Expectation apply(LogEntry logEntry) {
return ((ExpectationLogEntry) logEntry).getExpectation();
}
};
static Predicate<LogEntry> expectationLogPredicate = new Predicate<LogEntry>() {
public boolean apply(LogEntry input) {
return EXPECTATION_LOG_TYPES.contains(input.getClass());
}
};
public static Predicate<LogEntry> notMessageLogEntryPredicate = new Predicate<LogEntry>() {
public boolean apply(LogEntry logEntry) {
return !(logEntry instanceof MessageLogEntry);
}
};
private final LoggingFormatter logFormatter;
private Queue<LogEntry> requestLog = Queues.synchronizedQueue(EvictingQueue.<LogEntry>create(100));
private MatcherBuilder matcherBuilder;
private HttpRequestSerializer httpRequestSerializer = new HttpRequestSerializer();
private Function<LogEntry, String> logEntryToMessage = new Function<LogEntry, String>() {
public String apply(LogEntry logEntry) {
return ((MessageLogEntry) logEntry).getMessage();
}
};

public LogFilter(LoggingFormatter logFormatter) {
this.logFormatter = logFormatter;
Expand Down Expand Up @@ -77,34 +101,24 @@ public void clear(HttpRequest request) {
}
}

public List<HttpRequest> retrieveRequests(HttpRequest httpRequest) {
return Lists.transform(
retrieveLogEntries(httpRequest, REQUEST_LOG_TYPES),
logEntryToHttpRequestFunction
);
public List<String> retrieveMessages(HttpRequest httpRequest) {
return retrieveLogEntries(httpRequest, messageLogPredicate, logEntryToMessage);
}

public List<Expectation> retrieveExpectations(HttpRequest httpRequest) {
List<Expectation> matchingExpectations = new ArrayList<>();
List<LogEntry> logEntries = retrieveLogEntries(httpRequest, EXPECTATION_LOG_TYPES);
for (LogEntry logEntry : logEntries) {
matchingExpectations.add(((ExpectationLogEntry) logEntry).getExpectation());
}
return matchingExpectations;
public List<HttpRequest> retrieveRequests(HttpRequest httpRequest) {
return retrieveLogEntries(httpRequest, requestLogPredicate, logEntryToRequest);
}

public List<LogEntry> retrieveLogEntries(HttpRequest httpRequest) {
return retrieveLogEntries(httpRequest, Collections.<Class<? extends LogEntry>>emptyList());
public List<Expectation> retrieveExpectations(HttpRequest httpRequest) {
return retrieveLogEntries(httpRequest, expectationLogPredicate, logEntryToExpectation);
}

public List<LogEntry> retrieveLogEntries(HttpRequest httpRequest, List<Class<? extends LogEntry>> types) {
List<LogEntry> requestLog = new LinkedList<>(this.requestLog);

List<LogEntry> matchingLogEntries = new ArrayList<>();
<T> List<T> retrieveLogEntries(HttpRequest httpRequest, Predicate<LogEntry> logEntryPredicate, Function<LogEntry, T> logEntryToTypeFunction) {
List<T> matchingLogEntries = new ArrayList<>();
HttpRequestMatcher httpRequestMatcher = matcherBuilder.transformsToMatcher(httpRequest);
for (LogEntry logEntry : requestLog) {
if ((types.isEmpty() || types.contains(logEntry.getClass())) && httpRequestMatcher.matches(logEntry.getHttpRequest(), true)) {
matchingLogEntries.add(logEntry);
for (LogEntry logEntry : new LinkedList<>(this.requestLog)) {
if (logEntryPredicate.apply(logEntry) && httpRequestMatcher.matches(logEntry.getHttpRequest(), false)) {
matchingLogEntries.add(logEntryToTypeFunction.apply(logEntry));
}
}
return matchingLogEntries;
Expand Down Expand Up @@ -155,7 +169,7 @@ public String verify(VerificationSequence verificationSequence) {
boolean foundRequest = false;
for (; !foundRequest && requestLogCounter < requestLog.size(); requestLogCounter++) {
LogEntry logEntry = requestLog.get(requestLogCounter);
if (!(logEntry instanceof MessageLogEntry) && httpRequestMatcher.matches(logEntry.getHttpRequest(), true)) {
if (!(logEntry instanceof MessageLogEntry) && httpRequestMatcher.matches(logEntry.getHttpRequest(), false)) {
// move on to next request
foundRequest = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public static String[] indentAndToString(Object... objects) {
public static String formatLogMessage(String message, Object... arguments) {
StringBuilder errorMessage = new StringBuilder();
Object[] formattedArguments = indentAndToString(arguments);
String[] messageParts = (message + NEW_LINE).split("\\{\\}");
String[] messageParts = message.split("\\{\\}");
for (int messagePartIndex = 0; messagePartIndex < messageParts.length; messagePartIndex++) {
errorMessage.append(messageParts[messagePartIndex]);
if (formattedArguments.length > messagePartIndex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@ public LoggingFormatter(Logger logger, HttpStateHandler httpStateHandler) {

public void traceLog(String message, Object... arguments) {
if (logger.isTraceEnabled()) {
logger.trace(formatLogMessage(message + NEW_LINE + NEW_LINE, arguments));
logger.trace(formatLogMessage(message, arguments));
}
}

public void infoLog(HttpRequest request, String message, Object... arguments) {
String logMessage = formatLogMessage(message + NEW_LINE, arguments);
String logMessage = formatLogMessage(message, arguments);
logger.info(logMessage);
addLogEvents(request, logMessage);
}

public void infoLog(List<HttpRequest> requests, String message, Object... arguments) {
String logMessage = formatLogMessage(message + NEW_LINE, arguments);
String logMessage = formatLogMessage(message, arguments);
logger.info(logMessage);
addLogEvents(requests, logMessage);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private void withSsl(Boolean isSsl) {
}

public boolean matches(HttpRequest request) {
return matches(request, false);
return matches(request, true);
}

public boolean matches(HttpRequest request, boolean logMatchResults) {
Expand Down Expand Up @@ -200,25 +200,25 @@ public boolean matches(HttpRequest request, boolean logMatchResults) {
boolean totalResult = methodMatches && pathMatches && queryStringParametersMatches && bodyMatches && headersMatch && cookiesMatch && keepAliveMatches && sslMatches;
boolean totalResultAfterNotOperatorApplied = request.isNot() == (this.httpRequest.isNot() == (not != totalResult));

if (logMatchResults && logger.isInfoEnabled()) {
if (logMatchResults) {
if (!totalResultAfterNotOperatorApplied) {
StringBuilder becauseBuilder = new StringBuilder();
becauseBuilder.append("method matches = ").append(methodMatches).append(NEW_LINE);
becauseBuilder.append("path matches = ").append(pathMatches).append(NEW_LINE);
becauseBuilder.append("query string parameters match = ").append(queryStringParametersMatches).append(NEW_LINE);
becauseBuilder.append("body matches = ").append(bodyMatches).append(NEW_LINE);
becauseBuilder.append("headers match = ").append(headersMatch).append(NEW_LINE);
becauseBuilder.append("cookies match = ").append(cookiesMatch).append(NEW_LINE);
becauseBuilder.append("keep-alive matches = ").append(keepAliveMatches).append(NEW_LINE);
becauseBuilder.append("ssl matches = ").append(sslMatches).append(NEW_LINE);
becauseBuilder.append("method matches = ").append(methodMatches);
becauseBuilder.append(NEW_LINE).append("path matches = ").append(pathMatches);
becauseBuilder.append(NEW_LINE).append("query string parameters match = ").append(queryStringParametersMatches);
becauseBuilder.append(NEW_LINE).append("body matches = ").append(bodyMatches);
becauseBuilder.append(NEW_LINE).append("headers match = ").append(headersMatch);
becauseBuilder.append(NEW_LINE).append("cookies match = ").append(cookiesMatch);
becauseBuilder.append(NEW_LINE).append("keep-alive matches = ").append(keepAliveMatches);
becauseBuilder.append(NEW_LINE).append("ssl matches = ").append(sslMatches);
if (request.isNot()) {
becauseBuilder.append("request \'not\' operator is enabled").append(NEW_LINE);
becauseBuilder.append(NEW_LINE).append("request \'not\' operator is enabled");
}
if (this.httpRequest.isNot()) {
becauseBuilder.append("expectation's request \'not\' operator is enabled").append(NEW_LINE);
becauseBuilder.append(NEW_LINE).append("expectation's request \'not\' operator is enabled");
}
if (not) {
becauseBuilder.append("expectation's request matcher \'not\' operator is enabled").append(NEW_LINE);
becauseBuilder.append(NEW_LINE).append("expectation's request matcher \'not\' operator is enabled");
}
logFormatter.infoLog(request, "request:{}" + NEW_LINE + " did" + (totalResult ? "" : " not") + " match expectation:{}" + NEW_LINE + " because:{}", request, this, becauseBuilder.toString());
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.mockserver.mock;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.mockserver.matchers.TimeToLive;
import org.mockserver.matchers.Times;
import org.mockserver.model.*;
Expand Down Expand Up @@ -267,6 +268,7 @@ public Expectation thenCallback(HttpObjectCallback httpObjectCallback) {
return this;
}

@JsonIgnore
public boolean isActive() {
return hasRemainingMatches() && isStillAlive();
}
Expand Down
Loading

0 comments on commit d03a88a

Please sign in to comment.