Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4.0.0 #20

Merged
merged 9 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/run-with-maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ jobs:
restore-keys: |
${{ runner.os }}-maven-

- name: Set up JDK 8
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '8'
java-version: '17'
distribution: 'adopt'
cache: maven

Expand Down
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ logCapture.assertLoggedInOrder(
* [MDC content](#mdc-content)
* [Exceptions](#exceptions)
* [Markers](#markers)
* [Key-Value](#key-value)
* [Logger name](#logger-name)
* [Examples](#examples)
* [Unit Test Example:](#unit-test-example)
Expand All @@ -49,6 +50,7 @@ logCapture.assertLoggedInOrder(
* [Cucumber example](#cucumber-example)
* [Cucumber feature file](#cucumber-feature-file)
* [Changes](#changes)
* [4.0.0](#400)
* [3.6.2](#362)
* [3.6.1](#361)
* [3.6.0](#360)
Expand All @@ -74,7 +76,7 @@ Add log-capture as a test dependency to your project. If you use Maven, add this
<dependency>
<groupId>de.dm.infrastructure</groupId>
<artifactId>log-capture</artifactId>
<version>3.6.2</version>
<version>4.0.0</version>
<scope>test</scope>
</dependency>
```
Expand Down Expand Up @@ -131,6 +133,18 @@ log.info(MarkerFactory.getMarker("my-marker"), "hello with marker");
logCapture.assertLogged(info("hello with marker", marker("my-marker")));
```

#### Key-Value

```java
import static de.dm.infrastructure.logcapture.ExpectedKeyValue.keyValue;

...

log.atInfo().setMessage("hello").addKeyValue("meaning", 42).log();

logCapture.assertLogged(info("hello", keyValue("meaning", 42)))
```

#### Logger name

```java
Expand Down Expand Up @@ -310,6 +324,13 @@ And with MDC logging context

## Changes

### 4.0.0

* **breaking change:** log-capture now requires Java 17
* **breaking change:** all deprecated parts have been removed
* added a new log event matcher [for key-value content](#key-value)
* lots of dependency updates

### 3.6.2

* Fixed an assertion message concerning captured Exceptions.
Expand Down
49 changes: 23 additions & 26 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,27 +29,26 @@
</developers>

<properties>
<project.version>3.6.2-SNAPSHOT</project.version>
<project.version>4.0.0-SNAPSHOT</project.version>

<java.version>1.8</java.version>
<lombok.version>1.18.22</lombok.version>
<logback.version>1.2.11</logback.version>
<junit.version>5.8.2</junit.version>
<java.version>17</java.version>
<lombok.version>1.18.30</lombok.version>
<logback.version>1.4.11</logback.version>
<junit.version>5.10.1</junit.version>
<encoding>UTF-8</encoding>

<archunit.version>0.23.1</archunit.version>
<assertj-core.version>3.22.0</assertj-core.version>
<checkstyle.version>8.45.1</checkstyle.version>
<jacoco.version>0.8.7</jacoco.version>
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
<maven-checkstyle-plugin.version>3.1.1</maven-checkstyle-plugin.version>
<maven-source-plugin.version>3.2.1</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.3.1</maven-javadoc-plugin.version>
<maven-compiler-plugin.version>3.9.0</maven-compiler-plugin.version>
<maven-release-plugin.version>2.5.3</maven-release-plugin.version>
<maven-gpg-plugin.version>3.0.1</maven-gpg-plugin.version>
<mockito.version>4.4.0</mockito.version>
<nexus-staging-maven-plugin.version>1.6.8</nexus-staging-maven-plugin.version>
<archunit.version>1.2.0</archunit.version>
<assertj-core.version>3.24.2</assertj-core.version>
<checkstyle.version>10.12.5</checkstyle.version>
<jacoco.version>0.8.11</jacoco.version>
<maven-surefire-plugin.version>3.2.2</maven-surefire-plugin.version>
<maven-checkstyle-plugin.version>3.3.1</maven-checkstyle-plugin.version>
<maven-source-plugin.version>3.3.0</maven-source-plugin.version>
<maven-javadoc-plugin.version>3.6.2</maven-javadoc-plugin.version>
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
<maven-gpg-plugin.version>3.1.0</maven-gpg-plugin.version>
<mockito.version>5.7.0</mockito.version>
<nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version>
</properties>

<dependencies>
Expand Down Expand Up @@ -90,6 +89,12 @@
<version>${archunit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand All @@ -106,14 +111,6 @@
<showWarnings>true</showWarnings>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>${maven-release-plugin.version}</version>
<configuration>
<tagNameFormat>v@{project.version}-${project.artifactId}</tagNameFormat>
</configuration>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@
import java.util.Optional;
import java.util.Set;

@Getter
@Setter
class CapturingAppender extends ContextAwareBase implements Appender<ILoggingEvent> {

@Getter
List<LoggedEvent> loggedEvents = new ArrayList<>();
private final Set<String> capturedPackages;

@Getter
@Setter
private String name;
@Getter
private boolean started;

CapturingAppender(LoggerContext loggerContext, Set<String> capturedPackages) {
Expand All @@ -42,8 +43,8 @@ public synchronized void doAppend(ILoggingEvent loggingEvent) {
.formattedMessage(loggingEvent.getFormattedMessage())
.mdcData(loggingEvent.getMDCPropertyMap())
.loggedException(getLoggedException(loggingEvent.getThrowableProxy()))
.marker(loggingEvent.getMarker())
.argumentArray(loggingEvent.getArgumentArray())
.markers(loggingEvent.getMarkerList())
.keyValuePairs(loggingEvent.getKeyValuePairs())
.build());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public String getMatcherDetailDescription() {
}

private static String loggedExceptionToString(Optional<LoggedEvent.LoggedException> optionalException) {
if (!optionalException.isPresent()) {
if (optionalException.isEmpty()) {
return "(null)";
}

Expand All @@ -75,10 +75,10 @@ public String getMatcherTypeDescription() {
}

private static boolean exceptionMatches(Optional<LoggedEvent.LoggedException> optionalActualException, Optional<ExpectedException> optionalExpectedException) {
if (!optionalActualException.isPresent() && optionalExpectedException.isPresent()) {
if (optionalActualException.isEmpty() && optionalExpectedException.isPresent()) {
return false;
}
if (!optionalExpectedException.isPresent()) {
if (optionalExpectedException.isEmpty()) {
return true;
}

Expand All @@ -91,12 +91,12 @@ private static boolean exceptionMatches(Optional<LoggedEvent.LoggedException> op
}

private static boolean expectedMessageMatches(LoggedEvent.LoggedException loggedException, ExpectedException expectedException) {
return !expectedException.expectedMessage.isPresent() ||
return expectedException.expectedMessage.isEmpty() ||
expectedException.expectedMessage.get().matcher(loggedException.getMessage()).matches();
}

private static boolean expectedTypeMatches(LoggedEvent.LoggedException loggedException, ExpectedException expectedException) {
if (!expectedException.expectedType.isPresent()) {
if (expectedException.expectedType.isEmpty()) {
return true;
}
try {
Expand All @@ -117,7 +117,7 @@ public String toString() {
}

/**
* helper for building ExcpectedExceptions
* helper for building ExpectedExceptions
*/
public static final class ExpectedExceptionBuilder {
private String expectedMessageRegex;
Expand All @@ -130,7 +130,7 @@ private ExpectedExceptionBuilder() {
/**
* set an expected message that should be matched for an expected Exception
*
* @param expectedMessageRegex regular expression mathing an exception's message. Will be padded with .*
* @param expectedMessageRegex regular expression matching an exception's message. Will be padded with .*
*
* @return the builder with the expected message set
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package de.dm.infrastructure.logcapture;

import java.util.Objects;
import java.util.stream.Collectors;

import static java.lang.String.format;
import static java.lang.System.lineSeparator;

/**
* define expected key-value pair to be attached to a log message
*/
public final class ExpectedKeyValue implements LogEventMatcher {
private final String key;
private final Object value;

private ExpectedKeyValue(String key, Object value) {
if (key == null || value == null) {
throw new IllegalArgumentException("key and value are required for key-value log assertion");
}
this.key = key;
this.value = value;
}

@Override
public boolean matches(LoggedEvent loggedEvent) {
return loggedEvent.getKeyValuePairs() != null &&
loggedEvent.getKeyValuePairs().stream()
.anyMatch(pair -> key.equals(pair.key) && (
Objects.equals(value, pair.value) ||
areEqualAsNumbers(value, pair.value)
));
}

/*
* this is only done for Numbers because
* 1. toString() should not be expensive for these
* 2. when Logging 2L can be considered equal to 2, for example, but maybe not to 2.0
*/
private boolean areEqualAsNumbers(Object expectedValue, Object actualValue) {
return expectedValue instanceof Number && actualValue instanceof Number &&
expectedValue.toString().equals(actualValue.toString());
}

@Override
public String getNonMatchingErrorMessage(LoggedEvent loggedEvent) {
String expected = format(" expected key-value pair (%s, %s)", key, value) + lineSeparator();
return expected + format(" actual pairs: [%s]", loggedEvent.getKeyValuePairs() == null ? "" :
loggedEvent.getKeyValuePairs().stream()
.map(pair -> "(%s, %s)".formatted(pair.key, pair.value))
.collect(Collectors.joining(", ")));
}

@Override
public String getMatcherTypeDescription() {
return "key-value pair";
}

@Override
public String getMatcherDetailDescription() {
return format("key-value pair (%s, %s)", key, value);
}

/**
* use this in a log expectation to verify that something has been logged with a certain key-value pair
*
* @param key expected key
* @param value expected value
*
* @return expected key-value to use in log expectation
*/
public static ExpectedKeyValue keyValue(String key, Object value) {
return new ExpectedKeyValue(key, value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ private ExpectedMarker(String expectedName) {

@Override
public boolean matches(LoggedEvent loggedEvent) {
return loggedEvent.getMarker() != null &&
(loggedEvent.getMarker().getName().equals(expectedName) || loggedEvent.getMarker().contains(expectedName));
return loggedEvent.getMarkers() != null && loggedEvent.getMarkers().stream().anyMatch(marker -> marker.contains(expectedName));
}

@Override
public String getNonMatchingErrorMessage(LoggedEvent loggedEvent) {
String expected = format(" expected marker name: \"%s\"", expectedName) + lineSeparator();
if (loggedEvent.getMarker() == null) {
if (loggedEvent.getMarkers() == null) {
return expected + " but no marker was found";
}
return expected + format(" actual marker names: \"%s\"", loggedEvent.getMarker());
return expected + format(" actual marker names: \"%s\"", loggedEvent.getMarkers());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public final class ExpectedMdcEntry implements LogEventMatcher {
* @return expected Mdc entry to use in log expectation
*/
public static ExpectedMdcEntry mdc(String key, String valueRegex) {
return ExpectedMdcEntry.withMdc(key, valueRegex);
return new ExpectedMdcEntry(key, new PatternMatcher(valueRegex));
}

/**
Expand All @@ -40,7 +40,7 @@ public static ExpectedMdcEntry mdc(String key, String valueRegex) {
* @return expected Mdc entry to use in log expectation
*/
public static ExpectedMdcEntry mdc(String key, MdcMatcher mdcMatcher) {
return ExpectedMdcEntry.withMdc(key, mdcMatcher);
return new ExpectedMdcEntry(key, mdcMatcher);
}

@Override
Expand All @@ -56,8 +56,7 @@ public String getNonMatchingErrorMessage(LoggedEvent loggedEvent) {
StringBuilder assertionMessage = new StringBuilder(format(" captured message: \"%s\"", loggedEvent.getFormattedMessage()));
assertionMessage.append(lineSeparator());
assertionMessage.append(format(" expected MDC key: %s", key));
if (matcher instanceof PatternMatcher) {
PatternMatcher patternMatcher = (PatternMatcher) matcher;
if (matcher instanceof PatternMatcher patternMatcher) {
assertionMessage.append(lineSeparator());
assertionMessage.append(format(" expected MDC value: \"%s\"", patternMatcher.pattern));
}
Expand All @@ -80,37 +79,6 @@ public String getMatcherDetailDescription() {
return format("MDCValue with key: \"%s\"", key);
}

/**
* use this in LogCapture.assertLogged(...) to verify that something has been logged with an MDC value
*
* @param key MDC key
* @param valueRegex regex that must match the expected value. Will be wrapped with .*
*
* @return expected entry
*
* @deprecated in favor of mdc(key, valueRegex) that matches the new assertion style
*/
@Deprecated
public static ExpectedMdcEntry withMdc(String key, String valueRegex) {
return new ExpectedMdcEntry(key, new PatternMatcher(valueRegex));
}

/**
* use this in LogCapture.assertLogged(...) to verify that something has been logged with an MDC value using
* your own {@link MdcMatcher} if MDC contents are structured and the Matcher needs to understand the structure
*
* @param key MDC key
* @param matcher implementation of {@link MdcMatcher} that checks if the actual MDC content matches the expectations
*
* @return expected entry
*
* @deprecated in favor of mdc(key, matcher) that matches the new assertion style
*/
@Deprecated
public static ExpectedMdcEntry withMdc(String key, MdcMatcher matcher) {
return new ExpectedMdcEntry(key, matcher);
}

private static class PatternMatcher implements MdcMatcher {

private final Pattern pattern;
Expand Down
Loading
Loading