Skip to content

Commit

Permalink
Merge pull request #20 from dm-drogeriemarkt/4.0.0-dev
Browse files Browse the repository at this point in the history
4.0.0
  • Loading branch information
DizzDev authored Nov 27, 2023
2 parents 17724cd + fd62f68 commit 09bbe0d
Show file tree
Hide file tree
Showing 19 changed files with 383 additions and 842 deletions.
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

0 comments on commit 09bbe0d

Please sign in to comment.