From 213b2ea9bc3f8ef00f13ae16650ff5180a11f925 Mon Sep 17 00:00:00 2001 From: Dmytro Nosan Date: Wed, 29 Jan 2025 00:44:42 +0200 Subject: [PATCH] Add more tests for SystemStatusListener and LogbackLoggingSystem See gh-44012 Signed-off-by: Dmytro Nosan --- .../logging/logback/SystemStatusListener.java | 2 +- .../logback/LogbackLoggingSystemTests.java | 13 +++++ .../logback/SystemStatusListenerTests.java | 53 ++++++++++++++++--- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/SystemStatusListener.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/SystemStatusListener.java index a033d72ac7d..ae6fac54669 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/SystemStatusListener.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/SystemStatusListener.java @@ -38,7 +38,7 @@ import ch.qos.logback.core.util.StatusListenerConfigHelper; */ final class SystemStatusListener extends OnConsoleStatusListener { - static final long RETROSPECTIVE_THRESHOLD = 300; + private static final long RETROSPECTIVE_THRESHOLD = 300; private final boolean debug; diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java index 5bd3ff185b8..474fe2b37fa 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemTests.java @@ -42,6 +42,7 @@ import ch.qos.logback.core.rolling.RollingFileAppender; import ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy; import ch.qos.logback.core.status.ErrorStatus; import ch.qos.logback.core.status.InfoStatus; +import ch.qos.logback.core.status.OnConsoleStatusListener; import ch.qos.logback.core.status.StatusManager; import ch.qos.logback.core.status.WarnStatus; import ch.qos.logback.core.util.DynamicClassLoadingException; @@ -673,6 +674,18 @@ class LogbackLoggingSystemTests extends AbstractLoggingSystemTests { } } + @Test + void logbackSystemStatusListenerShouldBeRegisteredWhenCustomLogbackXmlHasStatusListener(CapturedOutput output) { + this.loggingSystem.beforeInitialize(); + initialize(this.initializationContext, "classpath:logback-include-status-listener.xml", null); + LoggerContext loggerContext = this.logger.getLoggerContext(); + assertThat(loggerContext.getStatusManager().getCopyOfStatusListenerList()).hasSize(2) + .allSatisfy((listener) -> assertThat(listener).isInstanceOf(OnConsoleStatusListener.class)) + .anySatisfy((listener) -> assertThat(listener).isInstanceOf(SystemStatusListener.class)); + this.logger.info("Hello world"); + assertThat(output).contains("Hello world"); + } + @Test void logbackSystemStatusListenerShouldBeRegistered(CapturedOutput output) { this.loggingSystem.beforeInitialize(); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/SystemStatusListenerTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/SystemStatusListenerTests.java index a3ef3bf6593..0d98cc61fc9 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/SystemStatusListenerTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/SystemStatusListenerTests.java @@ -16,6 +16,7 @@ package org.springframework.boot.logging.logback; +import java.util.List; import java.util.function.Supplier; import ch.qos.logback.classic.LoggerContext; @@ -31,6 +32,7 @@ import org.mockito.ArgumentCaptor; import org.springframework.boot.testsupport.system.CapturedOutput; import org.springframework.boot.testsupport.system.OutputCaptureExtension; +import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -49,6 +51,15 @@ class SystemStatusListenerTests { private static final String TEST_MESSAGE = "testtesttest"; + private final StatusManager statusManager = mock(StatusManager.class); + + private final LoggerContext loggerContext = mock(LoggerContext.class); + + SystemStatusListenerTests() { + given(this.loggerContext.getStatusManager()).willReturn(this.statusManager); + given(this.statusManager.add(any(StatusListener.class))).willReturn(true); + } + @Test void addStatusWithInfoLevelWhenNoDebugDoesNotPrint(CapturedOutput output) { addStatus(false, () -> new InfoStatus(TEST_MESSAGE, null)); @@ -91,15 +102,43 @@ class SystemStatusListenerTests { assertThat(output.getErr()).doesNotContain(TEST_MESSAGE); } + @Test + void shouldRetrospectivePrintStatusOnStartAndDebugIsDisabled(CapturedOutput output) { + given(this.statusManager.getCopyOfStatusList()).willReturn(List.of(new ErrorStatus(TEST_MESSAGE, null), + new WarnStatus(TEST_MESSAGE, null), new InfoStatus(TEST_MESSAGE, null))); + addStatus(false, () -> new InfoStatus(TEST_MESSAGE, null)); + assertThat(output.getErr()).contains("WARN " + TEST_MESSAGE); + assertThat(output.getErr()).contains("ERROR " + TEST_MESSAGE); + assertThat(output.getErr()).doesNotContain("INFO"); + assertThat(output.getOut()).isEmpty(); + } + + @Test + void shouldRetrospectivePrintStatusOnStartAndDebugIsEnabled(CapturedOutput output) { + given(this.statusManager.getCopyOfStatusList()).willReturn(List.of(new ErrorStatus(TEST_MESSAGE, null), + new WarnStatus(TEST_MESSAGE, null), new InfoStatus(TEST_MESSAGE, null))); + addStatus(true, () -> new InfoStatus(TEST_MESSAGE, null)); + assertThat(output.getErr()).isEmpty(); + assertThat(output.getOut()).contains("WARN " + TEST_MESSAGE); + assertThat(output.getOut()).contains("ERROR " + TEST_MESSAGE); + assertThat(output.getOut()).contains("INFO " + TEST_MESSAGE); + } + + @Test + void shouldNotRetrospectivePrintWhenStatusIsOutdated(CapturedOutput output) { + ErrorStatus outdatedStatus = new ErrorStatus(TEST_MESSAGE, null); + ReflectionTestUtils.setField(outdatedStatus, "timestamp", System.currentTimeMillis() - 300); + given(this.statusManager.getCopyOfStatusList()).willReturn(List.of(outdatedStatus)); + addStatus(false, () -> new InfoStatus(TEST_MESSAGE, null)); + assertThat(output.getOut()).isEmpty(); + assertThat(output.getErr()).isEmpty(); + } + private void addStatus(boolean debug, Supplier statusFactory) { - StatusManager statusManager = mock(StatusManager.class); - given(statusManager.add(any(StatusListener.class))).willReturn(true); - LoggerContext loggerContext = mock(LoggerContext.class); - given(loggerContext.getStatusManager()).willReturn(statusManager); - SystemStatusListener.addTo(loggerContext, debug); + SystemStatusListener.addTo(this.loggerContext, debug); ArgumentCaptor listener = ArgumentCaptor.forClass(StatusListener.class); - then(statusManager).should().add(listener.capture()); - assertThat(listener.getValue()).extracting("context").isSameAs(loggerContext); + then(this.statusManager).should().add(listener.capture()); + assertThat(listener.getValue()).extracting("context").isSameAs(this.loggerContext); listener.getValue().addStatusEvent(statusFactory.get()); }