merge master

This commit is contained in:
Ken Stevens 2024-07-10 10:26:03 -04:00
commit 85feb822e2
91 changed files with 276 additions and 405 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-bom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<packaging>pom</packaging>
<name>HAPI FHIR BOM</name>
@ -12,7 +12,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,8 +6,8 @@ import ca.uhn.fhir.system.HapiSystemProperties;
import ca.uhn.fhir.test.utilities.RestServerR4Helper;
import ca.uhn.fhir.test.utilities.TlsAuthenticationTestHelper;
import ca.uhn.fhir.util.ParametersUtil;
import ca.uhn.test.util.LogEventIterableAssert;
import ca.uhn.test.util.LogbackTestExtension;
import ca.uhn.test.util.LogbackTestExtensionAssert;
import ch.qos.logback.classic.Logger;
import org.hl7.fhir.instance.model.api.IBaseParameters;
import org.junit.jupiter.api.BeforeEach;
@ -30,6 +30,7 @@ import static org.mockito.Mockito.spy;
@ExtendWith(MockitoExtension.class)
class ReindexTerminologyCommandTest {
private static final String FAILURE_MESSAGE = "FAILURE";
private final FhirContext myContext = FhirContext.forR4();
@Spy
@ -68,10 +69,9 @@ class ReindexTerminologyCommandTest {
);
runAppWithStartupHook(args, getLoggingStartupHook());
LogEventIterableAssert.assertThat(myAppLogCapture.getLogEvents()).hasNoFailureMessages();
LogbackTestExtensionAssert.assertThat(myAppLogCapture).doesNotHaveMessage(FAILURE_MESSAGE);
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
public void testNoVersionThrows(boolean theIncludeTls) {
@ -131,8 +131,9 @@ class ReindexTerminologyCommandTest {
);
runAppWithStartupHook(args, getLoggingStartupHook());
LogEventIterableAssert.assertThat(myAppLogCapture.getLogEvents()).hasAtLeastOneFailureMessage();
LogEventIterableAssert.assertThat(myAppLogCapture.getLogEvents()).hasAtLeastOneEventWithMessage("Internal error. Command result unknown. Check system logs for details");
LogbackTestExtensionAssert.assertThat(myAppLogCapture)
.hasMessage(FAILURE_MESSAGE)
.hasMessage("Internal error. Command result unknown. Check system logs for details");
}
@ParameterizedTest
@ -155,8 +156,9 @@ class ReindexTerminologyCommandTest {
);
runAppWithStartupHook(args, getLoggingStartupHook());
LogEventIterableAssert.assertThat(myAppLogCapture.getLogEvents()).hasAtLeastOneFailureMessage();
LogEventIterableAssert.assertThat(myAppLogCapture.getLogEvents()).hasAtLeastOneEventWithMessage("Freetext service is not configured. Operation didn't run.");
LogbackTestExtensionAssert.assertThat(myAppLogCapture)
.hasMessage(FAILURE_MESSAGE)
.hasMessage("Freetext service is not configured. Operation didn't run.");
}
static void runAppWithStartupHook(String[] args, Consumer<BaseApp> startupHook) {

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-cli</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -11,7 +11,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -27,9 +27,7 @@ import ca.uhn.fhir.jpa.search.BaseSourceSearchParameterTestCases;
import ca.uhn.fhir.jpa.search.CompositeSearchParameterTestCases;
import ca.uhn.fhir.jpa.search.QuantitySearchParameterTestCases;
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
import ca.uhn.fhir.jpa.search.lastn.ElasticsearchRestClientFactory;
import ca.uhn.fhir.jpa.search.lastn.ElasticsearchSvcImpl;
import ca.uhn.fhir.jpa.search.lastn.json.ObservationJson;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
@ -60,17 +58,11 @@ import ca.uhn.fhir.test.utilities.docker.RequiresDocker;
import ca.uhn.fhir.validation.FhirValidator;
import ca.uhn.fhir.validation.ValidationResult;
import ca.uhn.test.util.LogbackTestExtension;
import ca.uhn.test.util.LogbackTestExtensionAssert;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import com.fasterxml.jackson.databind.node.ObjectNode;
import jakarta.annotation.Nonnull;
import jakarta.json.JsonValue;
import jakarta.persistence.EntityManager;
import org.apache.commons.lang3.RandomStringUtils;
import org.elasticsearch.client.RequestOptions;
import org.hl7.fhir.instance.model.api.IBaseCoding;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@ -282,7 +274,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
class ElasticPerformanceTracingInterceptor {
private List<StorageProcessingMessage> messages = new ArrayList<>();
private final List<StorageProcessingMessage> messages = new ArrayList<>();
@Hook(Pointcut.JPA_PERFTRACE_INFO)
public void logPerformance(StorageProcessingMessage theMessage) {
@ -955,9 +947,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
assertThat(result).hasSize(1);
assertEquals(((Observation) result.get(0)).getIdElement().getIdPart(), id1.getIdPart());
List<ILoggingEvent> events = myLogbackTestExtension.filterLoggingEventsWithPredicate(e -> e.getLevel() == Level.WARN);
assertFalse(events.isEmpty());
assertTrue(events.stream().anyMatch(e -> e.getFormattedMessage().contains("Some resources were not found in index. Make sure all resources were indexed. Resorting to database search.")));
LogbackTestExtensionAssert.assertThat(myLogbackTestExtension).hasWarnMessage("Some resources were not found in index. Make sure all resources were indexed. Resorting to database search.");
// restore changed property
JpaStorageSettings defaultConfig = new JpaStorageSettings();
@ -1766,7 +1756,7 @@ public class FhirResourceDaoR4SearchWithElasticSearchIT extends BaseJpaTest impl
public class LastUpdatedTests {
private String myOldObsId, myNewObsId;
private String myOldLastUpdatedDateTime = "2017-03-24T03:21:47";
private final String myOldLastUpdatedDateTime = "2017-03-24T03:21:47";
@BeforeEach
public void enableResourceStorage() {

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -13,9 +13,8 @@ import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
import ca.uhn.fhir.rest.server.SimpleBundleProvider;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.subscription.SubscriptionConstants;
import ca.uhn.test.util.LogEventIterableAssert;
import ca.uhn.test.util.LogbackTestExtension;
import ch.qos.logback.classic.Level;
import ca.uhn.test.util.LogbackTestExtensionAssert;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.Subscription;
import org.junit.jupiter.api.BeforeEach;
@ -125,10 +124,8 @@ public class SubscriptionLoaderTest {
verify(mySubscriptionDao)
.searchForResources(any(SearchParameterMap.class), any(SystemRequestDetails.class));
String expected = "Subscription "
+ subscription.getIdElement().getIdPart()
+ " could not be activated.";
LogEventIterableAssert.assertThat(myLogCapture.getLogEvents()).hasEventWithLevelAndMessageContains(Level.ERROR, expected);
LogEventIterableAssert.assertThat(myLogCapture.getLogEvents()).hasAtLeastOneEventWithMessage(subscription.getError());
LogbackTestExtensionAssert.assertThat(myLogCapture).hasErrorMessage(
"Subscription " + subscription.getIdElement().getIdPart() + " could not be activated.");
LogbackTestExtensionAssert.assertThat(myLogCapture).hasMessage(subscription.getError());
}
}

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -32,8 +32,8 @@ import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.OperationOutcomeUtil;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.validation.IValidatorModule;
import ca.uhn.test.util.LogbackTestExtensionAssert;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
import org.hl7.fhir.common.hapi.validation.support.UnknownCodeSystemWarningValidationSupport;
@ -103,6 +103,7 @@ import static org.hl7.fhir.common.hapi.validation.support.CommonCodeSystemsTermi
import static org.hl7.fhir.common.hapi.validation.support.ValidationConstants.LOINC_LOW;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
@ -1514,7 +1515,7 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
// validator
assertNotNull(outcome);
assertTrue(outcome.getOperationOutcome() instanceof OperationOutcome);
assertInstanceOf(OperationOutcome.class, outcome.getOperationOutcome());
List<OperationOutcome.OperationOutcomeIssueComponent> issues = ((OperationOutcome) outcome.getOperationOutcome()).getIssue();
assertFalse(issues.isEmpty());
List<OperationOutcome.OperationOutcomeIssueComponent> errors = issues.stream()
@ -1523,12 +1524,7 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
// we have errors
assertFalse(errors.isEmpty());
List<ILoggingEvent> events = myLogbackTestExtension.filterLoggingEventsWithPredicate(e -> {
return e.getLevel() == Level.WARN;
});
// and we have warning logs
assertFalse(events.isEmpty());
assertTrue(events.stream().anyMatch(e -> e.getFormattedMessage().contains("Unrecognized profile uri")));
LogbackTestExtensionAssert.assertThat(myLogbackTestExtension).hasWarnMessage("Unrecognized profile uri");
}
@Test
@ -1654,7 +1650,7 @@ public class FhirResourceDaoR4ValidateTest extends BaseJpaR4Test {
// verify
assertNotNull(outcome);
assertTrue(outcome.getOperationOutcome() instanceof OperationOutcome);
assertInstanceOf(OperationOutcome.class, outcome.getOperationOutcome());
List<OperationOutcome.OperationOutcomeIssueComponent> issues = ((OperationOutcome) outcome.getOperationOutcome()).getIssue();
assertFalse(issues.isEmpty());
List<OperationOutcome.OperationOutcomeIssueComponent> errors = issues.stream()

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -12,9 +12,8 @@ import ca.uhn.fhir.rest.server.interceptor.auth.IAuthorizationSearchParamMatcher
import ca.uhn.fhir.rest.server.interceptor.auth.PolicyEnum;
import ca.uhn.fhir.rest.server.interceptor.auth.RuleBuilder;
import ca.uhn.fhir.test.utilities.ITestDataBuilder;
import ca.uhn.test.util.LogEventIterableAssert;
import ca.uhn.test.util.LogbackTestExtension;
import ch.qos.logback.classic.Level;
import ca.uhn.test.util.LogbackTestExtensionAssert;
import jakarta.annotation.Nullable;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@ -272,7 +271,7 @@ class FhirQueryRuleImplTest implements ITestDataBuilder {
// then
assertNull(verdict);
LogEventIterableAssert.assertThat(myLogCapture.getLogEvents()).hasEventWithLevelAndMessageContains(Level.WARN, "unsupported chain XXX");
LogbackTestExtensionAssert.assertThat(myLogCapture).hasWarnMessage("unsupported chain XXX");
}
@Test
@ -287,7 +286,7 @@ class FhirQueryRuleImplTest implements ITestDataBuilder {
// then
assertEquals(PolicyEnum.DENY, verdict.getDecision());
LogEventIterableAssert.assertThat(myLogCapture.getLogEvents()).hasEventWithLevelAndMessageContains(Level.WARN, "unsupported chain XXX");
LogbackTestExtensionAssert.assertThat(myLogCapture).hasWarnMessage("unsupported chain XXX");
}
/**
@ -306,7 +305,7 @@ class FhirQueryRuleImplTest implements ITestDataBuilder {
// then
assertNull(verdict);
LogEventIterableAssert.assertThat(myLogCapture.getLogEvents()).hasEventWithLevelAndMessageContains(Level.WARN, "No matcher provided");
LogbackTestExtensionAssert.assertThat(myLogCapture).hasWarnMessage("No matcher provided");
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,8 +5,8 @@ import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceJson;
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceRequestJson;
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseCardJson;
import ca.uhn.hapi.fhir.cdshooks.api.json.CdsServiceResponseJson;
import ca.uhn.test.util.LogEventIterableAssert;
import ca.uhn.test.util.LogbackTestExtension;
import ca.uhn.test.util.LogbackTestExtensionAssert;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import jakarta.annotation.Nonnull;
@ -68,7 +68,7 @@ class CdsServiceCacheTest {
assertTrue(cdsMethod.isAllowAutoFhirClientPrefetch());
assertThat(myFixture.myCdsServiceJson.getServices()).hasSize(1);
assertEquals(cdsServiceJson, myFixture.myCdsServiceJson.getServices().get(0));
LogEventIterableAssert.assertThat(myLogCapture.getLogEvents()).hasEventWithLevelAndMessageContains(Level.ERROR, expectedLogMessage);
LogbackTestExtensionAssert.assertThat(myLogCapture).hasErrorMessage(expectedLogMessage);
}
@ -96,7 +96,7 @@ class CdsServiceCacheTest {
final ICdsMethod actual = myFixture.unregisterServiceMethod(TEST_KEY, MODULE_ID);
// validate
assertNull(actual);
LogEventIterableAssert.assertThat(myLogCapture.getLogEvents()).hasEventWithLevelAndMessageContains(Level.ERROR, expectedLogMessage);
LogbackTestExtensionAssert.assertThat(myLogCapture).hasErrorMessage(expectedLogMessage);
}
@Nonnull

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>hapi-fhir-serviceloaders</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>hapi-fhir-serviceloaders</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -21,7 +21,7 @@
<dependency>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-caching-api</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
</dependency>
<dependency>

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>hapi-fhir-serviceloaders</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<artifactId>hapi-fhir</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>hapi-deployable-pom</artifactId>
<groupId>ca.uhn.hapi.fhir</groupId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
</parent>
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir-spring-boot</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -13,6 +13,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import static ca.uhn.test.util.LoggingEventPredicates.makeMessageContains;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -56,7 +57,7 @@ class ObservableSupplierSetTest {
myObservableSupplierSet.removeSupplier(myCounter::incrementAndGet);
myObserver.assertCalls(1, 0);
assertThat(myObservableSupplierSet.getSupplierResults()).hasSize(1);
List<ILoggingEvent> events = myLogger.filterLoggingEventsWithMessageContaining("Failed to remove supplier");
List<ILoggingEvent> events = myLogger.getLogEvents(makeMessageContains("Failed to remove supplier"));
assertThat(events).hasSize(1);
assertEquals(Level.WARN, events.get(0).getLevel());
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -1,30 +0,0 @@
/*-
* #%L
* HAPI FHIR Test Utilities
* %%
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.test.util;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.assertj.core.api.AbstractAssert;
public class LogEventAssert extends AbstractAssert<LogEventAssert, ILoggingEvent> {
protected LogEventAssert(ILoggingEvent actual) {
super(actual, LogEventAssert.class);
}
}

View File

@ -1,119 +0,0 @@
/*-
* #%L
* HAPI FHIR Test Utilities
* %%
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.test.util;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import jakarta.annotation.Nonnull;
import org.assertj.core.api.AbstractIterableAssert;
import java.util.Collection;
public class LogEventIterableAssert extends AbstractIterableAssert<LogEventIterableAssert, Collection<? extends ILoggingEvent>, ILoggingEvent, LogEventAssert> {
protected LogEventIterableAssert(Collection<ILoggingEvent> actual) {
super(actual, LogEventIterableAssert.class);
}
public static LogEventIterableAssert assertThat(Collection<ILoggingEvent> actual) {
return new LogEventIterableAssert(actual);
}
public LogEventIterableAssert hasNoFailureMessages() {
isNotNull();
matches(logEvents -> logEvents.stream()
.map(ILoggingEvent::getMessage)
.noneMatch(message -> message.contains("FAILURE")),
"LogEvents should not contain messages with 'FAILURE'");
return this;
}
public LogEventIterableAssert hasEventWithLevelAndMessageContains(@Nonnull Level theLevel, @Nonnull String thePartialMessage) {
isNotNull();
matches(logEvents -> logEvents.stream()
.anyMatch(event-> event.getFormattedMessage().contains(thePartialMessage) &&
event.getLevel().isGreaterOrEqual(theLevel)),
"Log Events should have at least one message with `"+theLevel.levelStr+"` in it.");
return this;
}
public LogEventIterableAssert hasAtLeastOneFailureMessage() {
isNotNull();
matches(logEvents -> logEvents.stream()
.map(ILoggingEvent::getMessage)
.anyMatch(message -> message.contains("FAILURE")),
"Log Events should have at least one message with `FAILURE` in it.");
return this;
}
public LogEventIterableAssert hasAtLeastOneEventWithMessage(String thePartial) {
isNotNull();
matches(logEvents -> logEvents.stream()
.map(ILoggingEvent::getFormattedMessage)
.anyMatch(message -> message.contains(thePartial)),
"Log Events should have at least one message with "+ thePartial + " in it.");
return this;
}
@Override
protected LogEventAssert toAssert(ILoggingEvent value, String description) {
return new LogEventAssert(value).as(description);
}
@Override
protected LogEventIterableAssert newAbstractIterableAssert(Iterable<? extends ILoggingEvent> iterable) {
return new LogEventIterableAssert((Collection<ILoggingEvent>) iterable);
}
public LogEventIterableAssert doesNotHaveEventWithMessage(String thePartial) {
isNotNull();
matches(logEvents -> logEvents.stream()
.map(ILoggingEvent::getFormattedMessage)
.noneMatch(message -> message.contains(thePartial)),
"Log Events should have no message with "+ thePartial + " in it.");
return this;
}
public LogEventIterableAssert hasEventWithLevelAndMessageAndThrew(Level theLevel, String thePartial, String theExceptionMessage) {
isNotNull();
matches(logEvents -> logEvents.stream()
.filter(message -> message.getMessage().contains(thePartial))
.filter(message -> message.getLevel() == theLevel)
.anyMatch(message -> message.getThrowableProxy().getMessage().contains(theExceptionMessage)),
"Log Events should have at least one message with "+ thePartial + " in it.");
return this;
}
public LogEventIterableAssert doesNotHaveEventWithLevelAndMessage(Level theLevel, String thePartial) {
isNotNull();
matches(logEvents -> logEvents.stream()
.filter(e -> e.getLevel() == theLevel)
.map(ILoggingEvent::getFormattedMessage)
.noneMatch(message -> message.contains(thePartial)),
"Log Events should have no " + theLevel.toString() + " message with "+ thePartial + " in it.");
return this;
}
}

View File

@ -1,75 +0,0 @@
/*-
* #%L
* HAPI FHIR Test Utilities
* %%
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.test.util;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import jakarta.annotation.Nullable;
import org.assertj.core.api.AbstractAssert;
/**
* An assertj matcher for junit assertions.
* Matches on level, partial message, and/or a portion of the message contained by a throwable, if present.
*/
public class LogbackEventAssert extends AbstractAssert<LogbackEventAssert, ILoggingEvent> {
@Nullable
private final Level myLevel;
@Nullable
private final String myLogMessage;
@Nullable
private final String myThrownMessage;
public LogbackEventAssert(@Nullable Level theLevel, @Nullable String thePartialString) {
this(theLevel, thePartialString, null);
}
public LogbackEventAssert(@Nullable Level theLevel, @Nullable String thePartialString, @Nullable String theThrownMessage) {
super(null, LogbackEventAssert.class);
myLevel = theLevel;
myLogMessage = thePartialString;
myThrownMessage = theThrownMessage;
}
public static LogbackEventAssert assertThat(@Nullable Level theLevel, @Nullable String thePartialString) {
return new LogbackEventAssert(theLevel, thePartialString);
}
public static LogbackEventAssert assertThat(@Nullable Level theLevel, @Nullable String thePartialString, @Nullable String theThrownMessage) {
return new LogbackEventAssert(theLevel, thePartialString, theThrownMessage);
}
public LogbackEventAssert matches(ILoggingEvent item) {
isNotNull();
if (myLevel != null && !item.getLevel().isGreaterOrEqual(myLevel)) {
failWithMessage("Expected level to be at least <%s> but was <%s>", myLevel, item.getLevel());
}
if (myLogMessage != null && !item.getFormattedMessage().contains(myLogMessage)) {
failWithMessage("Expected log message to contain <%s> but was <%s>", myLogMessage, item.getFormattedMessage());
}
if (myThrownMessage != null && (item.getThrowableProxy() == null || !item.getThrowableProxy().getMessage().contains(myThrownMessage))) {
failWithMessage("Expected throwable message to contain <%s> but was <%s>", myThrownMessage, item.getThrowableProxy() != null ? item.getThrowableProxy().getMessage() : "null");
}
return this;
}
}

View File

@ -32,9 +32,6 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test helper to collect logback lines.
@ -80,7 +77,11 @@ public class LogbackTestExtension implements BeforeEachCallback, AfterEachCallba
this((Logger) theLogger);
}
public java.util.List<ILoggingEvent> getLogEvents() {
/**
* Returns a copy to avoid concurrent modification errors.
* @return A copy of the log events so far.
*/
public List<ILoggingEvent> getLogEvents() {
return new ArrayList<>(myListAppender.list);
}
@ -120,37 +121,13 @@ public class LogbackTestExtension implements BeforeEachCallback, AfterEachCallba
}
}
public List<ILoggingEvent> filterLoggingEventsWithMessageEqualTo(String theMessageText) {
return filterLoggingEventsWithPredicate(loggingEvent -> loggingEvent.getFormattedMessage().equals(theMessageText));
}
public List<ILoggingEvent> filterLoggingEventsWithMessageContaining(String theMessageText) {
return filterLoggingEventsWithPredicate(loggingEvent -> loggingEvent.getFormattedMessage().contains(theMessageText));
}
public List<ILoggingEvent> filterLoggingEventsWithPredicate(Predicate<ILoggingEvent> theLoggingEventPredicate) {
return getLogEvents().stream().filter(theLoggingEventPredicate).collect(Collectors.toList());
public List<ILoggingEvent> getLogEvents(Predicate<ILoggingEvent> thePredicate) {
return getLogEvents().stream().filter(thePredicate).toList();
}
@Nonnull
public List<String> getLogMessages() {
return getLogEvents().stream().map(ILoggingEvent::getMessage).collect(Collectors.toList());
return getLogEvents().stream().map(ILoggingEvent::getMessage).toList();
}
public static void assertEventWithLevelAndMessageContains(List<ILoggingEvent> events, @Nonnull Level theLevel, @Nonnull String thePartialMessage) {
assertThat(events).anySatisfy(event -> LogbackEventAssert.assertThat(theLevel, thePartialMessage).matches(event));
}
public static void assertEventWithLevel(List<ILoggingEvent> events, @Nonnull Level theLevel) {
assertThat(events).anySatisfy(event -> LogbackEventAssert.assertThat(theLevel, null).matches(event));
}
public static void assertEventWithMessageContains(List<ILoggingEvent> events, @Nonnull String thePartialMessage) {
assertThat(events).anySatisfy(event -> LogbackEventAssert.assertThat(null, thePartialMessage).matches(event));
}
public static void assertEventWithLevelAndMessageAndThrew(List<ILoggingEvent> events, @Nonnull Level theLevel,
@Nonnull String thePartialMessage, @Nonnull String theThrown) {
assertThat(events).anySatisfy(event -> LogbackEventAssert.assertThat(theLevel, thePartialMessage, theThrown).matches(event));
}
}

View File

@ -29,7 +29,16 @@ import org.assertj.core.api.Condition;
import java.util.List;
import java.util.function.Predicate;
import static ca.uhn.test.util.LoggingEventPredicates.makeAnyMatch;
import static ca.uhn.test.util.LoggingEventPredicates.makeLevelEquals;
import static ca.uhn.test.util.LoggingEventPredicates.makeMessageContains;
public class LogbackTestExtensionAssert extends AbstractAssert<LogbackTestExtensionAssert, LogbackTestExtension> {
private static final String HAS_ERROR_MSG_1 = "has logging message with message containing %s";
private static final String HAS_ERROR_MSG_2 = "has logging message with level %s and message containing %s";
@Nonnull
public static LogbackTestExtensionAssert assertThat(@Nonnull LogbackTestExtension theLogbackTestExtension) {
return new LogbackTestExtensionAssert(theLogbackTestExtension, LogbackTestExtensionAssert.class);
@ -39,21 +48,93 @@ public class LogbackTestExtensionAssert extends AbstractAssert<LogbackTestExtens
super(theLogbackTestExtension, selfType);
}
/**
* Verifies that messages contains exactly the given values and nothing else, in order.
*/
@Nonnull
public LogbackTestExtensionAssert hasError(@Nonnull String theMessage) {
Assertions.assertThat(actual.getLogEvents()).has(eventWithLevelAndMessageContains(Level.ERROR, theMessage));
public LogbackTestExtensionAssert containsExactMessages(@Nonnull String ... theMessages) {
isNotNull();
Assertions.assertThat(actual.getLogMessages()).containsExactly(theMessages);
return this;
}
@Nonnull
public LogbackTestExtensionAssert hasInfo(@Nonnull String theMessage) {
Assertions.assertThat(actual.getLogEvents()).has(eventWithLevelAndMessageContains(Level.INFO, theMessage));
public LogbackTestExtensionAssert hasMessage(@Nonnull String theMessage) {
isNotNull();
final Predicate<ILoggingEvent> predicate = makeMessageContains(theMessage);
final Condition<List<? extends ILoggingEvent>> condition =
new Condition<>(makeAnyMatch(predicate), HAS_ERROR_MSG_1, theMessage);
Assertions.assertThat(actual.getLogEvents()).has(condition);
return this;
}
public LogbackTestExtensionAssert doesNotHaveMessage(@Nonnull String theMessage) {
isNotNull();
final Predicate<ILoggingEvent> predicate = makeMessageContains(theMessage);
final Condition<List<? extends ILoggingEvent>> condition =
new Condition<>(makeAnyMatch(predicate), HAS_ERROR_MSG_1, theMessage);
Assertions.assertThat(actual.getLogEvents()).doesNotHave(condition);
return this;
}
@Nonnull
public LogbackTestExtensionAssert hasDebug(@Nonnull String theMessage) {
Assertions.assertThat(actual.getLogEvents()).has(eventWithLevelAndMessageContains(Level.DEBUG, theMessage));
public LogbackTestExtensionAssert hasErrorMessage(@Nonnull String theMessage) {
isNotNull();
final Predicate<ILoggingEvent> predicate = makeLevelEquals(Level.ERROR)
.and(makeMessageContains(theMessage));
final Condition<List<? extends ILoggingEvent>> condition =
new Condition<>(makeAnyMatch(predicate), HAS_ERROR_MSG_2, Level.ERROR, theMessage);
Assertions.assertThat(actual.getLogEvents()).has(condition);
return this;
}
@Nonnull
public LogbackTestExtensionAssert hasInfoMessage(@Nonnull String theMessage) {
isNotNull();
final Predicate<ILoggingEvent> predicate = makeLevelEquals(Level.INFO)
.and(makeMessageContains(theMessage));
final Condition<List<? extends ILoggingEvent>> condition =
new Condition<>(makeAnyMatch(predicate), HAS_ERROR_MSG_2, Level.INFO, theMessage);
Assertions.assertThat(actual.getLogEvents()).has(condition);
return this;
}
@Nonnull
public LogbackTestExtensionAssert doesNotHaveInfoMessage(@Nonnull String theMessage) {
isNotNull();
final Predicate<ILoggingEvent> predicate = makeLevelEquals(Level.INFO).and(makeMessageContains(theMessage));
final Condition<List<? extends ILoggingEvent>> condition =
new Condition<>(makeAnyMatch(predicate), HAS_ERROR_MSG_2, Level.INFO, theMessage);
Assertions.assertThat(actual.getLogEvents()).doesNotHave(condition);
return this;
}
@Nonnull
public LogbackTestExtensionAssert hasWarnMessage(@Nonnull String theMessage) {
isNotNull();
final Predicate<ILoggingEvent> predicate = makeLevelEquals(Level.WARN)
.and(makeMessageContains(theMessage));
final Condition<List<? extends ILoggingEvent>> condition =
new Condition<>(makeAnyMatch(predicate), HAS_ERROR_MSG_2, Level.WARN, theMessage);
Assertions.assertThat(actual.getLogEvents()).has(condition);
return this;
}
@Nonnull
public LogbackTestExtensionAssert hasDebugMessage(@Nonnull String theMessage) {
isNotNull();
final Predicate<ILoggingEvent> predicate = makeLevelEquals(Level.DEBUG)
.and(makeMessageContains(theMessage));
final Condition<List<? extends ILoggingEvent>> condition =
new Condition<>(makeAnyMatch(predicate), HAS_ERROR_MSG_2, Level.DEBUG, theMessage);
Assertions.assertThat(actual.getLogEvents()).has(condition);
return this;
}
@Nonnull
public LogbackTestExtensionAssert anyMatch(@Nonnull Predicate<ILoggingEvent> thePredicate) {
isNotNull();
Assertions.assertThat(actual.getLogEvents()).anyMatch(thePredicate);
return this;
}
@ -64,12 +145,17 @@ public class LogbackTestExtensionAssert extends AbstractAssert<LogbackTestExtens
}
@Nonnull
private Condition<? super List<? extends ILoggingEvent>> eventWithLevelAndMessageContains(@Nonnull Level theLevel, @Nonnull String theExpected) {
final Predicate<ILoggingEvent> loggingEvent = theLoggingEvent ->
theLoggingEvent.getLevel().equals(theLevel) && theLoggingEvent.getFormattedMessage().contains(theExpected);
final Predicate<List<? extends ILoggingEvent>> loggingEvents = theLoggingEvents ->
theLoggingEvents.stream().anyMatch(loggingEvent);
return new Condition<>(loggingEvents, "has error logging message with level %s and message containing %s", theLevel, theExpected);
public LogbackTestExtensionAssert isNotEmpty() {
isNotNull();
Assertions.assertThat(actual.getLogEvents()).isNotEmpty();
return this;
}
@Nonnull
public LogbackTestExtensionAssert hasSize(int theExpected) {
isNotNull();
Assertions.assertThat(actual.getLogEvents()).hasSize(theExpected);
return this;
}
}

View File

@ -0,0 +1,58 @@
/*-
* #%L
* HAPI FHIR Test Utilities
* %%
* Copyright (C) 2014 - 2024 Smile CDR, Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package ca.uhn.test.util;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import jakarta.annotation.Nonnull;
import java.util.List;
import java.util.function.Predicate;
public final class LoggingEventPredicates {
private LoggingEventPredicates() {
}
@Nonnull
public static Predicate<ILoggingEvent> makeLevelEquals(@Nonnull Level theLevel) {
return loggingEvent -> loggingEvent.getLevel().equals(theLevel);
}
@Nonnull
public static Predicate<ILoggingEvent> makeMessageEquals(@Nonnull String theMessage) {
return loggingEvent -> loggingEvent.getFormattedMessage().equals(theMessage);
}
@Nonnull
public static Predicate<ILoggingEvent> makeMessageContains(@Nonnull String theMessage) {
return loggingEvent -> loggingEvent.getFormattedMessage().contains(theMessage);
}
@Nonnull
public static Predicate<ILoggingEvent> makeExceptionMessageContains(@Nonnull String theExceptionMessage) {
return loggingEvent -> loggingEvent.getThrowableProxy().getMessage().contains(theExceptionMessage);
}
@Nonnull
public static Predicate<List<? extends ILoggingEvent>> makeAnyMatch(@Nonnull Predicate<ILoggingEvent> thePredicate) {
return loggingEvents -> loggingEvents.stream().anyMatch(thePredicate);
}
}

View File

@ -21,13 +21,10 @@ package ca.uhn.test.util;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.filter.ThresholdFilter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import java.util.List;
/**
* This is a static wrapper around LogbackTestExtension for use in IT tests when you need to assert on App
* startup log entries
@ -64,16 +61,8 @@ public class StaticLogbackTestExtension implements BeforeAllCallback, AfterAllCa
myLogbackTestExtension.afterEach(theExtensionContext);
}
public List<ILoggingEvent> filterLoggingEventsWithMessageEqualTo(String theMessageText) {
return myLogbackTestExtension.filterLoggingEventsWithMessageEqualTo(theMessageText);
}
/**
* Returns a copy to avoid concurrent modification errors.
* @return A copy of the log events so far.
*/
public java.util.List<ILoggingEvent> getLogEvents() {
return myLogbackTestExtension.getLogEvents();
public LogbackTestExtension getLogbackTestExtension() {
return myLogbackTestExtension;
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-deployable-pom</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -8,7 +8,7 @@
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<packaging>pom</packaging>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<name>HAPI-FHIR</name>
<description>An open-source implementation of the FHIR specification in Java.</description>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>hapi-fhir</artifactId>
<version>7.3.9-SNAPSHOT</version>
<version>7.3.10-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>