diff --git a/pom.xml b/pom.xml index ebdd52f7..c07b55f4 100644 --- a/pom.xml +++ b/pom.xml @@ -140,6 +140,12 @@ org.apache.pdfbox pdfbox ${pdfbox.version} + + + commons-logging + commons-logging + + diff --git a/scripts/test_commons_logging_dependency_contract.py b/scripts/test_commons_logging_dependency_contract.py new file mode 100644 index 00000000..e10716da --- /dev/null +++ b/scripts/test_commons_logging_dependency_contract.py @@ -0,0 +1,48 @@ +import re +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +POM = ROOT / "pom.xml" + + +def _pom_text() -> str: + return POM.read_text(encoding="utf-8") + + +def _dependency_block(pom: str, group_id: str, artifact_id: str) -> str: + pattern = re.compile( + r"\s*" + rf"{re.escape(group_id)}\s*" + rf"{re.escape(artifact_id)}" + r".*?", + re.DOTALL, + ) + match = pattern.search(pom) + assert match is not None + return match.group(0) + + +def test_pdfbox_excludes_standalone_commons_logging_provider() -> None: + pom = _pom_text() + pdfbox = _dependency_block(pom, "org.apache.pdfbox", "pdfbox") + + exclusion = re.compile( + r"\s*" + r"commons-logging\s*" + r"commons-logging\s*" + r"" + ) + assert exclusion.search(pdfbox) is not None + + +def test_project_does_not_reintroduce_commons_logging_directly() -> None: + pom = _pom_text() + + direct_commons_logging = re.compile( + r"\s*" + r"commons-logging\s*" + r"commons-logging" + ) + assert direct_commons_logging.search(pom) is None + _dependency_block(pom, "org.springframework.boot", "spring-boot-starter-log4j2") diff --git a/src/test/java/com/clearfolio/viewer/config/CommonsLoggingRuntimeBindingTest.java b/src/test/java/com/clearfolio/viewer/config/CommonsLoggingRuntimeBindingTest.java new file mode 100644 index 00000000..1748203b --- /dev/null +++ b/src/test/java/com/clearfolio/viewer/config/CommonsLoggingRuntimeBindingTest.java @@ -0,0 +1,35 @@ +package com.clearfolio.viewer.config; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URL; +import java.util.Collections; +import java.util.List; +import org.junit.jupiter.api.Test; + +/** + * Verifies that the supported runtime contains exactly one Commons Logging API provider. + */ +final class CommonsLoggingRuntimeBindingTest { + + @Test + void commonsLoggingApiIsProvidedOnlyBySpringJcl() throws Exception { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + List providers = Collections.list( + loader.getResources("org/apache/commons/logging/LogFactory.class")) + .stream() + .map(URL::toExternalForm) + .sorted() + .toList(); + + assertEquals( + 1, + providers.size(), + () -> "Expected one Commons Logging API provider but found: " + providers); + assertTrue( + providers.getFirst().contains("spring-jcl"), + () -> "Expected Spring's spring-jcl bridge to own Commons Logging, but found: " + + providers.getFirst()); + } +}