Skip to content

Commit

Permalink
Merge branch 'master' into vampire/fix-typo
Browse files Browse the repository at this point in the history
  • Loading branch information
szpak authored Oct 29, 2024
2 parents 6dc9e29 + 6007b17 commit b5b385d
Show file tree
Hide file tree
Showing 53 changed files with 1,277 additions and 157 deletions.
10 changes: 0 additions & 10 deletions .github/workflows/gradle-wrapper-validation.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .idea/copyright/ASLv2.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions build-logic/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pluginManagement {
}
}

rootProject.name = "build-logic"
rootProject.buildFileName = 'build-logic.gradle'

dependencyResolutionManagement {
Expand Down
23 changes: 18 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import java.time.Duration

import static org.spockframework.gradle.AsciiDocLinkVerifier.verifyAnchorlessCrossDocumentLinks
import static org.spockframework.gradle.AsciiDocLinkVerifier.verifyLinksAndAnchors

Expand Down Expand Up @@ -127,6 +129,9 @@ subprojects {
groovy {
srcDir "src/${ss.name}-groovy-le-$gv/groovy"
}
resources {
srcDir "src/${ss.name}-groovy-le-$gv/resources"
}
}
for (jv in javaVersions.findAll { javaVersion <= it }) {
java {
Expand All @@ -135,6 +140,9 @@ subprojects {
groovy {
srcDir "src/${ss.name}-java-le-$jv/groovy"
}
resources {
srcDir "src/${ss.name}-java-le-$jv/resources"
}
}
for (gv in variants.findAll { variant >= it }) {
java {
Expand All @@ -143,6 +151,9 @@ subprojects {
groovy {
srcDir "src/${ss.name}-groovy-ge-$gv/groovy"
}
resources {
srcDir "src/${ss.name}-groovy-ge-$gv/resources"
}
}
for (jv in javaVersions.findAll { javaVersion >= it }) {
java {
Expand All @@ -151,6 +162,9 @@ subprojects {
groovy {
srcDir "src/${ss.name}-java-ge-$jv/groovy"
}
resources {
srcDir "src/${ss.name}-java-ge-$jv/resources"
}
}
}

Expand Down Expand Up @@ -190,9 +204,8 @@ subprojects {
outputLocation = file("${outputLocation.get()}/$taskName-$variant")
}
}
//Required for building on Travis' container-based infrastructure to not be killed with
//'exit code 137' - https://github.com/travis-ci/travis-ci/issues/5582
jvmArgs '-Xmx512m'
// As a generous general timeout, instead of the 6h of GHA.
timeout = Duration.ofMinutes(15)
}

tasks.register("allDependencyInsight", DependencyInsightReportTask) {}
Expand All @@ -210,7 +223,7 @@ tasks.register("collectTestXml") {


doFirst {
def target = file("$buildDir/collected-test-results")
def target = layout.buildDirectory.dir("collected-test-results").get().asFile
target.mkdirs()
reportingProjects.each { rp ->
rp.tasks.withType(Test).each { testTask ->
Expand Down Expand Up @@ -242,7 +255,7 @@ tasks.register("codeCoverageReport", JacocoReport) {
reports {
html.required = true
xml.required = true
xml.outputLocation = file("${buildDir}/reports/jacoco/report.xml") // report must be here for codecov to pick it up
xml.outputLocation = layout.buildDirectory.file("reports/jacoco/report.xml") // report must be here for codecov to pick it up
csv.required = false
}
}
Expand Down
36 changes: 34 additions & 2 deletions docs/extensions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -311,8 +311,7 @@ def "I fail if I run for more than five seconds"() { ... }
def "I better be quick" { ... }
----

Applying `Timeout` to a spec class has the same effect as applying it to each feature that is not already annotated
with `Timeout`, excluding time spent in fixtures:
Applying `@Timeout` to a spec class has the same effect as applying it to each feature and fixture method that is not already annotated with `@Timeout`:

[source,groovy]
----
Expand All @@ -323,6 +322,11 @@ class TimedSpec extends Specification {
@Timeout(value = 250, unit = MILLISECONDS)
def "I fail much faster"() { ... }
def setup() { /* I have 10 seconds */}
@Timeout(value = 25, unit = SECONDS)
def cleanup() { /* I have 25 seconds */ }
}
----

Expand All @@ -337,6 +341,11 @@ the timeout was exceeded. Additionally, thread dumps can be captured and logged
include::{sourcedir}/timeout/TimeoutConfigurationDoc.groovy[tag=example]
----

Since Spock 2.4, you can also configure a global timeout via the configuration file.
This will apply to all features that are not already annotated with `@Timeout`.
Setting the global to non-null will have the same effect as applying `@Timeout` it to all features.
With the flag `applyGlobalTimeoutToFixtures` you can control if the global timeout should also be applied to fixture methods.

=== Retry

The `@Retry` extensions can be used for flaky integration tests, where remote systems can fail sometimes.
Expand Down Expand Up @@ -1345,3 +1354,26 @@ The extension generates the following output for the example code above.
----
include::{sourcedir}/extension/ExtensionStoreSpec.groovy[tag=example-result]
----


[[default-value-provider]]
=== Default Value Provider Extensions

Stubs use the `EmptyOrDummyResponse` to return a default value for a method call.
If the `EmptyOrDummyResponse` doesn't have specific instructions for a type it will return a new `Stub` for that type.
This works for most cases, but can lead to unexpected behavior if the type does have a behavioral contract that is not fulfilled by the `Stub`.
Another problematic case is when the type is `final` or `sealed` as those are not mockable by default.

To address these issues, Spock 2.4 introduces the `org.spockframework.runtime.extension.IDefaultValueProviderExtension` that is loaded via Java's `ServiceLoader` mechanism.
This extension allows you to provide a default value if the `EmptyOrDummyResponse` doesn't have specific instructions for a type.

.Example Implementation
[source,groovy,indent=0]
----
include::{sourcedir-java}/smoke/mock/MaybeDefaultValueProvider.java[tag=sample-implementation]
----

It is primarily for framework developers who want to provide a default value for their framework types.
Or users of a framework that doesn't provide default values for their special types.

If you want to change the default response behavior for `Stub` have a look at <<interaction_based_testing.adoc#ALaCarteMocks,A la Carte Mocks>> and how to use your own `org.spockframework.mock.IDefaultResponse`.
4 changes: 4 additions & 0 deletions docs/include.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
:github-base: https://github.com/spockframework/spock
:github-blob-base: {github-base}/blob
:commit-ish: master
// source java dir
:base-sourcedir-java: spock-specs/src/test/java/org/spockframework
:sourcedir-java: ../{base-sourcedir-java}
:github-sourcedir-java: {github-blob-base}/{commit-ish}/{base-sourcedir-java}
// source dir
:base-sourcedir: spock-specs/src/test/groovy/org/spockframework/docs
:sourcedir: ../{base-sourcedir}
Expand Down
14 changes: 12 additions & 2 deletions docs/release_notes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,21 @@ include::include.adoc[]
=== Highlights

* Add support for combining two or more data providers using cartesian product spockIssue:1062[]
* Add support for a `filter` block after a `where` block to filter out unwanted iterations
* Add support for a `filter` block after a `where` block to filter out unwanted iterations spockPull:1927[]

=== Misc

* Types constraints or arguments in interactions can now handle primitive types like `_ as int` spockIssue:1974[]
* Add `globalTimeout` to `@Timeout` extension, to apply a timeout to all features in a specification, configurable via the spock configuration file spockPull:1986[]
* Add new <<extensions.adoc#default-value-provider,`IDefaultValueProviderExtension`>> extension point to add support for special classes in the Stub's default `EmptyOrDummyResponse` spockPull:1994[]
* Add support for Groovy-4-style range expressions spockIssue:1956[]
* Improve `@Timeout` extension will now use virtual threads if available spockPull:1986[]
* Improve mock argument matching, types constraints or arguments in interactions can now handle primitive types like `_ as int` spockIssue:1974[]
* Support ContextClassLoader when loading optional classes via `ReflectionUtil` spockPull:1995[]
** This enables loading of optional classes in e.g. OSGi environments
* `EmbeddedSpecRunner` and `EmbeddedSpecCompiler` now support the construction with a custom `ClassLoader` spockPull:1988[]
** This allows the use of these classes in an OSGi environment, where the class imports in the embedded spec are not visible to the Spock OSGi bundle ClassLoader
* Fix mocking issue with the ByteBuddy MockMaker when using multiple classloaders in Java 21 spockIssue:2017[]
* Fix mocking of final classes via `@SpringBean` and `@SpringSpy` spockIssue:1960[]

== 2.4-M4 (2024-03-21)

Expand Down
16 changes: 8 additions & 8 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
asciidoctorj = '2.5.13'
groovy2 = '2.5.23'
groovy3 = '3.0.22'
groovy4 = '4.0.22'
groovy4 = '4.0.23'
jacoco = '0.8.12'
junit = '5.10.3'
asm = '9.7'
junit = '5.11.3'
asm = '9.7.1'
mockito4 = '4.11.0'
mockito5 = '5.12.0'
mockito5 = '5.14.2'

[libraries]
jetbrains-annotations = "org.jetbrains:annotations:24.1.0"
jetbrains-annotations = "org.jetbrains:annotations:26.0.1"
asciidoctorj = { module = "org.asciidoctor:asciidoctorj", version.ref = "asciidoctorj" }
asm = { module = "org.ow2.asm:asm", version.ref = "asm" }
asmUtil = { module = "org.ow2.asm:asm-util", version.ref = "asm" }
bytebuddy = "net.bytebuddy:byte-buddy:1.14.18"
bytebuddy = "net.bytebuddy:byte-buddy:1.15.5"
cglib = "cglib:cglib-nodep:3.3.0"
geantyref = "io.leangen.geantyref:geantyref:1.3.15"
geantyref = "io.leangen.geantyref:geantyref:1.3.16"
h2database = "com.h2database:h2:2.2.224"
hamcrest = "org.hamcrest:hamcrest:2.2"
hamcrest = "org.hamcrest:hamcrest:3.0"
jaxb = "javax.xml.bind:jaxb-api:2.3.1"
junit4 = "junit:junit:4.13.2"
log4j = "log4j:log4j:1.2.17"
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
4 changes: 2 additions & 2 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionSha256Sum=31c55713e40233a8303827ceb42ca48a47267a0ad4bab9177123121e71524c26
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
4 changes: 2 additions & 2 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ pluginManagement {
}

plugins {
id "com.gradle.develocity" version "3.17.6"
id "com.gradle.develocity" version "3.18.1"
id "com.gradle.common-custom-user-data-gradle-plugin" version "2.0.2"
id "org.asciidoctor.jvm.convert" version "4.0.2"
id "org.asciidoctor.jvm.convert" version "4.0.3"
id "net.nemerosa.versioning" version "3.1.0"
id "io.github.gradle-nexus.publish-plugin" version "2.0.0"
id "com.github.ben-manes.versions" version "0.51.0"
Expand Down
13 changes: 8 additions & 5 deletions spock-core/core.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ dependencies {
if (variant == 2.5) {
api projects.spockGroovy2Compat
}

implementation libs.geantyref

compileOnly libs.jetbrains.annotations
Expand Down Expand Up @@ -69,7 +69,10 @@ tasks.named("jar", Jar) {
'net.bytebuddy.*;resolution:=optional',
'net.sf.cglib.*;resolution:=optional',
'org.objectweb.asm.*;resolution:=optional',
'org.mockito.*;resolution:=optional',
/* We need to override the OSGi version for Mockito here, otherwise the version range would be [4.11,5)
* which would exclude Mockito 5 in the OSGi case.
*/
'org.mockito.*;resolution:=optional;version="[4.11,6)"',
'*'
].join(','),
'-noclassforname': 'true',
Expand All @@ -92,10 +95,10 @@ tasks.named("processResources") {

tasks.register("coreConsole", JavaExec) {
description = 'Start a groovy Console with Spock Core Classpath, useful for AST-Inspection'
main = variant == 2.5 ? "groovy.ui.Console" : "groovy.console.ui.Console"
mainClass = variant == 2.5 ? "groovy.ui.Console" : "groovy.console.ui.Console"
classpath(sourceSets.named("main").map {it.runtimeClasspath }, configurations.named("coreConsoleRuntime"))
workingDir = file('build/console')
ignoreExitValue = true
ignoreExitValue true
args file('CoreConsole.groovy').absolutePath
doFirst {
workingDir.mkdirs()
Expand All @@ -106,7 +109,7 @@ tasks.register("coreConsole", JavaExec) {
// task writes out the properties necessary for it to verify the OSGi
// metadata.
def osgiProperties = tasks.register('osgiProperties', WriteProperties) {
outputFile = layout.getBuildDirectory().file("verifyOSGiProperties.bndrun")
destinationFile = layout.getBuildDirectory().file("verifyOSGiProperties.bndrun")
property('-standalone', true)
property('-runee', "JavaSE-${javaVersion < 9 ? '1.' + javaVersion : javaVersion}")
property('-runrequires', "osgi.identity;filter:='(osgi.identity=${project.name})'")
Expand Down
29 changes: 27 additions & 2 deletions spock-core/src/main/groovy/spock/util/EmbeddedSpecCompiler.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,36 @@ class EmbeddedSpecCompiler {
final CompilerConfiguration compilerConfigurationWithImports = new CompilerConfiguration().tap {
it.addCompilationCustomizers(importCustomizer)
}
final GroovyClassLoader loaderWithImports = new GroovyClassLoader(getClass().classLoader, compilerConfigurationWithImports)
final GroovyClassLoader loader = new GroovyClassLoader(getClass().classLoader)
final GroovyClassLoader loaderWithImports
final GroovyClassLoader loader

boolean unwrapCompileException = true

/**
* Creates a new {@link EmbeddedSpecCompiler} with default settings using the Spock {@link ClassLoader} for resolving imports.
*/
EmbeddedSpecCompiler() {
//We can't use the new constructor EmbeddedSpecCompiler(ClassLoader) here, because we can't call this before super
//and someone could have subclassed the EmbeddedSpecCompiler with a different classloader,
//which would break the existing code, if we use "EmbeddedSpecCompiler.class.classLoader"
def classLoader = this.class.classLoader
this.loaderWithImports = new GroovyClassLoader(classLoader, compilerConfigurationWithImports)
this.loader = new GroovyClassLoader(classLoader)
}

/**
* Creates a new {@link EmbeddedSpecCompiler} with a custom classloader to load imports of the spec.
* Note: The classloader need to be able to load Spock classes.
*
* @param classLoader the ClassLoader to use to load the spec imports
* @since 2.4
*/
@Beta
EmbeddedSpecCompiler(ClassLoader classLoader) {
Objects.requireNonNull(classLoader)
this.loaderWithImports = new GroovyClassLoader(classLoader, compilerConfigurationWithImports)
this.loader = new GroovyClassLoader(classLoader)
}

void addPackageImport(String pkg) {
importCustomizer.addStarImports(pkg)
Expand Down
34 changes: 33 additions & 1 deletion spock-core/src/main/groovy/spock/util/EmbeddedSpecRunner.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass
*/
@NotThreadSafe
class EmbeddedSpecRunner {
private final EmbeddedSpecCompiler compiler = new EmbeddedSpecCompiler(unwrapCompileException: false)
private final EmbeddedSpecCompiler compiler

boolean throwFailure = true

Expand All @@ -50,6 +50,38 @@ class EmbeddedSpecRunner {
List<Class> configClasses = []
boolean inheritParentExtensions = true

/**
* Creates a new {@link EmbeddedSpecRunner} with a default {@link EmbeddedSpecCompiler}.
*/
EmbeddedSpecRunner() {
this(new EmbeddedSpecCompiler())
this.compiler.unwrapCompileException = false
}

/**
* Creates a new {@link EmbeddedSpecRunner} with a custom classloader to load imports of the spec.
* Note: The classloader need to be able to load Spock classes.
*
* @param classLoader the ClassLoader to use to load the spec imports
* @since 2.4
*/
@Beta
EmbeddedSpecRunner(ClassLoader classLoader) {
this(new EmbeddedSpecCompiler(classLoader))
this.compiler.unwrapCompileException = false
}

/**
* Creates a new {@link EmbeddedSpecRunner} with a custom {@link EmbeddedSpecCompiler}.
*
* @param compiler the compiler to use
* @since 2.4
*/
@Beta
EmbeddedSpecRunner(EmbeddedSpecCompiler compiler) {
this.compiler = Objects.requireNonNull(compiler)
}

void configurationScript(Closure configurationScript) {
this.configurationScript = configurationScript
}
Expand Down
Loading

0 comments on commit b5b385d

Please sign in to comment.