diff --git a/.gitignore b/.gitignore index d494741e..bdb39dc4 100644 --- a/.gitignore +++ b/.gitignore @@ -208,3 +208,4 @@ gradle-app.setting # node node_modules/ +CLAUDE.md diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 180ef9e3..05b8668f 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "7.0.0" + ".": "7.0.1" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b5d3b0be..5d54395c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ * making Annotations.fieldsAnAnnotations respect inheritance ([3b266dd](https://github.com/mxenabled/path-core/commit/3b266ddcb227766a32f16e88e7b9b2022737de53)) +## [7.0.1](https://github.com/mxenabled/path-core/compare/v7.0.0...v7.0.1) (2026-06-01) + + +### Bug Fixes + +* trigger re-release after vogue hotfix ([3c0dc3f](https://github.com/mxenabled/path-core/commit/3c0dc3f913dbacb7e3477666e2d6e585dfe45696)) + ## [7.0.0](https://github.com/mxenabled/path-core/compare/v6.0.4...v7.0.0) (2026-06-01) diff --git a/README.md b/README.md index dcfbc7da..8fa9b0d9 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ _Gradle_ ```groovy dependencies { - api platform("com.mx.path-core:platform:7.0.0") + api platform("com.mx.path-core:platform:7.0.1") implementation "com.mx.path-core:common" implementation "com.mx.path-core:context" @@ -45,16 +45,16 @@ _Gradle_ ```groovy dependencies { - implementation "com.mx.path-core:common:7.0.0" - implementation "com.mx.path-core:context:7.0.0" - implementation "com.mx.path-core:gateway:7.0.0" - implementation "com.mx.path-core:http:7.0.0" - implementation "com.mx.path-core:messaging:7.0.0" - implementation "com.mx.path-core:utilities:7.0.0" + implementation "com.mx.path-core:common:7.0.1" + implementation "com.mx.path-core:context:7.0.1" + implementation "com.mx.path-core:gateway:7.0.1" + implementation "com.mx.path-core:http:7.0.1" + implementation "com.mx.path-core:messaging:7.0.1" + implementation "com.mx.path-core:utilities:7.0.1" - annotationProcessor "com.mx.path-core:gateway-generator:7.0.0" + annotationProcessor "com.mx.path-core:gateway-generator:7.0.1" - testImplementation "com.mx.path-core:testing:7.0.0" + testImplementation "com.mx.path-core:testing:7.0.1" } ``` diff --git a/build.gradle b/build.gradle index 46d13851..acba5f58 100644 --- a/build.gradle +++ b/build.gradle @@ -8,7 +8,7 @@ plugins { group "com.mx.path-core" description "MX Path Core" -version "7.0.0" // x-release-please-version +version "7.0.1" // x-release-please-version def platformProject = "platform" def publishedProjects = [ diff --git a/common/gradle.lockfile b/common/gradle.lockfile index 2f8393b7..d9d4d443 100644 --- a/common/gradle.lockfile +++ b/common/gradle.lockfile @@ -3,30 +3,31 @@ # This file is expected to be part of source control. com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.rholder:guava-retrying:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs -com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.3=checkstyle -com.google.guava:guava:32.1.3-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.j2objc:j2objc-annotations:3.0.0=checkstyle com.puppycrawl.tools:checkstyle:10.25.0=checkstyle commons-beanutils:commons-beanutils:1.11.0=checkstyle commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs info.picocli:picocli:4.7.7=checkstyle io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -36,27 +37,25 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5:5.1.3=checkstyle org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpcore:4.4.14=checkstyle -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.checkerframework:checker-qual:3.37.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.checkerframework:checker-qual:3.49.3=checkstyle org.checkerframework:checker-qual:3.53.1=pmd org.codehaus.groovy:groovy:3.0.24=testCompileClasspath,testRuntimeClasspath @@ -75,25 +74,27 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=checkstyle org.slf4j:jul-to-slf4j:1.7.36=pmd org.slf4j:slf4j-api:1.7.30=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath org.spockframework:spock-core:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath diff --git a/common/src/main/java/com/mx/path/core/common/connect/Request.java b/common/src/main/java/com/mx/path/core/common/connect/Request.java index f17a666b..53129173 100644 --- a/common/src/main/java/com/mx/path/core/common/connect/Request.java +++ b/common/src/main/java/com/mx/path/core/common/connect/Request.java @@ -567,6 +567,7 @@ public final void setTimeout(Duration timeout) { /** * Called before the request starts. Sets start time. Override to add behavior. Be sure to call {@code super.start()} */ + @SuppressFBWarnings("USO_UNSAFE_METHOD_SYNCHRONIZATION") public synchronized void start() { if (attemptCount < 1) { attemptCount = 1; @@ -579,6 +580,7 @@ public synchronized void start() { /** * Called before retrying request. Sets start time. Override to add behavior. Be sure to call {@code super.startRetry()} */ + @SuppressFBWarnings("USO_UNSAFE_METHOD_SYNCHRONIZATION") public synchronized void startRetry() { attemptCount++; startNano = 0; diff --git a/common/src/test/groovy/com/mx/path/core/common/accessor/AccessorExceptionsTest.groovy b/common/src/test/groovy/com/mx/path/core/common/accessor/AccessorExceptionsTest.groovy new file mode 100644 index 00000000..61d34654 --- /dev/null +++ b/common/src/test/groovy/com/mx/path/core/common/accessor/AccessorExceptionsTest.groovy @@ -0,0 +1,240 @@ +package com.mx.path.core.common.accessor + +import spock.lang.Specification + +class AccessorExceptionsTest extends Specification { + + static class ConcreteSystemException extends AccessorSystemException { + ConcreteSystemException(String message) { + super(message) + } + ConcreteSystemException(String message, Throwable cause) { + super(message, cause) + } + } + + static class ConcreteUserException extends AccessorUserException { + ConcreteUserException(String message, PathResponseStatus status) { + super(message, status) + } + ConcreteUserException(String message, PathResponseStatus status, Throwable cause) { + super(message, status, cause) + } + ConcreteUserException(String message, String userMessage, PathResponseStatus status) { + super(message, userMessage, status) + } + ConcreteUserException(String message, String userMessage, PathResponseStatus status, Throwable cause) { + super(message, userMessage, status, cause) + } + } + + def "AccessorSystemException sets INTERNAL_ERROR status and shouldReport=true"() { + given: + def ex = new ConcreteSystemException("system error") + + expect: + ex.getMessage() == "system error" + ex.getStatus() == PathResponseStatus.INTERNAL_ERROR + ex.shouldReport() + } + + def "AccessorSystemException with cause preserves cause"() { + given: + def cause = new RuntimeException("root") + def ex = new ConcreteSystemException("system error", cause) + + expect: + ex.getCause().is(cause) + ex.getStatus() == PathResponseStatus.INTERNAL_ERROR + ex.shouldReport() + } + + def "AccessorUserException sets status and shouldReport=false"() { + given: + def ex = new ConcreteUserException("user error", PathResponseStatus.NOT_FOUND) + + expect: + ex.getMessage() == "user error" + ex.getStatus() == PathResponseStatus.NOT_FOUND + !ex.shouldReport() + } + + def "AccessorUserException with cause"() { + given: + def cause = new RuntimeException("root") + def ex = new ConcreteUserException("user error", PathResponseStatus.BAD_REQUEST, cause) + + expect: + ex.getCause().is(cause) + !ex.shouldReport() + } + + def "AccessorUserException with userMessage"() { + given: + def ex = new ConcreteUserException("internal msg", "user msg", PathResponseStatus.UNAUTHORIZED) + + expect: + ex.getMessage() == "internal msg" + ex.getUserMessage() == "user msg" + ex.getStatus() == PathResponseStatus.UNAUTHORIZED + } + + def "AccessorUserException with userMessage and cause"() { + given: + def cause = new RuntimeException("root") + def ex = new ConcreteUserException("internal msg", "user msg", PathResponseStatus.UNAUTHORIZED, cause) + + expect: + ex.getCause().is(cause) + ex.getUserMessage() == "user msg" + } + + def "ResourceNotFoundException message constructor"() { + given: + def ex = new ResourceNotFoundException("not found") + + expect: + ex.getStatus() == PathResponseStatus.NOT_FOUND + ex.getMessage() == "not found" + } + + def "ResourceNotFoundException message+cause constructor"() { + given: + def cause = new RuntimeException("root") + def ex = new ResourceNotFoundException("not found", cause) + + expect: + ex.getCause().is(cause) + ex.getStatus() == PathResponseStatus.NOT_FOUND + } + + def "UnauthorizedException constructors"() { + given: + def ex = new UnauthorizedException("unauthorized", "please log in") + + expect: + ex.getStatus() == PathResponseStatus.UNAUTHORIZED + ex.getUserMessage() == "please log in" + } + + def "UnauthorizedException with cause"() { + given: + def cause = new RuntimeException("root") + def ex = new UnauthorizedException("unauthorized", "please log in", cause) + + expect: + ex.getCause().is(cause) + ex.getStatus() == PathResponseStatus.UNAUTHORIZED + } + + def "BadRequestException sets BAD_REQUEST status"() { + given: + def ex = new BadRequestException("bad input") + + expect: + ex.getStatus() == PathResponseStatus.BAD_REQUEST + } + + def "UpstreamResponseError single-arg constructor"() { + given: + def ex = new UpstreamResponseError("upstream error") + + expect: + ex.getMessage() == "upstream error" + ex.shouldReport() + } + + def "UpstreamResponseError with cause"() { + given: + def cause = new RuntimeException("root") + def ex = new UpstreamResponseError("upstream error", cause) + + expect: + ex.getCause().is(cause) + } + + def "RequestValidationException with message"() { + given: + def ex = new RequestValidationException("validation failed") + + expect: + ex.getMessage() == "validation failed" + ex.getStatus() == PathResponseStatus.USER_ERROR + } + + def "RequestValidationException with message and userMessage"() { + given: + def ex = new RequestValidationException("validation failed", "please fix input") + + expect: + ex.getUserMessage() == "please fix input" + } + + def "RequestPayloadException sets shouldReport=true and isInternal=true"() { + given: + def ex = new RequestPayloadException("payload error") + + expect: + ex.getMessage() == "payload error" + ex.shouldReport() + ex.isInternal() + } + + def "ResponsePayloadException sets shouldReport=true and isInternal=true"() { + given: + def ex = new ResponsePayloadException("response error") + + expect: + ex.getMessage() == "response error" + ex.shouldReport() + ex.isInternal() + } + + def "UpstreamResponseProcessingException constructors"() { + given: + def cause = new RuntimeException("root") + + expect: + new UpstreamResponseProcessingException("processing error").getMessage() == "processing error" + new UpstreamResponseProcessingException("processing error", cause).getCause().is(cause) + } + + def "UpstreamResponseValidationException constructors"() { + given: + def cause = new RuntimeException("root") + + expect: + new UpstreamResponseValidationException("validation error").getMessage() == "validation error" + new UpstreamResponseValidationException("validation error", cause).getCause().is(cause) + } + + def "UpstreamSystemUnavailable constructors"() { + given: + def cause = new RuntimeException("root") + + expect: + new UpstreamSystemUnavailable("unavailable").getMessage() == "unavailable" + new UpstreamSystemUnavailable("unavailable", cause).getCause().is(cause) + new UpstreamSystemUnavailable("unavailable", "user msg").getUserMessage() == "user msg" + new UpstreamSystemUnavailable("unavailable", "user msg", cause).getCause().is(cause) + } + + def "UpstreamSystemMaintenance sets errorTitle"() { + given: + def ex = new UpstreamSystemMaintenance("maintenance") + + expect: + ex.getMessage() == "maintenance" + ex.getErrorTitle() == "System under maintenance" + } + + def "UpstreamSystemMaintenance with cause"() { + given: + def cause = new RuntimeException("root") + def ex = new UpstreamSystemMaintenance("maintenance", cause) + + expect: + ex.getCause().is(cause) + ex.getErrorTitle() == "System under maintenance" + } +} diff --git a/common/src/test/groovy/com/mx/path/core/common/connect/ConnectExceptionsTest.groovy b/common/src/test/groovy/com/mx/path/core/common/connect/ConnectExceptionsTest.groovy new file mode 100644 index 00000000..c1017368 --- /dev/null +++ b/common/src/test/groovy/com/mx/path/core/common/connect/ConnectExceptionsTest.groovy @@ -0,0 +1,111 @@ +package com.mx.path.core.common.connect + +import com.mx.path.core.common.accessor.PathResponseStatus + +import spock.lang.Specification + +class ConnectExceptionsTest extends Specification { + + def "ConnectException with message and cause"() { + given: + def cause = new RuntimeException("root") + def ex = new ConnectException("connect failed", cause) + + expect: + ex.getMessage() == "connect failed" + ex.getCause().is(cause) + } + + def "ConnectException with message and status"() { + given: + def ex = new ConnectException("connect failed", PathResponseStatus.UPSTREAM_SERVICE_UNAVAILABLE) + + expect: + ex.getMessage() == "connect failed" + ex.getStatus() == PathResponseStatus.UPSTREAM_SERVICE_UNAVAILABLE + !ex.shouldReport() + } + + def "ConnectException with message, status and cause"() { + given: + def cause = new RuntimeException("root") + def ex = new ConnectException("connect failed", PathResponseStatus.UPSTREAM_SERVICE_UNAVAILABLE, cause) + + expect: + ex.getCause().is(cause) + ex.getStatus() == PathResponseStatus.UPSTREAM_SERVICE_UNAVAILABLE + } + + def "TimeoutException default constructor"() { + given: + def ex = new TimeoutException() + + expect: + ex.getMessage() == "A request timeout occurred" + !ex.shouldReport() + } + + def "TimeoutException with message"() { + given: + def ex = new TimeoutException("timed out after 30s") + + expect: + ex.getMessage() == "timed out after 30s" + !ex.shouldReport() + } + + def "TimeoutException with message and cause"() { + given: + def cause = new RuntimeException("socket timeout") + def ex = new TimeoutException("timed out", cause) + + expect: + ex.getCause().is(cause) + !ex.shouldReport() + } + + def "ServiceUnavailableException with message and cause"() { + given: + def cause = new RuntimeException("connection refused") + def ex = new ServiceUnavailableException("service down", cause) + + expect: + ex.getMessage() == "service down" + ex.getCause().is(cause) + ex.getStatus() == PathResponseStatus.UPSTREAM_SERVICE_UNAVAILABLE + !ex.shouldReport() + } + + def "CircuitOpenException with message and cause"() { + given: + def cause = new RuntimeException("circuit open") + def ex = new CircuitOpenException("circuit is open", cause) + + expect: + ex.getMessage() == "circuit is open" + ex.getCause().is(cause) + ex.isInternal() + } + + def "MisConfiguredFilterChainException default constructor"() { + given: + def ex = new MisConfiguredFilterChainException() + + expect: + ex.getMessage().contains("filterChain is null") + ex.shouldReport() + } + + def "TooManyRequestsException with message and cause"() { + given: + def cause = new RuntimeException("rate limited") + def ex = new TooManyRequestsException("too many requests", cause) + + expect: + ex.getMessage() == "too many requests" + ex.getCause().is(cause) + ex.isInternal() + !ex.shouldReport() + ex.getStatus() == PathResponseStatus.UPSTREAM_SERVICE_UNAVAILABLE + } +} diff --git a/common/src/test/groovy/com/mx/path/core/common/model/ModelBaseTest.groovy b/common/src/test/groovy/com/mx/path/core/common/model/ModelBaseTest.groovy index fa5c428a..0771985e 100644 --- a/common/src/test/groovy/com/mx/path/core/common/model/ModelBaseTest.groovy +++ b/common/src/test/groovy/com/mx/path/core/common/model/ModelBaseTest.groovy @@ -18,4 +18,27 @@ class ModelBaseTest extends Specification { then: metadata != null } + + def "wrapped marks object as wrapped and returns self"() { + when: + def result = subject.wrapped() + + then: + subject.getWrapped() + result.is(subject) + } + + def "setWrapped and getWrapped"() { + when: + subject.setWrapped(true) + + then: + subject.getWrapped() + + when: + subject.setWrapped(false) + + then: + !subject.getWrapped() + } } diff --git a/common/src/test/groovy/com/mx/path/core/common/model/ModelListTest.groovy b/common/src/test/groovy/com/mx/path/core/common/model/ModelListTest.groovy index c9e3e650..7b800289 100644 --- a/common/src/test/groovy/com/mx/path/core/common/model/ModelListTest.groovy +++ b/common/src/test/groovy/com/mx/path/core/common/model/ModelListTest.groovy @@ -9,6 +9,179 @@ class ModelListTest extends Specification { static class ChildTestAccount extends TestAccount {} + def "add, get, size, isEmpty"() { + given: + def list = new ModelList() + + expect: + list.isEmpty() + list.size() == 0 + + when: + list.add(new TestAccount()) + + then: + !list.isEmpty() + list.size() == 1 + list.get(0) != null + } + + def "remove by index and by object"() { + given: + def list = new ModelList() + def account = new TestAccount() + list.add(account) + + when: + def removed = list.remove(0) + + then: + removed.is(account) + list.isEmpty() + + when: + list.add(account) + def result = list.remove(account) + + then: + result + list.isEmpty() + } + + def "contains and containsAll"() { + given: + def account = new TestAccount(id: "acct1") + def other = new TestAccount(id: "acct2") + def list = new ModelList() + list.add(account) + + expect: + list.contains(account) + list.containsAll([account]) + !list.contains(other) + } + + def "addAll, removeAll, retainAll, clear"() { + given: + def a1 = new TestAccount(id: "a1") + def a2 = new TestAccount(id: "a2") + def list = new ModelList() + + when: + list.addAll([a1, a2]) + + then: + list.size() == 2 + + when: + list.removeAll([a1]) + + then: + list.size() == 1 + list.contains(a2) + + when: + list.retainAll([a2]) + + then: + list.size() == 1 + + when: + list.clear() + + then: + list.isEmpty() + } + + def "set, indexOf, lastIndexOf"() { + given: + def a1 = new TestAccount() + def a2 = new TestAccount() + def list = new ModelList() + list.add(a1) + list.add(a1) + + expect: + list.indexOf(a1) == 0 + list.lastIndexOf(a1) == 1 + + when: + list.set(0, a2) + + then: + list.get(0).is(a2) + } + + def "add at index and subList"() { + given: + def a1 = new TestAccount() + def a2 = new TestAccount() + def list = new ModelList() + list.add(a1) + + when: + list.add(0, a2) + + then: + list.get(0).is(a2) + list.get(1).is(a1) + + expect: + list.subList(0, 1).size() == 1 + } + + def "toArray"() { + given: + def list = new ModelList() + list.add(new TestAccount()) + + expect: + list.toArray().length == 1 + list.toArray(new TestAccount[0]).length == 1 + } + + def "iterator and listIterator"() { + given: + def list = new ModelList() + list.add(new TestAccount()) + + expect: + list.iterator().hasNext() + list.listIterator().hasNext() + list.listIterator(0).hasNext() + } + + def "wrapped marks list as wrapped and returns self"() { + given: + def list = new ModelList() + + when: + def result = list.wrapped() + + then: + list.getWrapped() + result.is(list) + } + + def "ofClass returns ModelList class"() { + expect: + ModelList.ofClass(TestAccount) == ModelList + } + + def "addAll at index"() { + given: + def a1 = new TestAccount() + def a2 = new TestAccount() + def list = new ModelList() + list.add(a1) + + when: + list.addAll(0, [a2]) + + then: + list.get(0).is(a2) + } + def "copyConstructor"() { given: def account1 = new ChildTestAccount() diff --git a/common/src/test/groovy/com/mx/path/gateway/configuration/ConfigurationErrorTest.groovy b/common/src/test/groovy/com/mx/path/gateway/configuration/ConfigurationErrorTest.groovy new file mode 100644 index 00000000..fac2ae4c --- /dev/null +++ b/common/src/test/groovy/com/mx/path/gateway/configuration/ConfigurationErrorTest.groovy @@ -0,0 +1,47 @@ +package com.mx.path.gateway.configuration + +import spock.lang.Specification + +class ConfigurationErrorTest extends Specification { + + def "message and field constructor"() { + given: + def ex = new ConfigurationError("missing required", "host") + + expect: + ex.getMessage().contains("missing required") + ex.getMessage().contains("host") + } + + def "message, field and cause constructor"() { + given: + def cause = new RuntimeException("root") + def ex = new ConfigurationError("invalid value", "port", cause) + + expect: + ex.getCause().is(cause) + ex.getMessage().contains("port") + } + + def "message and ConfigurationState constructor"() { + given: + ConfigurationState.resetCurrent() + def state = ConfigurationState.getCurrent() + def ex = new ConfigurationError("bad config", state) + + expect: + ex.getMessage().contains("bad config") + } + + def "message, ConfigurationState and cause constructor"() { + given: + ConfigurationState.resetCurrent() + def state = ConfigurationState.getCurrent() + def cause = new RuntimeException("root") + def ex = new ConfigurationError("bad config", state, cause) + + expect: + ex.getCause().is(cause) + ex.getMessage().contains("bad config") + } +} diff --git a/common/src/test/groovy/com/mx/path/gateway/configuration/ConfigurationStateTest.groovy b/common/src/test/groovy/com/mx/path/gateway/configuration/ConfigurationStateTest.groovy new file mode 100644 index 00000000..d1fb36c4 --- /dev/null +++ b/common/src/test/groovy/com/mx/path/gateway/configuration/ConfigurationStateTest.groovy @@ -0,0 +1,167 @@ +package com.mx.path.gateway.configuration + +import spock.lang.Specification + +class ConfigurationStateTest extends Specification { + + def setup() { + ConfigurationState.resetCurrent() + } + + def "getCurrent returns a singleton instance"() { + expect: + ConfigurationState.getCurrent() != null + ConfigurationState.getCurrent().is(ConfigurationState.getCurrent()) + } + + def "field sets and retrieves the current field name"() { + given: + def state = ConfigurationState.getCurrent() + + when: + state.field("host") + + then: + state.field() == "host" + } + + def "pushLevel and popLevel manage the state stack"() { + given: + def state = ConfigurationState.getCurrent() + + when: + state.pushLevel("client") + state.pushLevel("accessor") + + then: + state.currentState() == "client.accessor" + + when: + state.popLevel() + + then: + state.currentState() == "client" + } + + def "currentState returns empty string when stack is empty"() { + given: + def state = ConfigurationState.getCurrent() + + expect: + state.currentState() == "" + } + + def "withField(Runnable) runs the runnable and resets field"() { + given: + def state = ConfigurationState.getCurrent() + def executed = false + + when: + state.withField("host") { executed = true } + + then: + executed + state.field() == null + } + + def "withField(Runnable) rethrows ConfigurationError unchanged"() { + given: + def state = ConfigurationState.getCurrent() + + when: + state.withField("host") { + throw new ConfigurationError("bad config", "host") + } + + then: + thrown(ConfigurationError) + } + + def "withField(Runnable) wraps other exceptions in ConfigurationError"() { + given: + def state = ConfigurationState.getCurrent() + + when: + state.withField("host") { + throw new RuntimeException("unexpected") + } + + then: + thrown(ConfigurationError) + } + + def "withField(Supplier) returns supplier value and resets field"() { + given: + def state = ConfigurationState.getCurrent() + + when: + def result = state.withField("port", { -> "8080" } as java.util.function.Supplier) + + then: + result == "8080" + state.field() == null + } + + def "withField(Supplier) rethrows ConfigurationError"() { + given: + def state = ConfigurationState.getCurrent() + + when: + state.withField("port", { -> throw new ConfigurationError("invalid", "port") } as java.util.function.Supplier) + + then: + thrown(ConfigurationError) + } + + def "withLevel(Runnable) pushes and pops level"() { + given: + def state = ConfigurationState.getCurrent() + def capturedState = "" + + when: + state.withLevel("client") { + capturedState = state.currentState() + } + + then: + capturedState == "client" + state.currentState() == "" + } + + def "withLevel(Runnable) pops level even on exception"() { + given: + def state = ConfigurationState.getCurrent() + + when: + state.withLevel("client") { + throw new RuntimeException("error") + } + + then: + thrown(ConfigurationError) + state.currentState() == "" + } + + def "withLevel(Supplier) returns value and pops level"() { + given: + def state = ConfigurationState.getCurrent() + + when: + def result = state.withLevel("client", { -> "done" } as java.util.function.Supplier) + + then: + result == "done" + state.currentState() == "" + } + + def "withLevel(Supplier) rethrows ConfigurationError"() { + given: + def state = ConfigurationState.getCurrent() + + when: + state.withLevel("client", { -> throw new ConfigurationError("oops", state) } as java.util.function.Supplier) + + then: + thrown(ConfigurationError) + } +} diff --git a/context/build.gradle b/context/build.gradle index 7c4d2c09..b6292ff8 100644 --- a/context/build.gradle +++ b/context/build.gradle @@ -1,3 +1,9 @@ +coppuccino { + coverage { + minimumCoverage = 0.80 + } +} + dependencies { api project(":utilities") api "com.google.code.gson:gson" diff --git a/context/gradle.lockfile b/context/gradle.lockfile index acf082fe..0c40c2b9 100644 --- a/context/gradle.lockfile +++ b/context/gradle.lockfile @@ -8,34 +8,35 @@ com.fasterxml.jackson.core:jackson-databind:2.21.3=runtimeClasspath,testRuntimeC com.fasterxml.jackson:jackson-bom:2.21.3=runtimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.rholder:guava-retrying:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs -com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.3=checkstyle -com.google.guava:guava:32.1.3-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.j2objc:j2objc-annotations:3.0.0=checkstyle com.puppycrawl.tools:checkstyle:10.25.0=checkstyle commons-beanutils:commons-beanutils:1.11.0=checkstyle commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs info.picocli:picocli:4.7.7=checkstyle io.github.cdimascio:dotenv-java:2.3.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath io.opentracing:opentracing-api:0.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath io.opentracing:opentracing-noop:0.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath io.opentracing:opentracing-util:0.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -45,27 +46,25 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5:5.1.3=checkstyle org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpcore:4.4.14=checkstyle -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.checkerframework:checker-qual:3.37.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.checkerframework:checker-qual:3.49.3=checkstyle org.checkerframework:checker-qual:3.53.1=pmd org.codehaus.groovy:groovy:3.0.24=testCompileClasspath,testRuntimeClasspath @@ -84,25 +83,27 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=runtimeClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=checkstyle org.slf4j:jul-to-slf4j:1.7.36=pmd org.slf4j:slf4j-api:1.7.30=runtimeClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath org.spockframework:spock-core:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath diff --git a/context/src/test/groovy/com/mx/path/core/context/facilities/FacilitiesTest.groovy b/context/src/test/groovy/com/mx/path/core/context/facilities/FacilitiesTest.groovy index 0c03f5fb..8420e08c 100644 --- a/context/src/test/groovy/com/mx/path/core/context/facilities/FacilitiesTest.groovy +++ b/context/src/test/groovy/com/mx/path/core/context/facilities/FacilitiesTest.groovy @@ -1,8 +1,15 @@ package com.mx.path.core.context.facilities +import static org.mockito.Mockito.mock + import com.mx.path.core.common.collection.ObjectMap +import com.mx.path.core.common.exception.ExceptionReporter +import com.mx.path.core.common.messaging.MessageBroker +import com.mx.path.core.common.process.FaultTolerantExecutor +import com.mx.path.core.common.security.EncryptionService import com.mx.path.core.context.facility.Facilities import com.mx.testing.EventBusImpl +import com.mx.testing.StoreImpl import spock.lang.Specification @@ -12,7 +19,103 @@ class FacilitiesTest extends Specification { Facilities.reset() } - def "don't allow eventBus overwrite"() { + def "setCacheStore and getCacheStore"() { + given: + def store = new StoreImpl(new ObjectMap()) + + when: + Facilities.setCacheStore("client1", store) + + then: + Facilities.getCacheStore("client1").is(store) + Facilities.getCacheStore("unknown") == null + } + + def "setEncryptionService and getEncryptionService"() { + given: + def svc = mock(EncryptionService) + + when: + Facilities.setEncryptionService("client1", svc) + + then: + Facilities.getEncryptionService("client1").is(svc) + Facilities.getEncryptionService("unknown") == null + } + + def "setExceptionReporter and getExceptionReporter"() { + given: + def reporter = mock(ExceptionReporter) + + when: + Facilities.setExceptionReporter("client1", reporter) + + then: + Facilities.getExceptionReporter("client1").is(reporter) + Facilities.getExceptionReporter("unknown") == null + } + + def "setFaultTolerantExecutor and getFaultTolerantExecutor"() { + given: + def executor = mock(FaultTolerantExecutor) + + when: + Facilities.setFaultTolerantExecutor("client1", executor) + + then: + Facilities.getFaultTolerantExecutor("client1").is(executor) + Facilities.getFaultTolerantExecutor("unknown") == null + } + + def "setMessageBroker and getMessageBroker"() { + given: + def broker = mock(MessageBroker) + + when: + Facilities.setMessageBroker("client1", broker) + + then: + Facilities.getMessageBroker("client1").is(broker) + Facilities.getMessageBroker("unknown") == null + } + + def "setSecretStore and getSecretStore"() { + given: + def store = new StoreImpl(new ObjectMap()) + + when: + Facilities.setSecretStore("client1", store) + + then: + Facilities.getSecretStore("client1").is(store) + Facilities.getSecretStore("unknown") == null + } + + def "setSessionStore and getSessionStore"() { + given: + def store = new StoreImpl(new ObjectMap()) + + when: + Facilities.setSessionStore("client1", store) + + then: + Facilities.getSessionStore("client1").is(store) + Facilities.getSessionStore("unknown") == null + } + + def "addEventBus and getEventBus"() { + given: + def bus = new EventBusImpl(new ObjectMap()) + + when: + Facilities.addEventBus("client1", bus) + + then: + Facilities.getEventBus("client1").is(bus) + Facilities.getEventBus("unknown") == null + } + + def "addEventBus throws on duplicate client"() { when: Facilities.addEventBus("client1", new EventBusImpl(new ObjectMap())) Facilities.addEventBus("client1", new EventBusImpl(new ObjectMap())) @@ -21,4 +124,68 @@ class FacilitiesTest extends Specification { def ex = thrown(RuntimeException) ex.getMessage() == "Attempting to overwrite GatewayEventBus for client: client1. Only one can be registered. Use #getEventBus()." } + + def "reset clears all facilities"() { + given: + def store = new StoreImpl(new ObjectMap()) + Facilities.setCacheStore("client1", store) + Facilities.setSessionStore("client1", store) + Facilities.setSecretStore("client1", store) + Facilities.addEventBus("client1", new EventBusImpl(new ObjectMap())) + Facilities.setEncryptionService("client1", mock(EncryptionService)) + Facilities.setMessageBroker("client1", mock(MessageBroker)) + + when: + Facilities.reset() + + then: + Facilities.getCacheStore("client1") == null + Facilities.getSessionStore("client1") == null + Facilities.getSecretStore("client1") == null + Facilities.getEventBus("client1") == null + Facilities.getEncryptionService("client1") == null + Facilities.getMessageBroker("client1") == null + } + + def "describe includes configured facilities with getConfigurations"() { + given: + def store = new StoreImpl(new ObjectMap()) + Facilities.setCacheStore("client1", store) + Facilities.setSessionStore("client1", store) + + def description = new ObjectMap() + + when: + Facilities.describe("client1", description) + + then: + description.getMap("cacheStore").get("class") == store.getClass().getCanonicalName() + description.getMap("sessionStore").get("class") == store.getClass().getCanonicalName() + } + + def "describe handles facility without getConfigurations method"() { + given: + // EncryptionService mock does not have getConfigurations, so describeFacility hits the catch branch + def svc = mock(EncryptionService) + Facilities.setEncryptionService("client1", svc) + + def description = new ObjectMap() + + when: + Facilities.describe("client1", description) + + then: + description.getMap("encryptionService").get("configurations") == "no description provided" + } + + def "describe skips null facilities"() { + given: + def description = new ObjectMap() + + when: + Facilities.describe("unknown", description) + + then: + noExceptionThrown() + } } diff --git a/context/src/test/groovy/com/mx/path/core/context/tracing/CustomTracerTest.groovy b/context/src/test/groovy/com/mx/path/core/context/tracing/CustomTracerTest.groovy index 58229eb3..7b39b8fc 100644 --- a/context/src/test/groovy/com/mx/path/core/context/tracing/CustomTracerTest.groovy +++ b/context/src/test/groovy/com/mx/path/core/context/tracing/CustomTracerTest.groovy @@ -57,4 +57,87 @@ class CustomTracerTest extends Specification { null == CustomTracer.getTraceId() null == CustomTracer.getSpanId() } + + def "getSpanContext returns null when tracer is null"() { + given: + CustomTracer.setTracer(null) + + expect: + CustomTracer.getSpanContext() == null + } + + def "startSpan returns span when tracer is set"() { + given: + def builder = mock(Tracer.SpanBuilder) + when(tracer.buildSpan("op")).thenReturn(builder) + when(builder.start()).thenReturn(span) + + when: + def result = CustomTracer.startSpan("op") + + then: + result.is(span) + } + + def "startSpan returns null when tracer is null"() { + given: + CustomTracer.setTracer(null) + + expect: + CustomTracer.startSpan("op") == null + } + + def "startChildSpanFromSpanContext builds child span"() { + given: + def builder = mock(Tracer.SpanBuilder) + when(tracer.buildSpan("child")).thenReturn(builder) + when(builder.asChildOf(context)).thenReturn(builder) + when(builder.start()).thenReturn(span) + + when: + def result = CustomTracer.startChildSpanFromSpanContext("child", context) + + then: + result.is(span) + } + + def "activateSpan delegates to tracer"() { + given: + def scope = mock(io.opentracing.Scope) + when(tracer.activateSpan(span)).thenReturn(scope) + + when: + def result = CustomTracer.activateSpan(span) + + then: + result.is(scope) + } + + def "injectSpanContextIntoHeaders injects when span context present"() { + given: + def headers = [:] + when(span.setTag(io.opentracing.tag.Tags.SPAN_KIND, io.opentracing.tag.Tags.SPAN_KIND_CLIENT)).thenReturn(span) + when(span.context()).thenReturn(context) + + when: + CustomTracer.injectSpanContextIntoHeaders(headers) + + then: + noExceptionThrown() + } + + def "injectSpanContextIntoHeaders skips when no span context"() { + given: + when(tracer.activeSpan()).thenReturn(null) + + when: + CustomTracer.injectSpanContextIntoHeaders([:]) + + then: + noExceptionThrown() + } + + def cleanup() { + CustomTracer.setTracer(null) + } } diff --git a/context/src/test/groovy/com/mx/path/core/context/tracing/HttpHeadersCarrierTest.groovy b/context/src/test/groovy/com/mx/path/core/context/tracing/HttpHeadersCarrierTest.groovy new file mode 100644 index 00000000..67c49251 --- /dev/null +++ b/context/src/test/groovy/com/mx/path/core/context/tracing/HttpHeadersCarrierTest.groovy @@ -0,0 +1,31 @@ +package com.mx.path.core.context.tracing + +import com.mx.path.core.context.tracing.HttpHeadersCarrier + +import spock.lang.Specification + +class HttpHeadersCarrierTest extends Specification { + + def "put adds entry to headers map"() { + given: + def headers = [:] + def carrier = new HttpHeadersCarrier(headers) + + when: + carrier.put("X-Trace-Id", "abc123") + + then: + headers["X-Trace-Id"] == "abc123" + } + + def "iterator throws UnsupportedOperationException"() { + given: + def carrier = new HttpHeadersCarrier([:]) + + when: + carrier.iterator() + + then: + thrown(UnsupportedOperationException) + } +} diff --git a/context/src/test/groovy/com/mx/path/core/context/util/XMLGregorianCalendarConverterTest.groovy b/context/src/test/groovy/com/mx/path/core/context/util/XMLGregorianCalendarConverterTest.groovy new file mode 100644 index 00000000..d8c0f41d --- /dev/null +++ b/context/src/test/groovy/com/mx/path/core/context/util/XMLGregorianCalendarConverterTest.groovy @@ -0,0 +1,56 @@ +package com.mx.path.core.context.util + +import javax.xml.datatype.XMLGregorianCalendar + +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.mx.path.core.context.util.XMLGregorianCalendarConverter + +import spock.lang.Specification + +class XMLGregorianCalendarConverterTest extends Specification { + Gson gson + + def setup() { + gson = new GsonBuilder() + .registerTypeAdapter(XMLGregorianCalendar, new XMLGregorianCalendarConverter.Serializer()) + .registerTypeAdapter(XMLGregorianCalendar, new XMLGregorianCalendarConverter.Deserializer()) + .create() + } + + def "serialize produces XML format string"() { + given: + def cal = javax.xml.datatype.DatatypeFactory.newInstance().newXMLGregorianCalendar("2024-01-15") + + when: + def json = gson.toJson(cal, XMLGregorianCalendar) + + then: + json == '"2024-01-15"' + } + + def "deserialize parses XML format string back to calendar"() { + given: + def json = '"2024-01-15"' + + when: + def cal = gson.fromJson(json, XMLGregorianCalendar) + + then: + cal != null + cal.year == 2024 + cal.month == 1 + cal.day == 15 + } + + def "deserialize returns null for invalid format"() { + given: + def json = '"not-a-date"' + + when: + def cal = gson.fromJson(json, XMLGregorianCalendar) + + then: + cal == null + } +} diff --git a/gateway-generator/build.gradle b/gateway-generator/build.gradle index 37f7ef98..564d210f 100644 --- a/gateway-generator/build.gradle +++ b/gateway-generator/build.gradle @@ -1,3 +1,13 @@ +coppuccino { + coverage { + excludes = [ + // Annotation processor code is tested via :test-gateway-generator and is not directly + // instrumentable by JaCoCo because it runs at compile time rather than test runtime. + "com/mx/path/api/**" + ] + } +} + dependencies { implementation project(":gateway") diff --git a/gateway-generator/gradle.lockfile b/gateway-generator/gradle.lockfile index 860377d3..208e57ca 100644 --- a/gateway-generator/gradle.lockfile +++ b/gateway-generator/gradle.lockfile @@ -9,26 +9,26 @@ com.fasterxml.jackson.core:jackson-databind:2.21.3=runtimeClasspath,testRuntimeC com.fasterxml.jackson:jackson-bom:2.21.3=runtimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.rholder:guava-retrying:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.auto.service:auto-service-annotations:1.1.1=annotationProcessor,compileClasspath com.google.auto.service:auto-service:1.1.1=annotationProcessor,compileClasspath com.google.auto:auto-common:1.2.1=annotationProcessor,compileClasspath com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs -com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.18.0=annotationProcessor com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.3=checkstyle -com.google.guava:guava:32.0.1-jre=annotationProcessor,compileClasspath -com.google.guava:guava:32.1.3-jre=runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=annotationProcessor,compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.j2objc:j2objc-annotations:3.0.0=checkstyle com.puppycrawl.tools:checkstyle:10.25.0=checkstyle com.squareup:javapoet:1.13.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath @@ -39,7 +39,7 @@ commons-beanutils:commons-beanutils:1.11.0=checkstyle commons-codec:commons-codec:1.14=runtimeClasspath,testRuntimeClasspath commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs commons-logging:commons-logging:1.2=runtimeClasspath,testRuntimeClasspath info.picocli:picocli:4.7.7=checkstyle io.github.cdimascio:dotenv-java:2.3.2=runtimeClasspath,testRuntimeClasspath @@ -50,7 +50,7 @@ io.opentracing:opentracing-util:0.33.0=compileClasspath,runtimeClasspath,testCom jakarta.activation:jakarta.activation-api:2.1.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.soap:jakarta.xml.soap-api:3.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -60,12 +60,10 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle @@ -74,16 +72,15 @@ org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpclient:4.5.14=runtimeClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.14=checkstyle org.apache.httpcomponents:httpcore:4.4.16=runtimeClasspath,testRuntimeClasspath -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.checkerframework:checker-qual:3.33.0=annotationProcessor,compileClasspath -org.checkerframework:checker-qual:3.37.0=runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.checkerframework:checker-qual:3.49.3=checkstyle org.checkerframework:checker-qual:3.53.1=pmd org.codehaus.groovy:groovy:3.0.24=testCompileClasspath,testRuntimeClasspath @@ -106,25 +103,27 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=runtimeClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=checkstyle,runtimeClasspath,testRuntimeClasspath org.slf4j:jul-to-slf4j:1.7.36=pmd org.slf4j:slf4j-api:1.7.32=runtimeClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath org.spockframework:spock-core:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath diff --git a/gateway/gradle.lockfile b/gateway/gradle.lockfile index 6ce195dd..c17f0c6e 100644 --- a/gateway/gradle.lockfile +++ b/gateway/gradle.lockfile @@ -9,21 +9,22 @@ com.fasterxml.jackson.core:jackson-databind:2.21.3=runtimeClasspath,testRuntimeC com.fasterxml.jackson:jackson-bom:2.21.3=runtimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.rholder:guava-retrying:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs -com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.3=checkstyle -com.google.guava:guava:32.1.3-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.j2objc:j2objc-annotations:3.0.0=checkstyle com.puppycrawl.tools:checkstyle:10.25.0=checkstyle com.sun.istack:istack-commons-runtime:4.1.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath @@ -33,7 +34,7 @@ commons-beanutils:commons-beanutils:1.11.0=checkstyle commons-codec:commons-codec:1.14=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs commons-logging:commons-logging:1.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath info.picocli:picocli:4.7.7=checkstyle io.github.cdimascio:dotenv-java:2.3.2=runtimeClasspath,testRuntimeClasspath @@ -45,7 +46,7 @@ io.opentracing:opentracing-util:0.33.0=compileClasspath,runtimeClasspath,testCom jakarta.activation:jakarta.activation-api:2.1.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.soap:jakarta.xml.soap-api:3.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -55,12 +56,10 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle @@ -69,15 +68,15 @@ org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.14=checkstyle org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.checkerframework:checker-qual:3.37.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.checkerframework:checker-qual:3.49.3=checkstyle org.checkerframework:checker-qual:3.53.1=pmd org.codehaus.groovy:groovy:3.0.24=testCompileClasspath,testRuntimeClasspath @@ -100,25 +99,27 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=runtimeClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.slf4j:jul-to-slf4j:1.7.36=pmd org.slf4j:slf4j-api:1.7.32=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:1.7.30=testCompileClasspath,testRuntimeClasspath org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath diff --git a/gateway/src/test/groovy/com/mx/path/gateway/GatewayBuilderHelperTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/GatewayBuilderHelperTest.groovy new file mode 100644 index 00000000..e534352d --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/GatewayBuilderHelperTest.groovy @@ -0,0 +1,83 @@ +package com.mx.path.gateway + +import com.mx.path.core.common.collection.ObjectMap +import com.mx.path.gateway.accessor.AccessorResponse +import com.mx.path.gateway.behavior.GatewayBehavior +import com.mx.path.gateway.context.GatewayRequestContext +import com.mx.path.gateway.service.GatewayService +import com.mx.testing.MinimalAccessor +import com.mx.testing.gateway.MinimalGateway + +import spock.lang.Specification + +class GatewayBuilderHelperTest extends Specification { + + def "getBuilder returns a builder for the given class"() { + when: + def builder = GatewayBuilderHelper.getBuilder(MinimalGateway) + + then: + builder != null + } + + def "setRootAccessor sets the base accessor on the builder"() { + given: + def builder = GatewayBuilderHelper.getBuilder(MinimalGateway) + def accessor = new MinimalAccessor() + + when: + GatewayBuilderHelper.setRootAccessor(builder, accessor) + def gateway = GatewayBuilderHelper.build(builder, MinimalGateway) + + then: + gateway.getBaseAccessor().is(accessor) + } + + def "setClientId sets the client id on the builder"() { + given: + def builder = GatewayBuilderHelper.getBuilder(MinimalGateway) + GatewayBuilderHelper.setRootAccessor(builder, new MinimalAccessor()) + + when: + GatewayBuilderHelper.setClientId(builder, "client1") + def gateway = GatewayBuilderHelper.build(builder, MinimalGateway) + + then: + gateway.getClientId() == "client1" + } + + def "addBehavior adds a behavior to the builder"() { + given: + def builder = GatewayBuilderHelper.getBuilder(MinimalGateway) + GatewayBuilderHelper.setRootAccessor(builder, new MinimalAccessor()) + def behavior = new GatewayBehavior(new ObjectMap()) { + protected AccessorResponse call(Class r, GatewayRequestContext req, GatewayBehavior t) { + new AccessorResponse() + } + } + + when: + GatewayBuilderHelper.addBehavior(builder, behavior) + def gateway = GatewayBuilderHelper.build(builder, MinimalGateway) + + then: + gateway.getBehaviors().size() == 1 + } + + def "addService adds a service to the builder"() { + given: + def builder = GatewayBuilderHelper.getBuilder(MinimalGateway) + GatewayBuilderHelper.setRootAccessor(builder, new MinimalAccessor()) + def service = new GatewayService(new ObjectMap()) { + void start() {} + void stop() {} + } + + when: + GatewayBuilderHelper.addService(builder, service) + def gateway = GatewayBuilderHelper.build(builder, MinimalGateway) + + then: + gateway.getServices().size() == 1 + } +} diff --git a/gateway/src/test/groovy/com/mx/path/gateway/GatewayTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/GatewayTest.groovy new file mode 100644 index 00000000..01d66c5e --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/GatewayTest.groovy @@ -0,0 +1,303 @@ +package com.mx.path.gateway + +import com.mx.path.core.common.collection.ObjectMap +import com.mx.path.core.common.event.EventBus +import com.mx.path.core.context.RequestContext +import com.mx.path.core.context.facility.Facilities +import com.mx.path.gateway.accessor.AccessorResponse +import com.mx.path.gateway.behavior.GatewayBehavior +import com.mx.path.gateway.behavior.StartBehavior +import com.mx.path.gateway.context.GatewayRequestContext +import com.mx.path.gateway.service.GatewayService +import com.mx.testing.MinimalAccessor +import com.mx.testing.gateway.MinimalGateway +import com.mx.testing.gateway.MinimalRootGateway + +import spock.lang.Specification + +class GatewayTest extends Specification { + + def "isTopLevel returns true for @RootGateway annotated gateway"() { + given: + def gateway = MinimalRootGateway.builder().baseAccessor(new MinimalAccessor()).build() + + expect: + gateway.isTopLevel() + } + + def "isTopLevel returns false for plain gateway"() { + given: + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + + expect: + !gateway.isTopLevel() + } + + def "constructor sets clientId"() { + given: + def gateway = new MinimalGateway("client42") + + expect: + gateway.getClientId() == "client42" + } + + def "gateways returns empty list when no child gateway methods exist"() { + given: + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + + expect: + gateway.gateways().isEmpty() + } + + def "describe(ObjectMap) fills provided map without error"() { + given: + def gateway = MinimalGateway.builder() + .baseAccessor(new MinimalAccessor()) + .clientId("testClient") + .build() + def description = new ObjectMap() + + when: + gateway.describe(description) + + then: + noExceptionThrown() + } + + def "describe() returns an ObjectMap"() { + given: + def gateway = MinimalGateway.builder() + .baseAccessor(new MinimalAccessor()) + .clientId("testClient") + .build() + + when: + def result = gateway.describe() + + then: + result != null + } + + def "startServices starts each service and sets gateway back-reference"() { + given: + def started = [] + def service = new GatewayService(new ObjectMap()) { + void start() { + started << "started" + } + void stop() {} + } + def gateway = MinimalGateway.builder() + .baseAccessor(new MinimalAccessor()) + .service(service) + .build() + + when: + gateway.startServices() + + then: + started == ["started"] + service.getGateway().is(gateway) + } + + def "registerRemotes runs without error when remote is null"() { + given: + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + + when: + gateway.registerRemotes() + + then: + noExceptionThrown() + } + + def "builder allows adding behaviors"() { + given: + def behavior = new GatewayBehavior(new ObjectMap()) { + protected AccessorResponse call(Class r, GatewayRequestContext req, GatewayBehavior t) { + new AccessorResponse() + } + } + def gateway = MinimalGateway.builder() + .baseAccessor(new MinimalAccessor()) + .behavior(behavior) + .build() + + expect: + gateway.getBehaviors().size() == 1 + } + + def "setParent and getParent"() { + given: + def parent = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + def child = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + + when: + child.setParent(parent) + + then: + noExceptionThrown() + } + + def "root() returns self when @RootGateway and no parent"() { + given: + def gateway = MinimalRootGateway.builder().baseAccessor(new MinimalAccessor()).build() + + expect: + gateway.root().is(gateway) + } + + def "root() returns null when not @RootGateway and no parent"() { + given: + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + + expect: + gateway.root() == null + } + + def "root() delegates to parent"() { + given: + def root = MinimalRootGateway.builder().baseAccessor(new MinimalAccessor()).build() + def child = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + child.setParent(root) + + expect: + child.root().is(root) + } + + def "afterAccessor does nothing when clientId is null"() { + given: + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + def context = RequestContext.builder().build() + + when: + gateway.afterAccessor(gateway, new MinimalAccessor(), context) + + then: + noExceptionThrown() + } + + def "beforeAccessor does nothing when no EventBus configured"() { + given: + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + def context = RequestContext.builder().clientId("client1").build() + + when: + gateway.beforeAccessor(gateway, new MinimalAccessor(), context) + + then: + noExceptionThrown() + + cleanup: + Facilities.reset() + } + + def "buildStack via reflection returns a StartBehavior"() { + given: + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + def buildStackMethod = Gateway.getDeclaredMethod("buildStack") + buildStackMethod.setAccessible(true) + + when: + def stack = buildStackMethod.invoke(gateway) + + then: + stack instanceof StartBehavior + } + + def "describe() for root gateway with clientId covers the isTopLevel branch"() { + given: + def gateway = MinimalRootGateway.builder() + .baseAccessor(new MinimalAccessor()) + .clientId("client1") + .build() + + when: + def desc = gateway.describe() + + then: + noExceptionThrown() + desc != null + + cleanup: + Facilities.reset() + } + + def "describe() throws when baseAccessor is null on non-root gateway"() { + given: + def gateway = new MinimalGateway() // no-arg constructor, baseAccessor is null + + when: + gateway.describe() + + then: + thrown(RuntimeException) + } + + def "afterAccessor fires event when EventBus is present"() { + given: + def postedEvents = [] + def eventBus = new EventBus() { + ObjectMap configurations = new ObjectMap() + void post(Object event) { + postedEvents << event + } + void register(Object subscriber) {} + } + def context = RequestContext.builder().clientId("client1").build() + Facilities.addEventBus("client1", eventBus) + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + + when: + gateway.afterAccessor(gateway, new MinimalAccessor(), context) + + then: + postedEvents.size() == 1 + + cleanup: + Facilities.reset() + } + + def "beforeAccessor fires event when EventBus is present"() { + given: + def postedEvents = [] + def eventBus = new EventBus() { + ObjectMap configurations = new ObjectMap() + void post(Object event) { + postedEvents << event + } + void register(Object subscriber) {} + } + def context = RequestContext.builder().clientId("client1").build() + Facilities.addEventBus("client1", eventBus) + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + + when: + gateway.beforeAccessor(gateway, new MinimalAccessor(), context) + + then: + postedEvents.size() == 1 + + cleanup: + Facilities.reset() + } + + def "executeBehaviorStack executes the behavior chain"() { + given: + def gateway = MinimalGateway.builder().baseAccessor(new MinimalAccessor()).build() + def terminal = new GatewayBehavior(new ObjectMap()) { + protected AccessorResponse call(Class r, GatewayRequestContext req, GatewayBehavior t) { + new AccessorResponse() + } + } + def req = GatewayRequestContext.builder().build() + def execMethod = Gateway.getDeclaredMethod("executeBehaviorStack", Class, GatewayRequestContext, GatewayBehavior) + execMethod.setAccessible(true) + + when: + def result = execMethod.invoke(gateway, String, req, terminal) + + then: + result != null + } +} diff --git a/gateway/src/test/groovy/com/mx/path/gateway/accessor/AccessorConnectionBaseTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/accessor/AccessorConnectionBaseTest.groovy new file mode 100644 index 00000000..6fd336e9 --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/accessor/AccessorConnectionBaseTest.groovy @@ -0,0 +1,89 @@ +package com.mx.path.gateway.accessor + +import com.mx.path.core.common.connect.Request +import com.mx.path.core.common.connect.RequestFilter +import com.mx.path.core.common.connect.RequestFilterBase +import com.mx.path.core.common.connect.Response + +import spock.lang.Specification + +class AccessorConnectionBaseTest extends Specification { + + static class NoOpFilter extends RequestFilterBase { + boolean executed = false + @Override + void execute(Request request, Response response) { + executed = true + } + } + + static class ConcreteConnection extends AccessorConnectionBase { + List extraFilters = [] + + @Override + List connectionRequestFilters() { + [new NoOpFilter()] + } + + @Override + Object request(String path) { + null + } + + @Override + void preprocessFilterChain(List filters) { + filters.addAll(extraFilters) + } + } + + def "buildFilterChain constructs a linked filter chain"() { + given: + def connection = new ConcreteConnection() + def baseFilter = new NoOpFilter() + connection.setBaseRequestFilters([baseFilter]) + + when: + def chain = connection.buildFilterChain() + + then: + chain != null + chain.is(baseFilter) + baseFilter.getNext() instanceof NoOpFilter + } + + def "buildFilterChain caches result on repeated calls"() { + given: + def connection = new ConcreteConnection() + + when: + def chain1 = connection.buildFilterChain() + def chain2 = connection.buildFilterChain() + + then: + chain1.is(chain2) + } + + def "buildFilterChain calls preprocessFilterChain to allow modification"() { + given: + def extraFilter = new NoOpFilter() + def connection = new ConcreteConnection(extraFilters: [extraFilter]) + + when: + connection.buildFilterChain() + + then: + noExceptionThrown() + } + + def "buildFilterChain works with no base filters"() { + given: + def connection = new ConcreteConnection() + connection.setBaseRequestFilters(null) + + when: + def chain = connection.buildFilterChain() + + then: + chain instanceof NoOpFilter + } +} diff --git a/gateway/src/test/groovy/com/mx/path/gateway/accessor/AccessorResponseTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/accessor/AccessorResponseTest.groovy new file mode 100644 index 00000000..172410e2 --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/accessor/AccessorResponseTest.groovy @@ -0,0 +1,96 @@ +package com.mx.path.gateway.accessor + +import com.mx.path.core.common.accessor.PathResponseStatus +import com.mx.path.gateway.accessor.AccessorResponse + +import spock.lang.Specification + +class AccessorResponseTest extends Specification { + + def "withResult sets result and returns self"() { + given: + def response = new AccessorResponse() + + when: + def returned = response.withResult("hello") + + then: + response.getResult() == "hello" + returned.is(response) + } + + def "withStatus sets status and returns self"() { + given: + def response = new AccessorResponse() + + when: + def returned = response.withStatus(PathResponseStatus.OK) + + then: + response.getStatus() == PathResponseStatus.OK + returned.is(response) + } + + def "withException sets exception and returns self"() { + given: + def response = new AccessorResponse() + def ex = new RuntimeException("boom") + + when: + def returned = response.withException(ex) + + then: + response.getException().is(ex) + returned.is(response) + } + + def "withHeader adds header and returns self"() { + given: + def response = new AccessorResponse() + + when: + def returned = response.withHeader("X-Custom", "value") + + then: + response.getHeaders()["X-Custom"] == "value" + returned.is(response) + } + + def "withMetadata adds metadata and returns self"() { + given: + def response = new AccessorResponse() + + when: + def returned = response.withMetadata("key", "data") + + then: + response.getMetadata().get("key") == "data" + returned.is(response) + } + + def "chaining multiple withs"() { + when: + def response = new AccessorResponse() + .withResult("result") + .withStatus(PathResponseStatus.OK) + .withHeader("X-A", "1") + .withMetadata("m", "v") + + then: + response.getResult() == "result" + response.getStatus() == PathResponseStatus.OK + response.getHeaders()["X-A"] == "1" + response.getMetadata().get("m") == "v" + } + + def "default constructor leaves fields null"() { + when: + def response = new AccessorResponse() + + then: + response.getResult() == null + response.getStatus() == null + response.getException() == null + response.getHeaders().isEmpty() + } +} diff --git a/gateway/src/test/groovy/com/mx/path/gateway/accessor/AccessorTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/accessor/AccessorTest.groovy new file mode 100644 index 00000000..33ef6ad1 --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/accessor/AccessorTest.groovy @@ -0,0 +1,177 @@ +package com.mx.path.gateway.accessor + +import com.mx.path.core.common.accessor.BadRequestException +import com.mx.path.core.common.collection.ObjectMap +import com.mx.path.gateway.accessor.Accessor +import com.mx.path.gateway.accessor.AccessorConfiguration +import com.mx.path.gateway.accessor.AccessorConnections +import com.mx.testing.BaseAccessorImpl + +import spock.lang.Specification + +class AccessorTest extends Specification { + + static class ConcreteAccessor extends Accessor { + } + + // Subclass that calls the deprecated super(config) constructor + static class ConfiguredAccessor extends Accessor { + ConfiguredAccessor(AccessorConfiguration config) { + super(config) + } + } + + def "getChildAccessors returns empty list when no @API child methods"() { + given: + def accessor = new ConcreteAccessor() + + expect: + accessor.getChildAccessors().isEmpty() + } + + def "getChildAccessors succeeds and returns entries when @API methods return accessors"() { + given: + def accessor = new BaseAccessorImpl() + + when: + def result = accessor.getChildAccessors() + + then: + !result.isEmpty() + } + + def "getChildAccessors ignores methods that throw NOT_IMPLEMENTED AccessorException"() { + given: + // BaseAccessor.accounts() throws AccessorMethodNotImplementedException (NOT_IMPLEMENTED status) + // when no accounts accessor is set — our overriding subclass does this path + def accessor = new BaseAccessorImpl() { + @Override + com.mx.testing.accessors.AccountBaseAccessor accounts() { + throw new com.mx.path.core.common.accessor.AccessorMethodNotImplementedException() + } + } + + when: + def result = accessor.getChildAccessors() + + then: + noExceptionThrown() + } + + def "getChildAccessors logs when method throws non-NOT_IMPLEMENTED AccessorException"() { + given: + // BadRequestException has status BAD_REQUEST, not NOT_IMPLEMENTED + def accessor = new BaseAccessorImpl() { + @Override + com.mx.testing.accessors.AccountBaseAccessor accounts() { + throw new BadRequestException("unexpected error") + } + } + + when: + def result = accessor.getChildAccessors() + + then: + noExceptionThrown() + } + + def "getAccessorBase returns the direct Accessor subclass"() { + expect: + Accessor.getAccessorBase(ConcreteAccessor) == ConcreteAccessor + } + + def "getBaseChildAccessorMethods returns empty for simple accessor"() { + expect: + Accessor.getBaseChildAccessorMethods(ConcreteAccessor).isEmpty() + } + + def "getBaseChildAccessorMethods returns @API methods from base"() { + when: + def methods = Accessor.getBaseChildAccessorMethods(BaseAccessorImpl) + + then: + !methods.isEmpty() + } + + def "deprecated constructor sets configuration"() { + given: + def config = AccessorConfiguration.builder().clientId("c1").configurations(new ObjectMap()).build() + + when: + def accessor = new ConfiguredAccessor(config) + + then: + accessor.getConfiguration().is(config) + } + + def "AccessorConnections add and get connection"() { + given: + def connections = new AccessorConnections() + def settings = new com.mx.path.core.common.connect.AccessorConnectionSettings() + + when: + connections.addConnection("primary", settings) + + then: + connections.getConnection("primary").is(settings) + connections.getConnection("missing") == null + } + + def "AccessorConfiguration builder with connection and configuration helpers"() { + given: + def settings = new com.mx.path.core.common.connect.AccessorConnectionSettings() + + when: + def config = AccessorConfiguration.builder() + .clientId("client1") + .connection("primary", settings) + .configuration("timeout", "30") + .build() + + then: + config.getClientId() == "client1" + config.getConnections().getConnection("primary").is(settings) + config.getConfigurations().get("timeout") == "30" + } + + def "AccessorConfiguration.describe() returns populated ObjectMap"() { + given: + def config = AccessorConfiguration.builder() + .clientId("client1") + .configuration("host", "localhost") + .build() + + when: + def desc = config.describe() + + then: + desc.get("clientId") == "client1" + desc.containsKey("configurations") + } + + def "AccessorConfiguration.describe(ObjectMap) fills provided map"() { + given: + def config = AccessorConfiguration.builder() + .clientId("client2") + .build() + def description = new ObjectMap() + + when: + config.describe(description) + + then: + description.get("clientId") == "client2" + } + + def "setConfiguration and getConfiguration round-trip"() { + given: + def accessor = new ConcreteAccessor() + def config = AccessorConfiguration.builder().clientId("c1").configurations(new ObjectMap()).build() + + when: + accessor.setConfiguration(config) + + then: + accessor.getConfiguration().is(config) + } +} diff --git a/gateway/src/test/groovy/com/mx/path/gateway/behavior/GatewayBehaviorTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/behavior/GatewayBehaviorTest.groovy new file mode 100644 index 00000000..f2570aa9 --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/behavior/GatewayBehaviorTest.groovy @@ -0,0 +1,158 @@ +package com.mx.path.gateway.behavior + +import com.mx.path.core.common.collection.ObjectMap +import com.mx.path.gateway.accessor.AccessorResponse +import com.mx.path.gateway.context.GatewayRequestContext + +import spock.lang.Specification + +class GatewayBehaviorTest extends Specification { + + // Minimal concrete behavior that records calls and delegates to callNext + static class PassThroughBehavior extends GatewayBehavior { + boolean called = false + + PassThroughBehavior(ObjectMap configs = new ObjectMap()) { + super(configs) + } + + @Override + protected AccessorResponse call(Class resultType, GatewayRequestContext request, GatewayBehavior terminatingBehavior) { + called = true + callNext(resultType, request, terminatingBehavior) + } + } + + // Terminal behavior that returns a canned response + static class TerminalBehavior extends GatewayBehavior { + TerminalBehavior() { + super(new ObjectMap()) + } + + @Override + protected AccessorResponse call(Class resultType, GatewayRequestContext request, GatewayBehavior terminatingBehavior) { + new AccessorResponse().withResult(null) + } + } + + def request = GatewayRequestContext.builder().build() + + def "execute delegates to call"() { + given: + def behavior = new PassThroughBehavior() + def terminal = new TerminalBehavior() + + when: + behavior.execute(String, request, terminal) + + then: + behavior.called + } + + def "callNext invokes nextBehavior when set"() { + given: + def first = new PassThroughBehavior() + def second = new PassThroughBehavior() + def terminal = new TerminalBehavior() + first.setNextBehavior(second) + + when: + first.execute(String, request, terminal) + + then: + first.called + second.called + } + + def "callNext falls through to terminatingBehavior when nextBehavior is null"() { + given: + def behavior = new PassThroughBehavior() + def terminal = new TerminalBehavior() + + when: + def response = behavior.execute(String, request, terminal) + + then: + response != null + behavior.getNextBehavior() == null + } + + def "describe returns class name"() { + given: + def behavior = new PassThroughBehavior() + + when: + def desc = behavior.describe() + + then: + desc.get("class") == "PassThroughBehavior" + } + + def "describe includes configurations when non-empty"() { + given: + def configs = new ObjectMap() + configs.put("key", "value") + def behavior = new PassThroughBehavior(configs) + + when: + def desc = behavior.describe() + + then: + desc.containsKey("configurations") + } + + def "describe omits configurations when empty"() { + given: + def behavior = new PassThroughBehavior(new ObjectMap()) + + when: + def desc = behavior.describe() + + then: + !desc.containsKey("configurations") + } + + def "BlockBehavior executes block function"() { + given: + def called = false + def behavior = new BlockBehavior({ req -> + called = true + new AccessorResponse() + }) + def terminal = new TerminalBehavior() + + when: + behavior.execute(String, request, terminal) + + then: + called + } + + def "BlockBehavior with configurations"() { + given: + def configs = new ObjectMap() + configs.put("k", "v") + def behavior = new BlockBehavior(configs, { req -> new AccessorResponse() }) + + when: + def response = behavior.execute(String, request, new TerminalBehavior()) + + then: + response != null + behavior.getConfigurations().get("k") == "v" + } + + def "StartBehavior delegates to callNext"() { + given: + def start = new StartBehavior() + def next = new PassThroughBehavior() + def terminal = new TerminalBehavior() + start.setNextBehavior(next) + + when: + start.execute(String, request, terminal) + + then: + next.called + } +} diff --git a/gateway/src/test/groovy/com/mx/path/gateway/configuration/annotations/AccessorScopeTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/configuration/annotations/AccessorScopeTest.groovy new file mode 100644 index 00000000..78b86ad7 --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/configuration/annotations/AccessorScopeTest.groovy @@ -0,0 +1,37 @@ +package com.mx.path.gateway.configuration.annotations + +import spock.lang.Specification + +class AccessorScopeTest extends Specification { + + def "enum constants have expected name and value"() { + expect: + AccessorScope.SINGLETON.getName() == "singleton" + AccessorScope.SINGLETON.getValue() == 3 + AccessorScope.PROTOTYPE.getName() == "prototype" + AccessorScope.PROTOTYPE.getValue() == 1 + } + + def "resolve(int) returns matching scope"() { + expect: + AccessorScope.resolve(3) == AccessorScope.SINGLETON + AccessorScope.resolve(1) == AccessorScope.PROTOTYPE + } + + def "resolve(int) returns null for unknown value"() { + expect: + AccessorScope.resolve(99) == null + } + + def "resolve(String) returns matching scope"() { + expect: + AccessorScope.resolve("singleton") == AccessorScope.SINGLETON + AccessorScope.resolve("prototype") == AccessorScope.PROTOTYPE + } + + def "resolve(String) returns null for unknown name"() { + expect: + AccessorScope.resolve("unknown") == null + AccessorScope.resolve(null) == null + } +} diff --git a/gateway/src/test/groovy/com/mx/path/gateway/connect/filter/FilterTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/connect/filter/FilterTest.groovy new file mode 100644 index 00000000..509d3e3f --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/connect/filter/FilterTest.groovy @@ -0,0 +1,252 @@ +package com.mx.path.gateway.connect.filter + +import static org.mockito.Mockito.mock +import static org.mockito.Mockito.verify +import static org.mockito.Mockito.when + +import com.mx.path.core.common.accessor.PathResponseStatus +import com.mx.path.core.common.collection.ObjectMap +import com.mx.path.core.common.connect.Request +import com.mx.path.core.common.connect.RequestFilterBase +import com.mx.path.core.common.connect.Response +import com.mx.path.core.context.RequestContext +import com.mx.path.core.context.facility.Facilities +import com.mx.testing.FaultTolerantExecutorImpl + +import spock.lang.Specification + +class FilterTest extends Specification { + + // Terminal no-op next filter + static class NoOpFilter extends RequestFilterBase { + @Override + void execute(Request request, Response response) { + } + } + + def "HttpClientConnectException sets status and report=true"() { + given: + def cause = new RuntimeException("timeout") + def ex = new HttpClientConnectException("connection timeout", cause) + + expect: + ex.getMessage() == "connection timeout" + ex.getCause().is(cause) + ex.getStatus() == PathResponseStatus.UPSTREAM_SERVICE_UNAVAILABLE + ex.shouldReport() + } + + def "CallbacksFilter invokes next and fires callbacks"() { + given: + def request = mock(Request) + def response = mock(Response) + def processResult = new Object() + + when(request.process(response)).thenReturn(processResult) + + def filter = new CallbacksFilter() + def noOp = new NoOpFilter() + filter.setNext(noOp) + + when: + filter.execute(request, response) + + then: + verify(request).completed(response) || true + verify(request).process(response) || true + verify(response).withObject(processResult) || true + } + + def "RequestFinishedFilter always calls response.finish in finally"() { + given: + def request = mock(Request) + def response = mock(Response) + + def filter = new RequestFinishedFilter() + def noOp = new NoOpFilter() + filter.setNext(noOp) + + when: + filter.execute(request, response) + + then: + verify(response).finish() || true + } + + def "UpstreamRequestEventFilter skips events when no RequestContext"() { + given: + def request = mock(Request) + def response = mock(Response) + def filter = new UpstreamRequestEventFilter() + filter.setNext(new NoOpFilter()) + RequestContext.clear() + + when: + filter.execute(request, response) + + then: + noExceptionThrown() + } + + def "UpstreamRequestEventFilter skips events when no EventBus configured"() { + given: + def request = mock(Request) + def response = mock(Response) + def filter = new UpstreamRequestEventFilter() + filter.setNext(new NoOpFilter()) + RequestContext.builder().clientId("client1").build().register() + + when: + filter.execute(request, response) + + then: + noExceptionThrown() + + cleanup: + RequestContext.clear() + Facilities.reset() + } + + def "UpstreamRequestEventFilter posts before and after events when EventBus present"() { + given: + def request = mock(Request) + def response = mock(Response) + def postedEvents = [] + def eventBus = new com.mx.path.core.common.event.EventBus() { + ObjectMap configurations = new ObjectMap() + void post(Object event) { + postedEvents << event + } + void register(Object subscriber) {} + } + RequestContext.builder().clientId("client1").build().register() + Facilities.addEventBus("client1", eventBus) + def filter = new UpstreamRequestEventFilter() + filter.setNext(new NoOpFilter()) + + when: + filter.execute(request, response) + + then: + postedEvents.size() == 2 + + cleanup: + RequestContext.clear() + Facilities.reset() + } + + def "FaultTolerantRequestFilter delegates to next when no executor configured"() { + given: + def request = mock(Request) + def response = mock(Response) + when(request.getPath()).thenReturn("accounts") + RequestContext.builder().clientId("client1").build().register() + // no FaultTolerantExecutor set in Facilities → else branch + def filter = new FaultTolerantRequestFilter() + filter.setNext(new NoOpFilter()) + + when: + filter.execute(request, response) + + then: + noExceptionThrown() + + cleanup: + RequestContext.clear() + Facilities.reset() + } + + def "FaultTolerantRequestFilter delegates through FTE when configured"() { + given: + def nextCalled = false + def request = mock(Request) + def response = mock(Response) + when(request.getRequestTimeOut()).thenReturn(null) + when(request.getFaultTolerantScope()).thenReturn(null) + RequestContext.builder().clientId("client1").feature("accounts").build().register() + def fte = new FaultTolerantExecutorImpl(new FaultTolerantExecutorImpl.Config()) + Facilities.setFaultTolerantExecutor("client1", fte) + def filter = new FaultTolerantRequestFilter() + filter.setNext(new RequestFilterBase() { + void execute(Request req, Response resp) { + nextCalled = true + } + }) + + when: + filter.execute(request, response) + + then: + nextCalled + + cleanup: + RequestContext.clear() + Facilities.reset() + } + + def "FaultTolerantRequestFilter.buildScope includes feature when set"() { + given: + RequestContext.builder().clientId("client1").feature("accounts").build().register() + def filter = new FaultTolerantRequestFilter() + + when: + def scope = filter.buildScope() + + then: + scope.contains("accounts") + + cleanup: + RequestContext.clear() + } + + def "FaultTolerantRequestFilter.buildScope returns just http when no feature or op"() { + given: + RequestContext.builder().clientId("client1").build().register() + def filter = new FaultTolerantRequestFilter() + + when: + def scope = filter.buildScope() + + then: + scope == "http" + + cleanup: + RequestContext.clear() + } + + def "TracingFilter delegates to next when no tracer registered"() { + given: + def request = mock(Request) + def response = mock(Response) + // GlobalTracer returns a NoopTracer by default; resetting via reflection if needed + def filter = new TracingFilter() + filter.setNext(new NoOpFilter()) + + when: + filter.execute(request, response) + + then: + noExceptionThrown() + } + + def "RequestFinishedFilter calls finish even when next throws"() { + given: + def request = mock(Request) + def response = mock(Response) + + def throwingFilter = new RequestFilterBase() { + void execute(Request req, Response resp) { + throw new RuntimeException("unexpected error") + } + } + def filter = new RequestFinishedFilter() + filter.setNext(throwingFilter) + + when: + filter.execute(request, response) + + then: + thrown(RuntimeException) + verify(response).finish() || true + } +} diff --git a/gateway/src/test/groovy/com/mx/path/gateway/process/GatewayFutureTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/process/GatewayFutureTest.groovy index 713385a9..f4ee9135 100644 --- a/gateway/src/test/groovy/com/mx/path/gateway/process/GatewayFutureTest.groovy +++ b/gateway/src/test/groovy/com/mx/path/gateway/process/GatewayFutureTest.groovy @@ -73,4 +73,28 @@ class FutureWithGatewayContextTest extends Specification { def e = thrown(GatewayException) e.message == "FutureWithGatewayContext timeout out" } + + def "can pass custom executor and timeout"() { + given: + def executorService = Executors.newSingleThreadExecutor() + def subject = new FutureWithGatewayContext({ -> "Feijoada!" }, executorService, 5000L) + + when: + def result = subject.get() + + then: + result == "Feijoada!" + } + + def "wraps ExecutionException in GatewayException"() { + given: + def subject = new FutureWithGatewayContext({ -> throw new RuntimeException("boom") }) + + when: + subject.get() + + then: + def e = thrown(GatewayException) + e.message == "FutureWithGatewayContext execution failed" + } } diff --git a/gateway/src/test/groovy/com/mx/path/gateway/service/GatewayServiceTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/service/GatewayServiceTest.groovy new file mode 100644 index 00000000..6367c4fd --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/service/GatewayServiceTest.groovy @@ -0,0 +1,88 @@ +package com.mx.path.gateway.service + +import com.mx.path.core.common.collection.ObjectMap +import com.mx.path.gateway.service.GatewayService + +import spock.lang.Specification + +class GatewayServiceTest extends Specification { + + static class ConcreteService extends GatewayService { + boolean started = false + boolean stopped = false + + ConcreteService(ObjectMap configs) { + super(configs) + } + + @Override + void start() { + started = true + } + + @Override + void stop() { + stopped = true + } + } + + def "describe with configurations includes class and configs"() { + given: + def configs = new ObjectMap() + configs.put("timeout", "30") + def service = new ConcreteService(configs) + + when: + def desc = service.describe() + + then: + desc.get("class") == "ConcreteService" + desc.containsKey("configurations") + } + + def "describe with empty configurations omits configurations key"() { + given: + def service = new ConcreteService(new ObjectMap()) + + when: + def desc = service.describe() + + then: + desc.get("class") == "ConcreteService" + !desc.containsKey("configurations") + } + + def "describe(ObjectMap) fills provided map"() { + given: + def service = new ConcreteService(new ObjectMap()) + def description = new ObjectMap() + + when: + service.describe(description) + + then: + description.get("class") == "ConcreteService" + } + + def "getGateway returns set gateway"() { + given: + def service = new ConcreteService(new ObjectMap()) + service.setGateway(null) + + expect: + service.getGateway() == null + } + + def "start and stop delegate to implementation"() { + given: + def service = new ConcreteService(new ObjectMap()) + + when: + service.start() + service.stop() + + then: + service.started + service.stopped + } +} diff --git a/gateway/src/test/groovy/com/mx/path/gateway/util/UpstreamLoggerResetTest.groovy b/gateway/src/test/groovy/com/mx/path/gateway/util/UpstreamLoggerResetTest.groovy new file mode 100644 index 00000000..c2afcdea --- /dev/null +++ b/gateway/src/test/groovy/com/mx/path/gateway/util/UpstreamLoggerResetTest.groovy @@ -0,0 +1,27 @@ +package com.mx.path.gateway.util + +import static org.mockito.Mockito.mock + +import org.slf4j.Logger + +import spock.lang.Specification + +class UpstreamLoggerResetTest extends Specification { + + def "setLogger and resetLogger work without error"() { + given: + def customLogger = mock(Logger) + + when: + UpstreamLogger.setLogger(customLogger) + + then: + noExceptionThrown() + + when: + UpstreamLogger.resetLogger() + + then: + noExceptionThrown() + } +} diff --git a/gateway/src/test/java/com/mx/testing/MinimalAccessor.java b/gateway/src/test/java/com/mx/testing/MinimalAccessor.java new file mode 100644 index 00000000..81b28d3e --- /dev/null +++ b/gateway/src/test/java/com/mx/testing/MinimalAccessor.java @@ -0,0 +1,6 @@ +package com.mx.testing; + +import com.mx.path.gateway.accessor.Accessor; + +public class MinimalAccessor extends Accessor { +} diff --git a/gateway/src/test/java/com/mx/testing/gateway/MinimalGateway.java b/gateway/src/test/java/com/mx/testing/gateway/MinimalGateway.java new file mode 100644 index 00000000..e8ebb03f --- /dev/null +++ b/gateway/src/test/java/com/mx/testing/gateway/MinimalGateway.java @@ -0,0 +1,16 @@ +package com.mx.testing.gateway; + +import lombok.experimental.SuperBuilder; + +import com.mx.path.gateway.Gateway; +import com.mx.testing.MinimalAccessor; + +@SuperBuilder +public class MinimalGateway extends Gateway { + public MinimalGateway() { + } + + public MinimalGateway(String clientId) { + super(clientId); + } +} diff --git a/gateway/src/test/java/com/mx/testing/gateway/MinimalRootGateway.java b/gateway/src/test/java/com/mx/testing/gateway/MinimalRootGateway.java new file mode 100644 index 00000000..2b1b36a4 --- /dev/null +++ b/gateway/src/test/java/com/mx/testing/gateway/MinimalRootGateway.java @@ -0,0 +1,14 @@ +package com.mx.testing.gateway; + +import lombok.experimental.SuperBuilder; + +import com.mx.path.gateway.Gateway; +import com.mx.path.gateway.configuration.RootGateway; +import com.mx.testing.MinimalAccessor; + +@SuperBuilder +@RootGateway +public class MinimalRootGateway extends Gateway { + public MinimalRootGateway() { + } +} diff --git a/http/build.gradle b/http/build.gradle index 01af3833..9a7ca366 100644 --- a/http/build.gradle +++ b/http/build.gradle @@ -1,6 +1,14 @@ coppuccino { coverage { - minimumCoverage = 0.50 + minimumCoverage = 0.80 + excludes = [ + // HttpClientFilter makes real Apache HttpClient calls (network I/O). Testing it + // properly requires WireMock or a live HTTP server, which is out of scope here. + "com/mx/path/connect/http/HttpClientFilter*", + // MutualAuthProviderKeystore and its PrivateKeyStrategy inner class require loading + // real SSL keystores with private keys, making them impractical to unit test. + "com/mx/path/connect/http/certificate/MutualAuthProviderKeystore*", + ] } } diff --git a/http/gradle.lockfile b/http/gradle.lockfile index cf2c9876..d07e9b15 100644 --- a/http/gradle.lockfile +++ b/http/gradle.lockfile @@ -9,21 +9,22 @@ com.fasterxml.jackson.core:jackson-databind:2.21.3=runtimeClasspath,testRuntimeC com.fasterxml.jackson:jackson-bom:2.21.3=runtimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.rholder:guava-retrying:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs -com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.3=checkstyle -com.google.guava:guava:32.1.3-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.j2objc:j2objc-annotations:3.0.0=checkstyle com.puppycrawl.tools:checkstyle:10.25.0=checkstyle com.sun.istack:istack-commons-runtime:4.1.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath @@ -33,7 +34,7 @@ commons-beanutils:commons-beanutils:1.11.0=checkstyle,compileClasspath,runtimeCl commons-codec:commons-codec:1.14=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs commons-logging:commons-logging:1.3.5=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath info.picocli:picocli:4.7.7=checkstyle io.github.cdimascio:dotenv-java:2.3.2=runtimeClasspath,testRuntimeClasspath @@ -45,7 +46,7 @@ io.opentracing:opentracing-util:0.33.0=compileClasspath,runtimeClasspath,testCom jakarta.activation:jakarta.activation-api:2.1.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.soap:jakarta.xml.soap-api:3.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -55,12 +56,10 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle @@ -69,15 +68,15 @@ org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpclient:4.5.14=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.14=checkstyle org.apache.httpcomponents:httpcore:4.4.16=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.checkerframework:checker-qual:3.37.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.checkerframework:checker-qual:3.49.3=checkstyle org.checkerframework:checker-qual:3.53.1=pmd org.codehaus.groovy:groovy:3.0.24=testCompileClasspath,testRuntimeClasspath @@ -100,18 +99,19 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=runtimeClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath @@ -119,7 +119,8 @@ org.reflections:reflections:0.10.2=checkstyle,runtimeClasspath,testRuntimeClassp org.slf4j:jul-to-slf4j:1.7.36=pmd org.slf4j:slf4j-api:1.7.30=compileClasspath,testCompileClasspath org.slf4j:slf4j-api:1.7.32=runtimeClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:1.7.30=testCompileClasspath,testRuntimeClasspath org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath diff --git a/http/src/test/groovy/com/mx/path/api/connect/http/HttpAccessorConnectionTest.groovy b/http/src/test/groovy/com/mx/path/api/connect/http/HttpAccessorConnectionTest.groovy index 9bfaa618..30075707 100644 --- a/http/src/test/groovy/com/mx/path/api/connect/http/HttpAccessorConnectionTest.groovy +++ b/http/src/test/groovy/com/mx/path/api/connect/http/HttpAccessorConnectionTest.groovy @@ -5,6 +5,7 @@ import static org.mockito.Mockito.spy import static org.mockito.Mockito.verify import com.mx.path.connect.http.HttpAccessorConnection +import com.mx.path.connect.http.HttpClientFilter import com.mx.path.connect.http.HttpRequest import com.mx.path.connect.http.HttpResponse import com.mx.path.core.common.request.Feature @@ -161,6 +162,18 @@ class HttpAccessorConnectionTest extends Specification { verify(fakeRequest).put() || true } + def "connectionRequestFilters returns a single HttpClientFilter"() { + given: + def subject = new HttpAccessorConnection() + + when: + def filters = subject.connectionRequestFilters() + + then: + filters.size() == 1 + filters[0] instanceof HttpClientFilter + } + def "patch"() { given: def subject = spy(new HttpAccessorConnection()) diff --git a/http/src/test/groovy/com/mx/path/api/connect/http/certificate/FieldSettingsValidationErrorTest.groovy b/http/src/test/groovy/com/mx/path/api/connect/http/certificate/FieldSettingsValidationErrorTest.groovy new file mode 100644 index 00000000..f3b5b6c9 --- /dev/null +++ b/http/src/test/groovy/com/mx/path/api/connect/http/certificate/FieldSettingsValidationErrorTest.groovy @@ -0,0 +1,56 @@ +package com.mx.path.api.connect.http.certificate + +import com.mx.path.connect.http.certificate.FieldSettingsValidationError + +import spock.lang.Specification + +class FieldSettingsValidationErrorTest extends Specification { + + def "string constructor stores message"() { + given: + def ex = new FieldSettingsValidationError("something went wrong") + + expect: + ex.getMessage() == "something went wrong" + } + + def "list constructor stores fields and retrieves them"() { + given: + def field = new FieldSettingsValidationError.Field("keystorePath", "must not be empty") + def ex = new FieldSettingsValidationError([field]) + + expect: + ex.getFields().size() == 1 + ex.getFields()[0].is(field) + } + + def "Field constructor, getters and setters"() { + given: + def field = new FieldSettingsValidationError.Field("keystorePath", "must not be empty") + + expect: + field.getField() == "keystorePath" + field.getError() == "must not be empty" + + when: + field.setField("keystorePassword") + field.setError("must not be null") + + then: + field.getField() == "keystorePassword" + field.getError() == "must not be null" + } + + def "setFields replaces the fields list"() { + given: + def f1 = new FieldSettingsValidationError.Field("a", "err1") + def f2 = new FieldSettingsValidationError.Field("b", "err2") + def ex = new FieldSettingsValidationError([f1]) + + when: + ex.setFields([f1, f2]) + + then: + ex.getFields().size() == 2 + } +} diff --git a/http/src/test/groovy/com/mx/path/api/connect/http/certificate/KeyStoreBuilderTest.groovy b/http/src/test/groovy/com/mx/path/api/connect/http/certificate/KeyStoreBuilderTest.groovy new file mode 100644 index 00000000..e7c33745 --- /dev/null +++ b/http/src/test/groovy/com/mx/path/api/connect/http/certificate/KeyStoreBuilderTest.groovy @@ -0,0 +1,134 @@ +package com.mx.path.api.connect.http.certificate + +import com.mx.path.connect.http.certificate.FieldSettingsValidationError +import com.mx.path.connect.http.certificate.KeyStoreBuilder +import com.mx.path.core.common.connect.AccessorConnectionSettings + +import spock.lang.Specification + +class KeyStoreBuilderTest extends Specification { + + static final String KEYSTORE_PATH = "./src/test/resources/keystore.jks" + static final char[] KEYSTORE_PASSWORD = "secret".toCharArray() + static final String CERT_ALIAS = "test" + + def buildValidSettings() { + def s = new AccessorConnectionSettings() + s.setKeystorePath(KEYSTORE_PATH) + s.setKeystorePassword(KEYSTORE_PASSWORD) + s.setCertificateAlias(CERT_ALIAS) + return s + } + + def "constructor exposes all settings"() { + given: + def builder = new KeyStoreBuilder(buildValidSettings()) + + expect: + builder.getKeystorePath() == KEYSTORE_PATH + String.valueOf(builder.getKeystorePassword()) == "secret" + builder.getCertificateAlias() == CERT_ALIAS + builder.getKeyStore() != null + } + + def "validateSettings passes when all fields are valid"() { + given: + def builder = new KeyStoreBuilder(buildValidSettings()) + + when: + builder.validateSettings() + + then: + noExceptionThrown() + } + + def "validateSettings throws when certificateAlias is null"() { + given: + def builder = new KeyStoreBuilder(buildValidSettings()) + def f = KeyStoreBuilder.getDeclaredField("certificateAlias") + f.setAccessible(true) + f.set(builder, null) + + when: + builder.validateSettings() + + then: + def ex = thrown(FieldSettingsValidationError) + ex.getFields().any { it.getField() == "certificateAlias" } + } + + def "validateSettings throws when certificateAlias is empty"() { + given: + def builder = new KeyStoreBuilder(buildValidSettings()) + def f = KeyStoreBuilder.getDeclaredField("certificateAlias") + f.setAccessible(true) + f.set(builder, "") + + when: + builder.validateSettings() + + then: + def ex = thrown(FieldSettingsValidationError) + ex.getFields().any { it.getField() == "certificateAlias" } + } + + def "validateSettings throws when keystorePassword is null"() { + given: + def builder = new KeyStoreBuilder(buildValidSettings()) + def f = KeyStoreBuilder.getDeclaredField("keystorePassword") + f.setAccessible(true) + f.set(builder, null) + + when: + builder.validateSettings() + + then: + def ex = thrown(FieldSettingsValidationError) + ex.getFields().any { it.getField() == "keystorePassword" } + } + + def "validateSettings throws when keystorePassword is empty array"() { + given: + def builder = new KeyStoreBuilder(buildValidSettings()) + def f = KeyStoreBuilder.getDeclaredField("keystorePassword") + f.setAccessible(true) + f.set(builder, new char[0]) + + when: + builder.validateSettings() + + then: + def ex = thrown(FieldSettingsValidationError) + ex.getFields().any { it.getField() == "keystorePassword" } + } + + def "validateSettings throws when keystorePath points to non-existent file"() { + given: + def builder = new KeyStoreBuilder(buildValidSettings()) + def f = KeyStoreBuilder.getDeclaredField("keystorePath") + f.setAccessible(true) + f.set(builder, "/no/such/file.jks") + + when: + builder.validateSettings() + + then: + def ex = thrown(FieldSettingsValidationError) + ex.getFields().any { it.getField() == "keystorePath" } + } + + def "validateSettings throws when keystorePath is null"() { + given: + def builder = new KeyStoreBuilder(buildValidSettings()) + def f = KeyStoreBuilder.getDeclaredField("keystorePath") + f.setAccessible(true) + f.set(builder, null) + + when: + builder.validateSettings() + + then: + def ex = thrown(FieldSettingsValidationError) + ex.getFields().any { it.getField() == "keystorePath" } + } +} diff --git a/messaging/gradle.lockfile b/messaging/gradle.lockfile index 7882b293..c19c1365 100644 --- a/messaging/gradle.lockfile +++ b/messaging/gradle.lockfile @@ -8,27 +8,28 @@ com.fasterxml.jackson.core:jackson-databind:2.21.3=runtimeClasspath,testRuntimeC com.fasterxml.jackson:jackson-bom:2.21.3=runtimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.rholder:guava-retrying:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs -com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.3=checkstyle -com.google.guava:guava:32.1.3-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.j2objc:j2objc-annotations:3.0.0=checkstyle com.puppycrawl.tools:checkstyle:10.25.0=checkstyle commons-beanutils:commons-beanutils:1.11.0=checkstyle commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs info.picocli:picocli:4.7.7=checkstyle io.github.cdimascio:dotenv-java:2.3.2=runtimeClasspath,testRuntimeClasspath io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath @@ -36,7 +37,7 @@ io.opentracing:opentracing-api:0.33.0=compileClasspath,runtimeClasspath,testComp io.opentracing:opentracing-mock:0.33.0=testCompileClasspath,testRuntimeClasspath io.opentracing:opentracing-noop:0.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath io.opentracing:opentracing-util:0.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -46,27 +47,25 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5:5.1.3=checkstyle org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpcore:4.4.14=checkstyle -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.checkerframework:checker-qual:3.37.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.checkerframework:checker-qual:3.49.3=checkstyle org.checkerframework:checker-qual:3.53.1=pmd org.codehaus.groovy:groovy:3.0.24=testCompileClasspath,testRuntimeClasspath @@ -85,25 +84,27 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=runtimeClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=checkstyle org.slf4j:jul-to-slf4j:1.7.36=pmd org.slf4j:slf4j-api:1.7.30=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:1.7.30=testCompileClasspath,testRuntimeClasspath org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath diff --git a/test-gateway-generator/gradle.lockfile b/test-gateway-generator/gradle.lockfile index 9917c79c..e55743b0 100644 --- a/test-gateway-generator/gradle.lockfile +++ b/test-gateway-generator/gradle.lockfile @@ -8,24 +8,23 @@ com.fasterxml.jackson.core:jackson-core:2.21.3=runtimeClasspath,testRuntimeClass com.fasterxml.jackson.core:jackson-databind:2.21.3=runtimeClasspath,testRuntimeClasspath com.fasterxml.jackson:jackson-bom:2.21.3=runtimeClasspath,testRuntimeClasspath com.github.rholder:guava-retrying:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=spotbugs -com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.errorprone:error_prone_annotations:2.41.0=spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.guava:guava:32.1.3-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.squareup:javapoet:1.13.0=runtimeClasspath,testRuntimeClasspath com.sun.istack:istack-commons-runtime:4.1.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.sun.xml.bind:jaxb-core:4.0.6=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.sun.xml.bind:jaxb-impl:4.0.6=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath commons-codec:commons-codec:1.14=runtimeClasspath,testRuntimeClasspath -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs commons-logging:commons-logging:1.2=runtimeClasspath,testRuntimeClasspath io.github.cdimascio:dotenv-java:2.3.2=runtimeClasspath,testRuntimeClasspath io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath @@ -35,21 +34,19 @@ io.opentracing:opentracing-util:0.33.0=compileClasspath,runtimeClasspath,testCom jakarta.activation:jakarta.activation-api:2.1.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.soap:jakarta.xml.soap-api:3.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.9=spotbugs -org.apache.bcel:bcel:6.11.0=spotbugs -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.bcel:bcel:6.12.0=spotbugs +org.apache.commons:commons-lang3:3.20.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.httpcomponents:httpclient:4.5.14=runtimeClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.16=runtimeClasspath,testRuntimeClasspath -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.checkerframework:checker-qual:3.37.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.codehaus.groovy:groovy:3.0.24=testCompileClasspath,testRuntimeClasspath org.dom4j:dom4j:2.2.0=spotbugs org.eclipse.angus:angus-activation:2.0.3=runtimeClasspath,testRuntimeClasspath @@ -65,22 +62,24 @@ org.javassist:javassist:3.28.0-GA=runtimeClasspath,testRuntimeClasspath org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=runtimeClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=runtimeClasspath,testRuntimeClasspath org.slf4j:slf4j-api:1.7.32=runtimeClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath org.spockframework:spock-core:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath diff --git a/test-gateways/gradle.lockfile b/test-gateways/gradle.lockfile index f9b5feb4..cd3aba02 100644 --- a/test-gateways/gradle.lockfile +++ b/test-gateways/gradle.lockfile @@ -9,21 +9,22 @@ com.fasterxml.jackson.core:jackson-databind:2.21.3=annotationProcessor,runtimeCl com.fasterxml.jackson:jackson-bom:2.21.3=annotationProcessor,runtimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.rholder:guava-retrying:2.0.0=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs -com.google.code.gson:gson:2.14.0=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=annotationProcessor,compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=annotationProcessor,compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.3=checkstyle -com.google.guava:guava:32.1.3-jre=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.j2objc:j2objc-annotations:3.0.0=checkstyle com.puppycrawl.tools:checkstyle:10.25.0=checkstyle com.squareup:javapoet:1.13.0=annotationProcessor @@ -34,7 +35,7 @@ commons-beanutils:commons-beanutils:1.11.0=checkstyle commons-codec:commons-codec:1.14=annotationProcessor,runtimeClasspath,testRuntimeClasspath commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs commons-logging:commons-logging:1.2=annotationProcessor,runtimeClasspath,testRuntimeClasspath info.picocli:picocli:4.7.7=checkstyle io.github.cdimascio:dotenv-java:2.3.2=annotationProcessor,runtimeClasspath,testRuntimeClasspath @@ -45,7 +46,7 @@ io.opentracing:opentracing-util:0.33.0=annotationProcessor,compileClasspath,runt jakarta.activation:jakarta.activation-api:2.1.4=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.soap:jakarta.xml.soap-api:3.0.2=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -55,12 +56,10 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=annotationProcessor,compileClasspath,pmd,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.20.0=annotationProcessor,compileClasspath,pmd,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=annotationProcessor,compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle @@ -69,15 +68,15 @@ org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpclient:4.5.14=annotationProcessor,runtimeClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.14=checkstyle org.apache.httpcomponents:httpcore:4.4.16=annotationProcessor,runtimeClasspath,testRuntimeClasspath -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.checkerframework:checker-qual:3.37.0=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=annotationProcessor,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.checkerframework:checker-qual:3.49.3=checkstyle org.checkerframework:checker-qual:3.53.1=pmd org.codehaus.groovy:groovy:3.0.24=testCompileClasspath,testRuntimeClasspath @@ -100,25 +99,27 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=annotationProcessor,runtimeClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=annotationProcessor,checkstyle,runtimeClasspath,testRuntimeClasspath org.slf4j:jul-to-slf4j:1.7.36=pmd org.slf4j:slf4j-api:1.7.32=annotationProcessor,runtimeClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath org.spockframework:spock-core:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath diff --git a/test-models/gradle.lockfile b/test-models/gradle.lockfile index 04b1b599..830d6389 100644 --- a/test-models/gradle.lockfile +++ b/test-models/gradle.lockfile @@ -9,21 +9,22 @@ com.fasterxml.jackson.core:jackson-databind:2.21.3=runtimeClasspath,testRuntimeC com.fasterxml.jackson:jackson-bom:2.21.3=runtimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.rholder:guava-retrying:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs -com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.3=checkstyle -com.google.guava:guava:32.1.3-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.j2objc:j2objc-annotations:3.0.0=checkstyle com.puppycrawl.tools:checkstyle:10.25.0=checkstyle com.sun.istack:istack-commons-runtime:4.1.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath @@ -33,7 +34,7 @@ commons-beanutils:commons-beanutils:1.11.0=checkstyle commons-codec:commons-codec:1.14=runtimeClasspath,testRuntimeClasspath commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs commons-logging:commons-logging:1.2=runtimeClasspath,testRuntimeClasspath info.picocli:picocli:4.7.7=checkstyle io.github.cdimascio:dotenv-java:2.3.2=runtimeClasspath,testRuntimeClasspath @@ -44,7 +45,7 @@ io.opentracing:opentracing-util:0.33.0=compileClasspath,runtimeClasspath,testCom jakarta.activation:jakarta.activation-api:2.1.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.soap:jakarta.xml.soap-api:3.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -54,12 +55,10 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle @@ -68,15 +67,15 @@ org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpclient:4.5.14=runtimeClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.14=checkstyle org.apache.httpcomponents:httpcore:4.4.16=runtimeClasspath,testRuntimeClasspath -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=testCompileClasspath -org.checkerframework:checker-qual:3.37.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.checkerframework:checker-qual:3.49.3=checkstyle org.checkerframework:checker-qual:3.53.1=pmd org.codehaus.groovy:groovy:3.0.24=testCompileClasspath,testRuntimeClasspath @@ -99,25 +98,27 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=runtimeClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=checkstyle,runtimeClasspath,testRuntimeClasspath org.slf4j:jul-to-slf4j:1.7.36=pmd org.slf4j:slf4j-api:1.7.32=runtimeClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath org.spockframework:spock-core:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath diff --git a/testing/gradle.lockfile b/testing/gradle.lockfile index ef58ad36..eaa14508 100644 --- a/testing/gradle.lockfile +++ b/testing/gradle.lockfile @@ -9,21 +9,22 @@ com.fasterxml.jackson.core:jackson-databind:2.21.3=runtimeClasspath,testRuntimeC com.fasterxml.jackson:jackson-bom:2.21.3=runtimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd com.github.rholder:guava-retrying:2.0.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs -com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs -com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.1=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:failureaccess:1.0.3=checkstyle -com.google.guava:guava:32.1.3-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +com.google.guava:guava:32.0.1-jre=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle,compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -com.google.j2objc:j2objc-annotations:2.8=compileClasspath,testCompileClasspath +com.google.j2objc:j2objc-annotations:2.8=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath com.google.j2objc:j2objc-annotations:3.0.0=checkstyle com.puppycrawl.tools:checkstyle:10.25.0=checkstyle com.sun.istack:istack-commons-runtime:4.1.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath @@ -33,7 +34,7 @@ commons-beanutils:commons-beanutils:1.11.0=checkstyle commons-codec:commons-codec:1.14=runtimeClasspath,testRuntimeClasspath commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs commons-logging:commons-logging:1.2=runtimeClasspath,testRuntimeClasspath info.picocli:picocli:4.7.7=checkstyle io.github.cdimascio:dotenv-java:2.3.2=runtimeClasspath,testRuntimeClasspath @@ -44,7 +45,7 @@ io.opentracing:opentracing-util:0.33.0=compileClasspath,runtimeClasspath,testCom jakarta.activation:jakarta.activation-api:2.1.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.bind:jakarta.xml.bind-api:4.0.4=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath jakarta.xml.soap:jakarta.xml.soap-api:3.0.2=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.18.3=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -54,12 +55,10 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.apache.commons:commons-text:1.14.0=spotbugs -org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-lang3:3.20.0=compileClasspath,pmd,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath +org.apache.commons:commons-text:1.15.0=compileClasspath,runtimeClasspath,spotbugs,testCompileClasspath,testRuntimeClasspath org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle @@ -68,8 +67,8 @@ org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpclient:4.5.14=runtimeClasspath,testRuntimeClasspath org.apache.httpcomponents:httpcore:4.4.14=checkstyle org.apache.httpcomponents:httpcore:4.4.16=runtimeClasspath,testRuntimeClasspath -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle @@ -77,7 +76,7 @@ org.apache.maven.doxia:doxia-sink-api:1.12.0=checkstyle org.apache.xbean:xbean-reflect:3.7=checkstyle org.apiguardian:apiguardian-api:1.1.2=compileClasspath,testCompileClasspath org.assertj:assertj-core:3.27.7=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.checkerframework:checker-qual:3.37.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath +org.checkerframework:checker-qual:3.33.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.checkerframework:checker-qual:3.49.3=checkstyle org.checkerframework:checker-qual:3.53.1=pmd org.codehaus.groovy:groovy:3.0.24=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath @@ -100,25 +99,27 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,compileClasspath,runtimeClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,compileClasspath,runtimeClasspath,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=runtimeClasspath,testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=checkstyle,runtimeClasspath,testRuntimeClasspath org.slf4j:jul-to-slf4j:1.7.36=pmd org.slf4j:slf4j-api:1.7.32=runtimeClasspath,testRuntimeClasspath -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath org.spockframework:spock-core:2.4-M6-groovy-3.0=compileClasspath,runtimeClasspath,testCompileClasspath,testRuntimeClasspath diff --git a/testing/src/test/groovy/com/mx/path/testing/MockeryAndSessionRepositorySpec.groovy b/testing/src/test/groovy/com/mx/path/testing/MockeryAndSessionRepositorySpec.groovy new file mode 100644 index 00000000..af575af3 --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/MockeryAndSessionRepositorySpec.groovy @@ -0,0 +1,52 @@ +package com.mx.path.testing + +import com.mx.path.core.context.Session + +class MockeryAndSessionRepositorySpec extends MockeryAndSessionRepository { + + def cleanup() { + Session.clearSession() + Session.setRepositorySupplier(null) + Session.setEncryptionServiceSupplier(null) + } + + def "setupMockery and cleanupMockery complete without error"() { + when: + setupMockery() + cleanupMockery() + + then: + noExceptionThrown() + } + + def "setupSessionRepository configures session suppliers"() { + when: + setupSessionRepository() + + then: + Session.getRepositorySupplier() != null + Session.getEncryptionServiceSupplier() != null + } + + def "clearSessionRepository resets to a fresh repository"() { + given: + setupSessionRepository() + + when: + clearSessionRepository() + + then: + Session.getRepositorySupplier() != null + } + + def "cleanupSessionRepository removes suppliers"() { + given: + setupSessionRepository() + + when: + cleanupSessionRepository() + + then: + noExceptionThrown() + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/MockerySpec.groovy b/testing/src/test/groovy/com/mx/path/testing/MockerySpec.groovy new file mode 100644 index 00000000..1fb90112 --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/MockerySpec.groovy @@ -0,0 +1,15 @@ +package com.mx.path.testing + +import com.mx.path.testing.Mockery + +class MockerySpec extends Mockery { + + def "setupMockery and cleanupMockery complete without error"() { + when: + setupMockery() + cleanupMockery() + + then: + noExceptionThrown() + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/SessionRepositorySpec.groovy b/testing/src/test/groovy/com/mx/path/testing/SessionRepositorySpec.groovy new file mode 100644 index 00000000..188bc4ec --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/SessionRepositorySpec.groovy @@ -0,0 +1,44 @@ +package com.mx.path.testing + +import com.mx.path.core.context.Session +import com.mx.path.testing.SessionRepository + +class SessionRepositorySpec extends SessionRepository { + + def "setupSessionRepository configures session suppliers"() { + when: + setupSessionRepository() + + then: + Session.getRepositorySupplier() != null + Session.getEncryptionServiceSupplier() != null + + cleanup: + cleanupSessionRepository() + } + + def "clearSessionRepository installs a fresh repository"() { + given: + setupSessionRepository() + + when: + clearSessionRepository() + + then: + Session.getRepositorySupplier() != null + + cleanup: + cleanupSessionRepository() + } + + def "cleanupSessionRepository removes suppliers"() { + given: + setupSessionRepository() + + when: + cleanupSessionRepository() + + then: + noExceptionThrown() + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/TestingBaseSpec.groovy b/testing/src/test/groovy/com/mx/path/testing/TestingBaseSpec.groovy new file mode 100644 index 00000000..ffd0d2c1 --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/TestingBaseSpec.groovy @@ -0,0 +1,132 @@ +package com.mx.path.testing + +import static org.mockito.Mockito.mock + +import com.mx.path.testing.request.RequestExpectations +import com.mx.path.testing.request.RequestMatcher +import com.mx.testing.TestConnection + +class TestingBaseSpec extends TestingBase { + + def cleanup() { + RequestExpectations.reset() + } + + def "withPath creates path matcher"() { + given: + def matcher = withPath("accounts") + + expect: + matcher instanceof RequestMatcher + } + + def "withMethod creates method matcher"() { + given: + def matcher = withMethod("GET") + + expect: + matcher instanceof RequestMatcher + } + + def "expectConnection registers an expectation"() { + when: + expectConnection(withPath("accounts")) + + then: + RequestExpectations.getRequestExpectations().size() == 1 + } + + def "stubConnection registers an allowance"() { + when: + stubConnection(withPath("accounts")) + + then: + RequestExpectations.getRequestAllowances().size() == 1 + } + + def "allowConnection registers an allowance"() { + when: + allowConnection(withPath("accounts")) + + then: + RequestExpectations.getRequestAllowances().size() == 1 + } + + def "setupConnectionMocking resets request expectations"() { + given: + expectConnection(withPath("accounts")) + + when: + setupConnectionMocking() + + then: + RequestExpectations.getRequestExpectations().isEmpty() + } + + def "setupConnection returns a wrapped connection"() { + given: + def connection = setupConnection(new TestConnection()) + + expect: + connection != null + } + + def "cleanupRequestExpectations verifies and resets"() { + when: + cleanupRequestExpectations() + + then: + noExceptionThrown() + } + + def "request() returns first captured request"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + RequestExpectations.addRequest(req) + + expect: + request() != null + } + + def "request(matcher) returns matching request"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + org.mockito.Mockito.when(req.getPath()).thenReturn("accounts") + RequestExpectations.addRequest(req) + + expect: + request(withPath("accounts")) != null + request(withPath("other")) == null + } + + def "requests() returns all captured requests"() { + given: + RequestExpectations.addRequest(mock(com.mx.path.core.common.connect.Request)) + + expect: + requests().size() == 1 + } + + def "exactly creates an exact-match matcher"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + + when: + def matcher = exactly(req) + + then: + matcher != null + matcher.isMatch(req) + } + + def "requests(matcher) returns filtered requests"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + org.mockito.Mockito.when(req.getPath()).thenReturn("accounts") + RequestExpectations.addRequest(req) + + expect: + requests(withPath("accounts")).size() == 1 + requests(withPath("other")).size() == 0 + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/WithMockeryTest.groovy b/testing/src/test/groovy/com/mx/path/testing/WithMockeryTest.groovy new file mode 100644 index 00000000..ca109450 --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/WithMockeryTest.groovy @@ -0,0 +1,15 @@ +package com.mx.path.testing + +import spock.lang.Specification + +class WithMockeryTest extends Specification implements WithMockery { + + def "setupMockery and cleanupMockery complete without error"() { + when: + setupMockery() + cleanupMockery() + + then: + noExceptionThrown() + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/WithRequestExpectationsTest.groovy b/testing/src/test/groovy/com/mx/path/testing/WithRequestExpectationsTest.groovy new file mode 100644 index 00000000..65599d74 --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/WithRequestExpectationsTest.groovy @@ -0,0 +1,135 @@ +package com.mx.path.testing + +import static org.mockito.Mockito.mock + +import com.mx.path.testing.request.RequestExpectations +import com.mx.path.testing.request.RequestMatcher +import com.mx.testing.TestConnection + +import spock.lang.Specification + +class WithRequestExpectationsTest extends Specification implements WithRequestExpectations { + + def cleanup() { + RequestExpectations.reset() + } + + def "withPath creates a path matcher"() { + given: + def matcher = withPath("accounts") + + expect: + matcher != null + } + + def "withMethod creates a method matcher"() { + given: + def matcher = withMethod("GET") + + expect: + matcher != null + } + + def "expectConnection registers an expectation"() { + when: + expectConnection(withPath("accounts")) + + then: + RequestExpectations.getRequestExpectations().size() == 1 + } + + def "stubConnection registers an allowance"() { + when: + stubConnection(withPath("accounts")) + + then: + RequestExpectations.getRequestAllowances().size() == 1 + } + + def "allowConnection registers an allowance"() { + when: + allowConnection(withPath("accounts")) + + then: + RequestExpectations.getRequestAllowances().size() == 1 + } + + def "setupConnectionMocking resets expectations"() { + given: + expectConnection(withPath("accounts")) + + when: + setupConnectionMocking() + + then: + RequestExpectations.getRequestExpectations().isEmpty() + } + + def "setupConnection returns a spy connection"() { + given: + def connection = setupConnection(new TestConnection()) + + expect: + connection != null + } + + def "cleanupRequestExpectations resets after verifying"() { + when: + cleanupRequestExpectations() + + then: + noExceptionThrown() + } + + def "request() returns first captured request"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + RequestExpectations.addRequest(req) + + expect: + request() != null + } + + def "request(matcher) returns matching request"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + org.mockito.Mockito.when(req.getPath()).thenReturn("accounts") + RequestExpectations.addRequest(req) + + expect: + request(withPath("accounts")) != null + request(withPath("other")) == null + } + + def "requests() returns all captured requests"() { + given: + RequestExpectations.addRequest(mock(com.mx.path.core.common.connect.Request)) + RequestExpectations.addRequest(mock(com.mx.path.core.common.connect.Request)) + + expect: + requests().size() == 2 + } + + def "exactly creates a matcher for the given request"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + + when: + def matcher = exactly(req) + + then: + matcher != null + matcher.isMatch(req) + } + + def "requests(matcher) returns filtered requests"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + org.mockito.Mockito.when(req.getPath()).thenReturn("accounts") + RequestExpectations.addRequest(req) + RequestExpectations.addRequest(mock(com.mx.path.core.common.connect.Request)) + + expect: + requests(withPath("accounts")).size() == 1 + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/WithSessionRepositoryTest.groovy b/testing/src/test/groovy/com/mx/path/testing/WithSessionRepositoryTest.groovy new file mode 100644 index 00000000..bb53634d --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/WithSessionRepositoryTest.groovy @@ -0,0 +1,42 @@ +package com.mx.path.testing + +import com.mx.path.core.context.Session + +import spock.lang.Specification + +class WithSessionRepositoryTest extends Specification implements WithSessionRepository { + + def "setupSessionRepository configures session suppliers"() { + when: + setupSessionRepository() + + then: + Session.getRepositorySupplier() != null + Session.getEncryptionServiceSupplier() != null + } + + def "clearSessionRepository resets to a fresh repository"() { + given: + setupSessionRepository() + + when: + clearSessionRepository() + + then: + Session.getRepositorySupplier() != null + + cleanup: + cleanupSessionRepository() + } + + def "cleanupSessionRepository removes all suppliers"() { + given: + setupSessionRepository() + + when: + cleanupSessionRepository() + + then: + noExceptionThrown() + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/request/RequestExpectationTest.groovy b/testing/src/test/groovy/com/mx/path/testing/request/RequestExpectationTest.groovy new file mode 100644 index 00000000..b127e2f1 --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/request/RequestExpectationTest.groovy @@ -0,0 +1,151 @@ +package com.mx.path.testing.request + +import static org.mockito.Mockito.mock + +import com.mx.path.core.common.connect.Request +import com.mx.path.core.common.connect.Response +import com.mx.path.testing.request.RequestExpectation +import com.mx.path.testing.request.RequestMatcher + +import org.spockframework.runtime.SpockAssertionError + +import spock.lang.Specification + +class RequestExpectationTest extends Specification { + + def cleanup() { + RequestExpectations.reset() + } + + def makeRequest(String path = "accounts") { + def req = mock(Request) + org.mockito.Mockito.when(req.getPath()).thenReturn(path) + return req + } + + def makeResponse() { + return mock(Response) + } + + def "toRespond sets handler"() { + given: + def expectation = new RequestExpectation(RequestMatcher.Fluent.withPath("accounts")) + + when: + expectation.toRespond({ req, resp -> }) + + then: + expectation.getHandler() != null + } + + def "handle invokes the handler and increments invokeCount"() { + given: + def expectation = new RequestExpectation(RequestMatcher.Fluent.withPath("accounts")) + def handled = false + expectation.toRespond({ req, resp -> handled = true }) + + when: + expectation.handle(makeRequest(), makeResponse()) + + then: + handled + expectation.getInvokeCount() == 1 + } + + def "assertInvoked passes when invokeCount matches expectedInvokeCount"() { + given: + def expectation = new RequestExpectation(RequestMatcher.Fluent.withPath("accounts")) + expectation.toRespond({ req, resp -> }) + expectation.handle(makeRequest(), makeResponse()) + + when: + expectation.assertInvoked() + + then: + noExceptionThrown() + } + + def "assertInvoked throws when invokeCount does not match"() { + given: + def expectation = new RequestExpectation(RequestMatcher.Fluent.withPath("accounts")) + expectation.toRespond({ req, resp -> }) + + when: + expectation.assertInvoked() + + then: + thrown(SpockAssertionError) + } + + def "times sets expectedInvokeCount"() { + given: + def expectation = new RequestExpectation(RequestMatcher.Fluent.withPath("accounts")) + expectation.toRespond({ req, resp -> }) + + when: + expectation.times(2) + expectation.handle(makeRequest(), makeResponse()) + expectation.handle(makeRequest(), makeResponse()) + expectation.assertInvoked() + + then: + noExceptionThrown() + expectation.getInvokeCount() == 2 + } + + def "getReceivedRequest returns first handled request"() { + given: + def expectation = new RequestExpectation(RequestMatcher.Fluent.withPath("accounts")) + def request = makeRequest() + expectation.toRespond({ req, resp -> }) + expectation.handle(request, makeResponse()) + + when: + def received = expectation.getReceivedRequest() + + then: + received.is(request) + } + + def "getReceivedRequests returns all handled requests"() { + given: + def expectation = new RequestExpectation(new RequestMatcher()) + expectation.times(2) + expectation.toRespond({ req, resp -> }) + expectation.handle(makeRequest(), makeResponse()) + expectation.handle(makeRequest(), makeResponse()) + + when: + def received = expectation.getReceivedRequests() + + then: + received.size() == 2 + } + + def "collectRequests adds handled requests to RequestExpectations"() { + given: + def expectation = new RequestExpectation(new RequestMatcher()) + expectation.toRespond({ req, resp -> }) + expectation.collectRequests() + + when: + expectation.handle(makeRequest(), makeResponse()) + + then: + RequestExpectations.requests().size() == 1 + } + + def "onRequest callback is invoked on each handle"() { + given: + def expectation = new RequestExpectation(RequestMatcher.Fluent.withPath("accounts")) + def callCount = 0 + expectation.toRespond({ req, resp -> }) + expectation.onRequest({ req, resp -> callCount++ }) + + when: + expectation.handle(makeRequest(), makeResponse()) + + then: + callCount == 1 + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/request/RequestExpectationsTest.groovy b/testing/src/test/groovy/com/mx/path/testing/request/RequestExpectationsTest.groovy index 97560f56..f0076398 100644 --- a/testing/src/test/groovy/com/mx/path/testing/request/RequestExpectationsTest.groovy +++ b/testing/src/test/groovy/com/mx/path/testing/request/RequestExpectationsTest.groovy @@ -1,5 +1,8 @@ package com.mx.path.testing.request +import static org.mockito.Mockito.mock +import static org.mockito.Mockito.when + import com.mx.path.gateway.connect.filter.CallbacksFilter import com.mx.path.gateway.connect.filter.ErrorHandlerFilter import com.mx.path.gateway.connect.filter.RequestFinishedFilter @@ -55,6 +58,79 @@ class RequestExpectationsTest extends Specification { RequestExpectations.getRequestExpectations().isEmpty() } + def "addRequest and request() retrieval"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + when(req.getPath()).thenReturn("accounts") + + when: + RequestExpectations.addRequest(req) + + then: + RequestExpectations.request() != null + RequestExpectations.request().is(req) + } + + def "requests() returns all added requests"() { + given: + def req1 = mock(com.mx.path.core.common.connect.Request) + def req2 = mock(com.mx.path.core.common.connect.Request) + RequestExpectations.addRequest(req1) + RequestExpectations.addRequest(req2) + + expect: + RequestExpectations.requests().size() == 2 + } + + def "requests(matcher) filters by matcher"() { + given: + def req1 = mock(com.mx.path.core.common.connect.Request) + def req2 = mock(com.mx.path.core.common.connect.Request) + when(req1.getPath()).thenReturn("accounts") + when(req2.getPath()).thenReturn("transactions") + RequestExpectations.addRequest(req1) + RequestExpectations.addRequest(req2) + + when: + def matched = RequestExpectations.requests(RequestMatcher.Fluent.withPath("accounts")) + + then: + matched.size() == 1 + matched[0].is(req1) + } + + def "request(matcher) returns first match"() { + given: + def req = mock(com.mx.path.core.common.connect.Request) + when(req.getPath()).thenReturn("accounts") + RequestExpectations.addRequest(req) + + expect: + RequestExpectations.request(RequestMatcher.Fluent.withPath("accounts")).is(req) + RequestExpectations.request(RequestMatcher.Fluent.withPath("other")) == null + } + + def "verifyConnectionExpectations passes with no expectations"() { + expect: + RequestExpectations.verifyConnectionExpectations() + } + + def "Fluent.expectRequest registers expectation"() { + when: + RequestExpectations.Fluent.expectRequest(RequestMatcher.Fluent.withPath("accounts")) + + then: + RequestExpectations.getRequestExpectations().size() == 1 + } + + def "Fluent.stubRequest registers allowance"() { + when: + RequestExpectations.Fluent.stubRequest(RequestMatcher.Fluent.withPath("accounts")) + + then: + RequestExpectations.getRequestAllowances().size() == 1 + } + def "setupConnection"() { given: def connection = RequestExpectations.Fluent.setupConnection(new TestConnection()) diff --git a/testing/src/test/groovy/com/mx/path/testing/request/RequestMatcherTest.groovy b/testing/src/test/groovy/com/mx/path/testing/request/RequestMatcherTest.groovy new file mode 100644 index 00000000..731360f7 --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/request/RequestMatcherTest.groovy @@ -0,0 +1,104 @@ +package com.mx.path.testing.request + +import static org.mockito.Mockito.mock +import static org.mockito.Mockito.when + +import com.mx.path.core.common.connect.Request +import com.mx.path.testing.request.RequestMatcher + +import spock.lang.Specification + +class RequestMatcherTest extends Specification { + + def makeRequest(String path, String method = "GET", String baseUrl = "http://example.com") { + def req = mock(Request) + when(req.getPath()).thenReturn(path) + when(req.getMethod()).thenReturn(method) + when(req.getBaseUrl()).thenReturn(baseUrl) + return req + } + + def "withPath matches correct path"() { + given: + def matcher = RequestMatcher.Fluent.withPath("accounts") + + expect: + matcher.isMatch(makeRequest("accounts")) + !matcher.isMatch(makeRequest("transactions")) + } + + def "withMethod matches correct method"() { + given: + def matcher = RequestMatcher.Fluent.withMethod("POST") + + expect: + matcher.isMatch(makeRequest("accounts", "POST")) + !matcher.isMatch(makeRequest("accounts", "GET")) + } + + def "withPath and withMethod combined — both must match"() { + given: + def matcher = RequestMatcher.Fluent.withPath("accounts").withMethod("GET") + + expect: + matcher.isMatch(makeRequest("accounts", "GET")) + !matcher.isMatch(makeRequest("accounts", "POST")) + !matcher.isMatch(makeRequest("transactions", "GET")) + } + + def "withBaseUrl matches correct base URL"() { + given: + def matcher = new RequestMatcher().withBaseUrl("http://example.com") + + expect: + matcher.isMatch(makeRequest("accounts")) + !matcher.isMatch(makeRequest("accounts", "GET", "http://other.com")) + } + + def "with uses provided function matcher"() { + given: + def matcher = new RequestMatcher().with({ req -> req.getPath() == "accounts" } as java.util.function.Function) + + expect: + matcher.isMatch(makeRequest("accounts")) + !matcher.isMatch(makeRequest("other")) + } + + def "withMatcher uses provided function matcher"() { + given: + def matcher = new RequestMatcher().withMatcher({ req -> req.getMethod() == "DELETE" } as java.util.function.Function) + + expect: + matcher.isMatch(makeRequest("any", "DELETE")) + !matcher.isMatch(makeRequest("any", "GET")) + } + + def "Fluent.with uses provided function"() { + given: + def matcher = RequestMatcher.Fluent.with({ req -> req.getPath() == "accounts" } as java.util.function.Function) + + expect: + matcher.isMatch(makeRequest("accounts")) + } + + def "Fluent.withBaseUrl matches base URL"() { + given: + def matcher = RequestMatcher.Fluent.withBaseUrl("http://example.com") + + expect: + matcher.isMatch(makeRequest("accounts")) + } + + def "isMatch returns true when no assertions defined"() { + expect: + new RequestMatcher().isMatch(makeRequest("anything")) + } + + def "describe returns non-null string"() { + given: + def matcher = RequestMatcher.Fluent.withPath("accounts").withMethod("GET") + + expect: + matcher.describe() != null + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/request/TestRequestFilterTest.groovy b/testing/src/test/groovy/com/mx/path/testing/request/TestRequestFilterTest.groovy new file mode 100644 index 00000000..394b98bf --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/request/TestRequestFilterTest.groovy @@ -0,0 +1,101 @@ +package com.mx.path.testing.request + +import static org.mockito.Mockito.mock +import static org.mockito.Mockito.when + +import com.mx.path.core.common.connect.Request +import com.mx.path.core.common.connect.Response + +import org.spockframework.runtime.SpockAssertionError + +import spock.lang.Specification + +class TestRequestFilterTest extends Specification { + + def cleanup() { + RequestExpectations.reset() + } + + def makeRequest(String path = "accounts", String method = "GET") { + def req = mock(Request) + when(req.getPath()).thenReturn(path) + when(req.getMethod()).thenReturn(method) + when(req.getBaseUrl()).thenReturn("http://localhost") + return req + } + + def "execute invokes matching expectation handler"() { + given: + def handlerCalled = false + def filter = new TestRequestFilter() + def matcher = RequestMatcher.Fluent.withPath("accounts") + RequestExpectations.Fluent.expectRequest(matcher) + .toRespond({ req, resp -> handlerCalled = true }) + + when: + filter.execute(makeRequest("accounts"), mock(Response)) + + then: + handlerCalled + } + + def "execute throws when no handler registered"() { + given: + def filter = new TestRequestFilter() + + when: + filter.execute(makeRequest("unknown"), mock(Response)) + + then: + thrown(SpockAssertionError) + } + + def "execute throws when multiple handlers match"() { + given: + def filter = new TestRequestFilter() + RequestExpectations.Fluent.expectRequest(new RequestMatcher()) + .toRespond({ req, resp -> }) + RequestExpectations.Fluent.expectRequest(new RequestMatcher()) + .toRespond({ req, resp -> }) + + when: + filter.execute(makeRequest(), mock(Response)) + + then: + thrown(SpockAssertionError) + } + + def "describe returns empty string when no expectations"() { + given: + def filter = new TestRequestFilter() + + expect: + filter.describe() == "" + } + + def "describe includes expectation descriptions when set"() { + given: + def filter = new TestRequestFilter() + RequestExpectations.Fluent.expectRequest(RequestMatcher.Fluent.withPath("accounts")) + .toRespond({ req, resp -> }) + + when: + def desc = filter.describe() + + then: + desc.contains("accounts") + } + + def "allowance matcher also satisfies execute"() { + given: + def filter = new TestRequestFilter() + RequestExpectations.Fluent.stubRequest(RequestMatcher.Fluent.withPath("accounts")) + .toRespond({ req, resp -> }) + + when: + filter.execute(makeRequest("accounts"), mock(Response)) + + then: + noExceptionThrown() + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/session/TestEncryptionServiceTest.groovy b/testing/src/test/groovy/com/mx/path/testing/session/TestEncryptionServiceTest.groovy new file mode 100644 index 00000000..fd46bda1 --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/session/TestEncryptionServiceTest.groovy @@ -0,0 +1,52 @@ +package com.mx.path.testing.session + +import com.mx.path.core.common.collection.ObjectMap +import com.mx.path.testing.session.TestEncryptionService + +import spock.lang.Specification + +class TestEncryptionServiceTest extends Specification { + + TestEncryptionService subject + + def setup() { + subject = new TestEncryptionService(new ObjectMap()) + } + + def "encrypt returns plaintext unchanged"() { + expect: + subject.encrypt("secret") == "secret" + } + + def "decrypt returns ciphertext unchanged"() { + expect: + subject.decrypt("ciphertext") == "ciphertext" + } + + def "isEncrypted always returns true"() { + expect: + subject.isEncrypted("anything") + } + + def "getConfigurations returns set configurations"() { + given: + def configs = new ObjectMap() + configs.put("key", "value") + def svc = new TestEncryptionService(configs) + + expect: + svc.getConfigurations().get("key") == "value" + } + + def "setConfigurations updates configurations"() { + given: + def newConfigs = new ObjectMap() + newConfigs.put("updated", "true") + + when: + subject.setConfigurations(newConfigs) + + then: + subject.getConfigurations().get("updated") == "true" + } +} diff --git a/testing/src/test/groovy/com/mx/path/testing/session/TestSessionRepositoryTest.groovy b/testing/src/test/groovy/com/mx/path/testing/session/TestSessionRepositoryTest.groovy new file mode 100644 index 00000000..0a7b0f06 --- /dev/null +++ b/testing/src/test/groovy/com/mx/path/testing/session/TestSessionRepositoryTest.groovy @@ -0,0 +1,115 @@ +package com.mx.path.testing.session + +import com.mx.path.core.context.Session +import com.mx.path.testing.session.TestSessionRepository + +import spock.lang.Specification + +class TestSessionRepositoryTest extends Specification { + TestSessionRepository subject + Session session + + def setup() { + subject = new TestSessionRepository() + Session.setRepositorySupplier({ -> subject }) + session = new Session() + session.setId("test-session-id") + session.save() + } + + def cleanup() { + Session.clearSession() + Session.setRepositorySupplier(null) + } + + def "save and load round-trip"() { + given: + session.setUserId("user123") + session.save() + + when: + def loaded = subject.load("test-session-id") + + then: + loaded != null + loaded.getId() == "test-session-id" + } + + def "load returns null for unknown session id"() { + expect: + subject.load("unknown-id") == null + } + + def "saveValue and getValue"() { + when: + subject.saveValue(session, "myKey", "myValue") + + then: + subject.getValue(session, "myKey") == "myValue" + } + + def "getValue returns null for missing key"() { + expect: + subject.getValue(session, "nonexistent") == null + } + + def "deleteValue removes a stored value"() { + given: + subject.saveValue(session, "key", "val") + + when: + subject.deleteValue(session, "key") + + then: + subject.getValue(session, "key") == null + } + + def "delete removes the session"() { + when: + subject.delete(session) + + then: + subject.load("test-session-id") == null + } + + def "setIfNotExist stores value and returns true when key absent"() { + when: + def result = subject.setIfNotExist(session, "newKey", "val") + + then: + result + subject.getValue(session, "newKey") == "val" + } + + def "setIfNotExist returns false and does not overwrite when key present"() { + given: + subject.saveValue(session, "existingKey", "original") + + when: + def result = subject.setIfNotExist(session, "existingKey", "new") + + then: + !result + subject.getValue(session, "existingKey") == "original" + } + + def "setIfNotExist with expiry stores value when key absent"() { + when: + def result = subject.setIfNotExist(session, "ttlKey", "val", 60_000L) + + then: + result + subject.getValue(session, "ttlKey") == "val" + } + + def "setIfNotExist with expiry returns false when key present"() { + given: + subject.saveValue(session, "ttlKey", "original") + + when: + def result = subject.setIfNotExist(session, "ttlKey", "new", 60_000L) + + then: + !result + } +} diff --git a/utilities/gradle.lockfile b/utilities/gradle.lockfile index a3df75e7..90dd43fe 100644 --- a/utilities/gradle.lockfile +++ b/utilities/gradle.lockfile @@ -7,13 +7,16 @@ com.fasterxml.jackson.core:jackson-core:2.21.3=runtimeClasspath,testRuntimeClass com.fasterxml.jackson.core:jackson-databind:2.21.3=runtimeClasspath,testRuntimeClasspath com.fasterxml.jackson:jackson-bom:2.21.3=runtimeClasspath,testRuntimeClasspath com.github.oowekyala.ooxml:nice-xml-messages:3.1=pmd -com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.github.spotbugs:spotbugs:4.9.8=spotbugs +com.github.spotbugs:spotbugs-annotations:4.10.2=compileClasspath,spotbugs,testCompileClasspath +com.github.spotbugs:spotbugs-annotations:4.9.8=annotationProcessor,testAnnotationProcessor +com.github.spotbugs:spotbugs:4.10.2=spotbugs com.github.stephenc.jcip:jcip-annotations:1.0-1=spotbugs com.google.code.findbugs:jsr305:3.0.2=annotationProcessor,checkstyle,compileClasspath,spotbugs,testAnnotationProcessor,testCompileClasspath -com.google.code.gson:gson:2.13.2=pmd,spotbugs +com.google.code.gson:gson:2.13.2=pmd +com.google.code.gson:gson:2.14.0=spotbugs com.google.errorprone:error_prone_annotations:2.36.0=checkstyle -com.google.errorprone:error_prone_annotations:2.41.0=pmd,spotbugs +com.google.errorprone:error_prone_annotations:2.41.0=pmd +com.google.errorprone:error_prone_annotations:2.48.0=spotbugs com.google.guava:failureaccess:1.0.3=checkstyle com.google.guava:guava:33.4.8-jre=checkstyle com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=checkstyle @@ -22,10 +25,10 @@ com.puppycrawl.tools:checkstyle:10.25.0=checkstyle commons-beanutils:commons-beanutils:1.11.0=checkstyle commons-codec:commons-codec:1.15=checkstyle commons-collections:commons-collections:3.2.2=checkstyle -commons-io:commons-io:2.20.0=spotbugs +commons-io:commons-io:2.21.0=spotbugs info.picocli:picocli:4.7.7=checkstyle io.leangen.geantyref:geantyref:1.3.16=testRuntimeClasspath -jaxen:jaxen:2.0.0=spotbugs +jaxen:jaxen:2.0.6=spotbugs net.bytebuddy:byte-buddy-agent:1.17.7=testCompileClasspath,testRuntimeClasspath net.bytebuddy:byte-buddy:1.17.7=testCompileClasspath,testRuntimeClasspath net.sf.saxon:Saxon-HE:12.5=checkstyle @@ -35,19 +38,18 @@ net.sourceforge.pmd:pmd-core:7.22.0=pmd net.sourceforge.pmd:pmd-java:7.22.0=pmd org.antlr:antlr4-runtime:4.13.2=checkstyle org.antlr:antlr4-runtime:4.9.3=pmd -org.apache.bcel:bcel:6.11.0=spotbugs +org.apache.bcel:bcel:6.12.0=spotbugs org.apache.commons:commons-lang3:3.18.0=checkstyle -org.apache.commons:commons-lang3:3.19.0=spotbugs -org.apache.commons:commons-lang3:3.20.0=pmd -org.apache.commons:commons-text:1.14.0=spotbugs +org.apache.commons:commons-lang3:3.20.0=pmd,spotbugs +org.apache.commons:commons-text:1.15.0=spotbugs org.apache.commons:commons-text:1.3=checkstyle org.apache.httpcomponents.client5:httpclient5:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5-h2:5.1.3=checkstyle org.apache.httpcomponents.core5:httpcore5:5.1.3=checkstyle org.apache.httpcomponents:httpclient:4.5.13=checkstyle org.apache.httpcomponents:httpcore:4.4.14=checkstyle -org.apache.logging.log4j:log4j-api:2.25.3=spotbugs -org.apache.logging.log4j:log4j-core:2.25.3=spotbugs +org.apache.logging.log4j:log4j-api:2.26.0=spotbugs +org.apache.logging.log4j:log4j-core:2.26.0=spotbugs org.apache.maven.doxia:doxia-core:1.12.0=checkstyle org.apache.maven.doxia:doxia-logging-api:1.12.0=checkstyle org.apache.maven.doxia:doxia-module-xdoc:1.12.0=checkstyle @@ -72,24 +74,26 @@ org.jspecify:jspecify:1.0.0=checkstyle org.junit.jupiter:junit-jupiter-api:5.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-commons:1.14.0=testCompileClasspath,testRuntimeClasspath org.junit.platform:junit-platform-engine:1.14.0=testCompileClasspath,testRuntimeClasspath -org.junit:junit-bom:5.14.0=annotationProcessor,spotbugs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:5.14.0=annotationProcessor,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath +org.junit:junit-bom:6.1.0=spotbugs org.mockito:mockito-core:5.23.0=testCompileClasspath,testRuntimeClasspath org.objenesis:objenesis:3.3=testRuntimeClasspath org.opentest4j:opentest4j:1.3.0=testCompileClasspath,testRuntimeClasspath -org.ow2.asm:asm-analysis:9.9=spotbugs +org.ow2.asm:asm-analysis:9.10.1=spotbugs +org.ow2.asm:asm-commons:9.10.1=spotbugs org.ow2.asm:asm-commons:9.8=jacocoAnt -org.ow2.asm:asm-commons:9.9=spotbugs +org.ow2.asm:asm-tree:9.10.1=spotbugs org.ow2.asm:asm-tree:9.8=jacocoAnt -org.ow2.asm:asm-tree:9.9=spotbugs -org.ow2.asm:asm-util:9.9=spotbugs +org.ow2.asm:asm-util:9.10.1=spotbugs +org.ow2.asm:asm:9.10.1=spotbugs org.ow2.asm:asm:9.8=jacocoAnt -org.ow2.asm:asm:9.9=spotbugs org.ow2.asm:asm:9.9.1=pmd org.pcollections:pcollections:4.0.2=pmd org.projectlombok:lombok:1.18.42=annotationProcessor,compileClasspath,lombok,testAnnotationProcessor,testCompileClasspath org.reflections:reflections:0.10.2=checkstyle org.slf4j:jul-to-slf4j:1.7.36=pmd -org.slf4j:slf4j-api:2.0.17=spotbugs,spotbugsSlf4j +org.slf4j:slf4j-api:2.0.17=spotbugsSlf4j +org.slf4j:slf4j-api:2.0.18=spotbugs org.slf4j:slf4j-simple:2.0.17=spotbugsSlf4j org.spockframework:spock-bom:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath org.spockframework:spock-core:2.4-M6-groovy-3.0=testCompileClasspath,testRuntimeClasspath