Skip to content

Commit

Permalink
Make @Use on feature and fixture method parallel (#1691)
Browse files Browse the repository at this point in the history
For `@Use` on a specification same-thread policy is necessary, as the
whole spec execution is wrapped in a use-closure so that also helper methods
can use the category methods.

For `@Use` on features or fixture method, this is not necessary, 
as just the method invocation is wrapped in the use-closure,
and this is then always run within one thread.
  • Loading branch information
Vampire authored Feb 24, 2024
1 parent 16c657e commit f20866f
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ public void visitSpecAnnotations(List<Use> annotations, SpecInfo spec) {
@Override
public void visitFeatureAnnotations(List<Use> annotations, FeatureInfo feature) {
addInterceptor(annotations, feature.getFeatureMethod());
feature.setExecutionMode(ExecutionMode.SAME_THREAD);
}

@Override
Expand Down
75 changes: 69 additions & 6 deletions spock-specs/src/test/groovy/spock/util/mop/UseSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,15 @@

package spock.util.mop

import org.spockframework.EmbeddedSpecification
import org.spockframework.runtime.model.parallel.ExecutionMode
import spock.lang.Isolated
import spock.lang.Requires
import spock.lang.Specification

import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit

class UseOnMethods extends Specification {
// can be applied to a fixture method
@Use(StringExtensions)
Expand All @@ -32,12 +38,6 @@ class UseOnMethods extends Specification {
"foo".duplicate() == "foofoo"
}

@Use(StringExtensions)
def "sets feature execution mode to SAME_THREAD"() {
expect:
specificationContext.currentFeature.executionMode.get() == ExecutionMode.SAME_THREAD
}

@Use([StringExtensions, IntegerExtensions])
def "can use multiple categories"() {
expect:
Expand Down Expand Up @@ -83,6 +83,69 @@ class UseOnMethods extends Specification {
}
}

@Isolated("Isolate from other tests to have full access to cores for the embedded tests.")
@Requires({ Runtime.runtime.availableProcessors() >= 2 })
class IsolatedUseSpec extends EmbeddedSpecification {
def setup() {
runner.addClassImport(Use)
runner.addClassImport(CountDownLatch)
runner.addClassImport(StringExtensions)
runner.addClassImport(ExecutionMode)
runner.addClassImport(TimeUnit)
runner.configurationScript {
runner {
parallel {
enabled true
fixed(4)
}
}
}
}

def "executing iterations in parallel is prevented with annotated specification"() {
given:
runner.throwFailure = false

when:
def result = runner.runWithImports '''
@Use(StringExtensions)
class ASpec extends Specification {
def feature() {
expect:
specificationContext.currentSpec.childExecutionMode.orElse(null) == ExecutionMode.SAME_THREAD
}
}
'''

then:
result.testsSucceededCount == 1
}

def "executing iterations in parallel works with annotated feature"() {
when:
def result = runner.runSpecBody '''
@Shared
CountDownLatch latch = new CountDownLatch(2)
@Use(StringExtensions)
def feature() {
given:
latch.countDown()
expect:
latch.await(10, TimeUnit.SECONDS)
"foo".duplicate() == "foofoo"
where:
i << (1..2)
}
'''

then:
result.testsSucceededCount == 3
}
}

@Use(StringExtensions)
class UseOnClasses extends Specification {
// affects fixture methods
Expand Down

0 comments on commit f20866f

Please sign in to comment.